Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52181f877a | ||
|
|
d636cd1444 | ||
|
|
62a0dc57b1 | ||
|
|
a2861d75eb | ||
|
|
c05b270edc | ||
|
|
f7d56943fd | ||
|
|
4c2943df23 | ||
|
|
8fb08b68cc | ||
|
|
75cfe1dc69 | ||
|
|
eaeb7f00b5 | ||
|
|
e8a7f5d3ce | ||
|
|
812e8f2a16 | ||
|
|
d1327738c2 | ||
|
|
b01c1c679f | ||
|
|
2387d574cb | ||
|
|
34a1a37246 | ||
|
|
8eda16c9f6 | ||
|
|
b8ec4b0fd6 | ||
|
|
654cb9d439 | ||
|
|
096714d1b8 | ||
|
|
f57ac7b09e | ||
|
|
9007701670 | ||
|
|
e962f07d19 | ||
|
|
6c92ba774e | ||
|
|
857e608b51 | ||
|
|
4d611ca405 | ||
|
|
01f5b5d918 | ||
|
|
28309520c0 | ||
|
|
068cc18927 | ||
|
|
132a1ad291 | ||
|
|
8e590a1af3 | ||
|
|
4d156854fe | ||
|
|
9f4d71f48d | ||
|
|
01e8384000 | ||
|
|
c55d2e7ba3 | ||
|
|
36d0bc2617 | ||
|
|
c7c1ba3a19 | ||
|
|
734eff70b8 | ||
|
|
621adde3b2 | ||
|
|
9038579ab2 | ||
|
|
8e16b872e5 | ||
|
|
45c9fbd6d9 | ||
|
|
944e2e9e12 | ||
|
|
674534a700 | ||
|
|
4156060ca4 | ||
|
|
95e2b430ea | ||
|
|
b26818fe73 | ||
|
|
aeb86b109a | ||
|
|
06d5e5ff5a | ||
|
|
837ff9d206 | ||
|
|
1166782eb7 | ||
|
|
9af909bf35 | ||
|
|
018df9c9b1 | ||
|
|
b0592024e2 | ||
|
|
f547dca9e3 | ||
|
|
a4c0c27410 | ||
|
|
344f942573 | ||
|
|
81276c4ee4 | ||
|
|
bc400ed13b | ||
|
|
c601622aa7 | ||
|
|
6810dd6191 | ||
|
|
d8970199f8 | ||
|
|
e79dbb8074 | ||
|
|
af80f6dfac | ||
|
|
3968160a91 | ||
|
|
176a543dde | ||
|
|
d2c48042e6 | ||
|
|
b878bd08dd | ||
|
|
d06c15cc89 | ||
|
|
f3800ba073 | ||
|
|
cdb9481e38 | ||
|
|
c0eb6c9c81 | ||
|
|
015985c1f9 | ||
|
|
f46a3603c9 | ||
|
|
286394aa9b | ||
|
|
c96535f67e | ||
|
|
3e9572bfa9 | ||
|
|
f1bf281715 | ||
|
|
c6ca65ab78 | ||
|
|
61d912f3ff | ||
|
|
a6a7f08eaf | ||
|
|
a371df534d | ||
|
|
b3af1873a0 | ||
|
|
b5c98fbfd0 | ||
|
|
e498bb64b6 | ||
|
|
a38601f05a | ||
|
|
ef2c836955 | ||
|
|
5fe974261b | ||
|
|
2841c79e87 | ||
|
|
43d463eccb | ||
|
|
5029ebce2f | ||
|
|
b31df043a0 | ||
|
|
80d6ccea79 | ||
|
|
fce4df3ab7 | ||
|
|
a968099038 | ||
|
|
d605f482c7 | ||
|
|
a30febaeeb | ||
|
|
58adb1059f | ||
|
|
bc601bdc6d | ||
|
|
b13a9207f9 | ||
|
|
78056a3e9c | ||
|
|
ab3625cffd | ||
|
|
904d4da239 | ||
|
|
ed38b645db | ||
|
|
b84274da0f | ||
|
|
c63081623f | ||
|
|
eb6b199038 | ||
|
|
4c4149452c | ||
|
|
9719fd616c | ||
|
|
33dabc8c80 | ||
|
|
327cf6fac1 | ||
|
|
6453f8158f | ||
|
|
4baecdf72a | ||
|
|
1bc77ee174 | ||
|
|
3f5737afd7 | ||
|
|
21bb78e908 | ||
|
|
6a0638048a | ||
|
|
61025d5b7d | ||
|
|
ff0be17cf7 | ||
|
|
cb47871a0a | ||
|
|
b114477f2a | ||
|
|
23b5ee1236 | ||
|
|
bfbef51afb | ||
|
|
81f1f76479 | ||
|
|
2953d45a0f | ||
|
|
1d70bc3ba9 | ||
|
|
f8178ec74e | ||
|
|
5d900ff747 | ||
|
|
69baaee3e4 | ||
|
|
3e1e49d775 | ||
|
|
9ef732f653 | ||
|
|
c4a40dbf65 | ||
|
|
bee9e5f38c | ||
|
|
4107b734bd | ||
|
|
585b5a1039 | ||
|
|
f837326f11 | ||
|
|
3d673f3275 | ||
|
|
5f228f8db2 | ||
|
|
a892e25374 | ||
|
|
b758250eb1 | ||
|
|
0fd322f812 | ||
|
|
9ad7ea44ec | ||
|
|
2536771134 | ||
|
|
a8db4bd3fe | ||
|
|
785331acbd | ||
|
|
579f3d7794 | ||
|
|
ac098c7f5f | ||
|
|
610a81ecf9 | ||
|
|
cc669006dc | ||
|
|
af3531ee35 | ||
|
|
58bcc328a4 | ||
|
|
ee130a9889 | ||
|
|
5922f4e2ae | ||
|
|
09caa4d800 | ||
|
|
450feb0f95 | ||
|
|
83b51e9f88 | ||
|
|
b85f7d7790 | ||
|
|
a17fe4c9e5 | ||
|
|
41ad46f1a9 | ||
|
|
82d5a9870e | ||
|
|
de0499f7fa | ||
|
|
a48e32ca50 | ||
|
|
a821aee3b1 | ||
|
|
6996804d05 | ||
|
|
d86c7ad458 | ||
|
|
bef61221a3 | ||
|
|
203aac5bc6 | ||
|
|
a880ca239b | ||
|
|
13fddac46d | ||
|
|
e31e7ca9ed | ||
|
|
6c9b023f3e | ||
|
|
fb6901b2c0 | ||
|
|
8ac2831f3d | ||
|
|
1e01560b83 | ||
|
|
058da605cb | ||
|
|
f8e9bec73a | ||
|
|
8f56fa2f58 | ||
|
|
9563fb4bfc | ||
|
|
30c26ab726 | ||
|
|
fbdd30d68e | ||
|
|
aafe97b67d | ||
|
|
526ec646b7 | ||
|
|
9703a59121 | ||
|
|
885476fb5b | ||
|
|
2fa4f2e246 | ||
|
|
2c6b14ed22 | ||
|
|
3d346579d8 | ||
|
|
36d2dfd846 | ||
|
|
4765929271 | ||
|
|
70802cde6d | ||
|
|
4b8185c7fc | ||
|
|
50b9c41196 | ||
|
|
59a7116cc2 | ||
|
|
094c000904 | ||
|
|
f86d4bd1d5 | ||
|
|
5f6ca3c6ce | ||
|
|
90c0462d63 | ||
|
|
bdeb4786b5 | ||
|
|
c45dec12c5 | ||
|
|
10a3d4dca9 | ||
|
|
824aaa695f | ||
|
|
c5d70b7dbb | ||
|
|
48a6427d22 | ||
|
|
7a1fde2957 | ||
|
|
462918560c | ||
|
|
f871b5144e | ||
|
|
e649fad7aa | ||
|
|
bfcd5b81d7 | ||
|
|
1a90133b15 | ||
|
|
947548c24f | ||
|
|
641e594309 | ||
|
|
d5910a5d94 | ||
|
|
1d0c1707d1 | ||
|
|
1dfe37fea9 | ||
|
|
ce388fe4d2 | ||
|
|
a63aaaa2cc | ||
|
|
dbc8a59a0a | ||
|
|
50c634b86e | ||
|
|
7231ea72a8 | ||
|
|
cf7d601bf5 | ||
|
|
d7d89513d6 | ||
|
|
0827edeace | ||
|
|
72a3fbc0e4 | ||
|
|
56261001ea | ||
|
|
816a3f47c7 | ||
|
|
cdc8ae2e9b | ||
|
|
00679da22b | ||
|
|
95624b77e4 | ||
|
|
de58910b5a | ||
|
|
882ceb86bc | ||
|
|
56682a7709 | ||
|
|
04325cbc2f | ||
|
|
fb13d757af | ||
|
|
425ce5547c | ||
|
|
f00407b640 | ||
|
|
6625f3b390 | ||
|
|
dca73db30c | ||
|
|
dcc6c7e9ae | ||
|
|
440f390cba | ||
|
|
7186a50775 | ||
|
|
44f77b5c71 | ||
|
|
b25d7eacf2 | ||
|
|
2b4491d81a | ||
|
|
5333e41ab3 | ||
|
|
8ea219d8c6 | ||
|
|
1290933d19 | ||
|
|
e5811e5520 | ||
|
|
f5cbee988b | ||
|
|
d97605ad85 | ||
|
|
7ac2052dbc | ||
|
|
d0f5ba36fb | ||
|
|
0c7668cd06 | ||
|
|
6b053b9f60 | ||
|
|
041bc0bdb7 | ||
|
|
20f9ff7e53 | ||
|
|
e55da9e963 | ||
|
|
11e73576bb | ||
|
|
0dd3588acc | ||
|
|
186ded6d91 | ||
|
|
5740eb6769 | ||
|
|
0a3fa6f909 | ||
|
|
20aa1b455c | ||
|
|
0033bb4785 | ||
|
|
19b75b6ecb | ||
|
|
8cd423a659 | ||
|
|
60796e76b0 | ||
|
|
f52a7d8faa | ||
|
|
4c0540da1c | ||
|
|
91ffc8d256 | ||
|
|
45139e9fd5 | ||
|
|
18fbcddd0c | ||
|
|
787b76904a | ||
|
|
ea3b81f02c | ||
|
|
0594e8135b | ||
|
|
18d3a97d43 | ||
|
|
79827a179f | ||
|
|
13cc7c610e | ||
|
|
9ad3f31d33 | ||
|
|
95dfd48143 | ||
|
|
3da3dc2f45 | ||
|
|
1e08c49f75 | ||
|
|
2bb5eec711 | ||
|
|
44ae395b3e | ||
|
|
03026c3b1d | ||
|
|
8930c3c79b | ||
|
|
8b7fa49590 | ||
|
|
dce9a09772 | ||
|
|
515c506b4c | ||
|
|
d0a3f25697 | ||
|
|
c9d674b60d | ||
|
|
97d3d28dab | ||
|
|
820af1e078 | ||
|
|
4b0024a97d | ||
|
|
be3bd70c57 | ||
|
|
2e8c19f6a3 | ||
|
|
a36d9302ce | ||
|
|
7ad7ba3178 | ||
|
|
9f9630f455 | ||
|
|
0c86d23467 | ||
|
|
eb3a7a3827 | ||
|
|
6efce7c9ca | ||
|
|
f4abba02ba | ||
|
|
54e9412ddd | ||
|
|
19ca3fbc03 | ||
|
|
0c53c5ad4a | ||
|
|
5261a288d1 | ||
|
|
3d7377b874 | ||
|
|
a96e67af6c | ||
|
|
4c870b70fc | ||
|
|
dbaa7042d9 | ||
|
|
f9513115e4 | ||
|
|
ae7380d2af | ||
|
|
e1a799e5de | ||
|
|
9c071664ad | ||
|
|
32a98bafdc | ||
|
|
77d9109c27 | ||
|
|
482b84f07b | ||
|
|
1e4dc2e5f1 | ||
|
|
a17369c7dc | ||
|
|
b26c53b0d0 | ||
|
|
197a5737c8 | ||
|
|
21616d8a77 | ||
|
|
5c1148a6a5 | ||
|
|
cdb3e7af2f | ||
|
|
1951c1b3a0 | ||
|
|
894bbda44c | ||
|
|
188c748208 | ||
|
|
723418f8d8 | ||
|
|
4a9e0502e6 | ||
|
|
2b7120ec71 | ||
|
|
2ff9249810 | ||
|
|
fb756156f5 | ||
|
|
fafa322456 | ||
|
|
1a6f2b4f7f | ||
|
|
79463a65e9 | ||
|
|
a940e78f16 | ||
|
|
501eb25102 | ||
|
|
429987c9a6 | ||
|
|
2179ce00e1 | ||
|
|
03e040a966 | ||
|
|
7ebd897157 | ||
|
|
64bb6640f2 | ||
|
|
6cf253fb52 | ||
|
|
cafc3b1bcb | ||
|
|
324e9654d3 | ||
|
|
32fed9c7be | ||
|
|
800c87fed0 | ||
|
|
a3538bbc6f | ||
|
|
c823237d7b | ||
|
|
ea031f4ea2 | ||
|
|
54fa31f03b | ||
|
|
cee31bbd25 | ||
|
|
b8701102e0 | ||
|
|
8c3ba44ada | ||
|
|
07e047873e | ||
|
|
f75ad2edcf | ||
|
|
6b2f26791e | ||
|
|
2888c62e85 | ||
|
|
5e220bf4b5 | ||
|
|
31ba3f7e64 | ||
|
|
54bd39abdf | ||
|
|
4909a341db | ||
|
|
2a6aa6be5f | ||
|
|
a1394399b4 | ||
|
|
281c7970ac | ||
|
|
1828c2619c | ||
|
|
bd2740f347 | ||
|
|
ae087ec4bb | ||
|
|
4fa585aee3 | ||
|
|
6ff9d5e881 | ||
|
|
f8745ae095 | ||
|
|
62c0dd7aff | ||
|
|
c5be47c8c1 | ||
|
|
1cd61ea862 | ||
|
|
260ff2f6b7 | ||
|
|
de7e3be7fa | ||
|
|
7b6a8840c5 | ||
|
|
f8c8796dfe | ||
|
|
fe82637069 | ||
|
|
b174809fcc | ||
|
|
9448a3790d | ||
|
|
f9e4f89252 | ||
|
|
a2f492f2b3 | ||
|
|
282000d88b | ||
|
|
97d1de3d22 | ||
|
|
8b2210411a | ||
|
|
23c73fe3e2 | ||
|
|
6746de8dd6 | ||
|
|
c1a862385f | ||
|
|
bad7ed161a | ||
|
|
663c55eba0 | ||
|
|
142076ceae | ||
|
|
787a72cdfe | ||
|
|
226cdffd69 | ||
|
|
889a492784 | ||
|
|
acbd6c0341 | ||
|
|
1a279ae85a | ||
|
|
77ef7847f7 |
+4
-26
@@ -1,33 +1,14 @@
|
||||
version: 2
|
||||
|
||||
references:
|
||||
# Install the dependencies required for tests.
|
||||
# Add the step "- *install-dependencies" to the beginning of your job to run
|
||||
# this command.
|
||||
install-dependencies: &install-dependencies
|
||||
run:
|
||||
name: Install dependencies
|
||||
# TODO: We can split these dependencies up by job to reduce installation
|
||||
# time.
|
||||
command: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get -y -qq update
|
||||
sudo apt-get -y install \
|
||||
gcc-multilib-powerpc-linux-gnu gcc-arm-linux-gnueabi \
|
||||
libc6-dev-armel-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
|
||||
libc6-dev-ppc64-powerpc-cross zstd gzip coreutils \
|
||||
libcurl4-openssl-dev
|
||||
|
||||
jobs:
|
||||
# the first half of the jobs are in this test
|
||||
short-tests-0:
|
||||
# TODO: Create a small custom docker image with all the dependencies we need
|
||||
# preinstalled to reduce installation time.
|
||||
docker:
|
||||
- image: circleci/buildpack-deps:bionic
|
||||
- image: fbopensource/zstd-circleci-primary:0.0.1
|
||||
steps:
|
||||
- checkout
|
||||
- *install-dependencies
|
||||
- run:
|
||||
name: Test
|
||||
command: |
|
||||
@@ -41,10 +22,9 @@ jobs:
|
||||
# the second half of the jobs are in this test
|
||||
short-tests-1:
|
||||
docker:
|
||||
- image: circleci/buildpack-deps:bionic
|
||||
- image: fbopensource/zstd-circleci-primary:0.0.1
|
||||
steps:
|
||||
- checkout
|
||||
- *install-dependencies
|
||||
- run:
|
||||
name: Test
|
||||
command: |
|
||||
@@ -61,12 +41,11 @@ jobs:
|
||||
# tagged release.
|
||||
publish-github-release:
|
||||
docker:
|
||||
- image: circleci/buildpack-deps:bionic
|
||||
- image: fbopensource/zstd-circleci-primary:0.0.1
|
||||
environment:
|
||||
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
|
||||
steps:
|
||||
- checkout
|
||||
- *install-dependencies
|
||||
- run:
|
||||
name: Publish
|
||||
command: |
|
||||
@@ -86,12 +65,11 @@ jobs:
|
||||
# This step should only be run in a cron job
|
||||
regression-test:
|
||||
docker:
|
||||
- image: circleci/buildpack-deps:bionic
|
||||
- image: fbopensource/zstd-circleci-primary:0.0.1
|
||||
environment:
|
||||
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
|
||||
steps:
|
||||
- checkout
|
||||
- *install-dependencies
|
||||
# Restore the cached resources.
|
||||
- restore_cache:
|
||||
# We try our best to bust the cache when the data changes by hashing
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
FROM circleci/buildpack-deps:bionic
|
||||
|
||||
RUN sudo dpkg --add-architecture i386
|
||||
RUN sudo apt-get -y -qq update
|
||||
RUN sudo apt-get -y install \
|
||||
gcc-multilib-powerpc-linux-gnu gcc-arm-linux-gnueabi \
|
||||
libc6-dev-armel-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
|
||||
libc6-dev-ppc64-powerpc-cross zstd gzip coreutils \
|
||||
libcurl4-openssl-dev
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
env:
|
||||
CIRRUS_CLONE_DEPTH: 1
|
||||
ARCH: amd64
|
||||
|
||||
task:
|
||||
freebsd_instance:
|
||||
matrix:
|
||||
image: freebsd-12-0-release-amd64
|
||||
image: freebsd-11-2-release-amd64
|
||||
install_script:
|
||||
- sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf
|
||||
- pkg upgrade -y
|
||||
- pkg install -y gmake coreutils
|
||||
script: |
|
||||
MOREFLAGS="-Werror" gmake -j all
|
||||
gmake shortest
|
||||
+3
-2
@@ -14,7 +14,7 @@
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
zstd
|
||||
/zstd
|
||||
zstdmt
|
||||
*.exe
|
||||
*.out
|
||||
@@ -22,7 +22,7 @@ zstdmt
|
||||
|
||||
# Test artefacts
|
||||
tmp*
|
||||
dictionary*
|
||||
dictionary.
|
||||
NUL
|
||||
|
||||
# Build artefacts
|
||||
@@ -41,3 +41,4 @@ _zstdbench/
|
||||
.DS_Store
|
||||
googletest/
|
||||
*.d
|
||||
*.vscode
|
||||
|
||||
+31
-13
@@ -2,7 +2,6 @@
|
||||
|
||||
language: c
|
||||
dist: trusty
|
||||
sudo: required
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
@@ -154,6 +153,12 @@ matrix:
|
||||
- make clean
|
||||
- make travis-install # just ensures `make install` works
|
||||
|
||||
- name: c99 compatibility
|
||||
if: branch = master
|
||||
script:
|
||||
- make c99build
|
||||
- make -C tests test-zstd
|
||||
|
||||
- name: PPC64
|
||||
if: branch = master
|
||||
script:
|
||||
@@ -179,23 +184,36 @@ matrix:
|
||||
|
||||
# meson dedicated test
|
||||
- name: Xenial (Meson + clang)
|
||||
# env: ALLOW_FAILURES=true
|
||||
dist: xenial
|
||||
language: cpp
|
||||
compiler: clang
|
||||
before_install:
|
||||
install:
|
||||
- sudo apt-get install -qq liblz4-dev valgrind tree
|
||||
- curl -o ~/get-pip.py 'https://bootstrap.pypa.io/get-pip.py'
|
||||
- python3 ~/get-pip.py --user
|
||||
- pip3 install --user meson ninja
|
||||
- |
|
||||
travis_retry curl -o ~/ninja.zip -L 'https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip' &&
|
||||
unzip ~/ninja.zip -d ~/.local/bin
|
||||
- |
|
||||
travis_retry curl -o ~/get-pip.py -L 'https://bootstrap.pypa.io/get-pip.py' &&
|
||||
python3 ~/get-pip.py --user &&
|
||||
pip3 install --user meson
|
||||
script:
|
||||
- meson --buildtype=debug
|
||||
-Db_lundef=false
|
||||
-Dauto_features=enabled
|
||||
-Dbuild_{programs,tests,contrib}=true
|
||||
-Ddefault_library=both
|
||||
build/meson builddir
|
||||
- cd builddir
|
||||
- |
|
||||
meson setup \
|
||||
--buildtype=debugoptimized \
|
||||
-Db_lundef=false \
|
||||
-Dauto_features=enabled \
|
||||
-Dbin_programs=true \
|
||||
-Dbin_tests=true \
|
||||
-Dbin_contrib=true \
|
||||
-Ddefault_library=both \
|
||||
build/meson builddir
|
||||
- pushd builddir
|
||||
- ninja
|
||||
- meson test --verbose --no-rebuild
|
||||
- DESTDIR=./staging ninja install
|
||||
- tree ./staging
|
||||
after_failure:
|
||||
- cat "$TRAVIS_BUILD_DIR"/builddir/meson-logs/testlog.txt
|
||||
allow_failures:
|
||||
- name: Xenial (Meson + clang)
|
||||
- env: ALLOW_FAILURES=true
|
||||
|
||||
@@ -1,3 +1,70 @@
|
||||
v1.4.1
|
||||
bug: Fix data corruption in niche use cases by @terrelln (#1659)
|
||||
bug: Fuzz legacy modes, fix uncovered bugs by @terrelln (#1593, #1594, #1595)
|
||||
bug: Fix out of bounds read by @terrelln (#1590)
|
||||
perf: Improve decode speed by ~7% @mgrice (#1668)
|
||||
perf: Slightly improved compression ratio of level 3 and 4 (ZSTD_dfast) by @cyan4973 (#1681)
|
||||
perf: Slightly faster compression speed when re-using a context by @cyan4973 (#1658)
|
||||
perf: Improve compression ratio for small windowLog by @cyan4973 (#1624)
|
||||
perf: Faster compression speed in high compression mode for repetitive data by @terrelln (#1635)
|
||||
api: Add parameter to generate smaller dictionaries by @tyler-tran (#1656)
|
||||
cli: Recognize symlinks when built in C99 mode by @felixhandte (#1640)
|
||||
cli: Expose cpu load indicator for each file on -vv mode by @ephiepark (#1631)
|
||||
cli: Restrict read permissions on destination files by @chungy (#1644)
|
||||
cli: zstdgrep: handle -f flag by @felixhandte (#1618)
|
||||
cli: zstdcat: follow symlinks by @vejnar (#1604)
|
||||
doc: Remove extra size limit on compressed blocks by @felixhandte (#1689)
|
||||
doc: Fix typo by @yk-tanigawa (#1633)
|
||||
doc: Improve documentation on streaming buffer sizes by @cyan4973 (#1629)
|
||||
build: CMake: support building with LZ4 @leeyoung624 (#1626)
|
||||
build: CMake: install zstdless and zstdgrep by @leeyoung624 (#1647)
|
||||
build: CMake: respect existing uninstall target by @j301scott (#1619)
|
||||
build: Make: skip multithread tests when built without support by @michaelforney (#1620)
|
||||
build: Make: Fix examples/ test target by @sjnam (#1603)
|
||||
build: Meson: rename options out of deprecated namespace by @lzutao (#1665)
|
||||
build: Meson: fix build by @lzutao (#1602)
|
||||
build: Visual Studio: don't export symbols in static lib by @scharan (#1650)
|
||||
build: Visual Studio: fix linking by @absotively (#1639)
|
||||
build: Fix MinGW-W64 build by @myzhang1029 (#1600)
|
||||
misc: Expand decodecorpus coverage by @ephiepark (#1664)
|
||||
|
||||
v1.4.0
|
||||
perf: Improve level 1 compression speed in most scenarios by 6% by @gbtucker and @terrelln
|
||||
api: Move the advanced API, including all functions in the staging section, to the stable section
|
||||
api: Make ZSTD_e_flush and ZSTD_e_end block for maximum forward progress
|
||||
api: Rename ZSTD_CCtxParam_getParameter to ZSTD_CCtxParams_getParameter
|
||||
api: Rename ZSTD_CCtxParam_setParameter to ZSTD_CCtxParams_setParameter
|
||||
api: Don't export ZSTDMT functions from the shared library by default
|
||||
api: Require ZSTD_MULTITHREAD to be defined to use ZSTDMT
|
||||
api: Add ZSTD_decompressBound() to provide an upper bound on decompressed size by @shakeelrao
|
||||
api: Fix ZSTD_decompressDCtx() corner cases with a dictionary
|
||||
api: Move ZSTD_getDictID_*() functions to the stable section
|
||||
api: Add ZSTD_c_literalCompressionMode flag to enable or disable literal compression by @terrelln
|
||||
api: Allow compression parameters to be set when a dictionary is used
|
||||
api: Allow setting parameters before or after ZSTD_CCtx_loadDictionary() is called
|
||||
api: Fix ZSTD_estimateCStreamSize_usingCCtxParams()
|
||||
api: Setting ZSTD_d_maxWindowLog to 0 means use the default
|
||||
cli: Ensure that a dictionary is not used to compress itself by @shakeelrao
|
||||
cli: Add --[no-]compress-literals flag to enable or disable literal compression
|
||||
doc: Update the examples to use the advanced API
|
||||
doc: Explain how to transition from old streaming functions to the advanced API in the header
|
||||
build: Improve the Windows release packages
|
||||
build: Improve CMake build by @hjmjohnson
|
||||
build: Build fixes for FreeBSD by @lwhsu
|
||||
build: Remove redundant warnings by @thatsafunnyname
|
||||
build: Fix tests on OpenBSD by @bket
|
||||
build: Extend fuzzer build system to work with the new clang engine
|
||||
build: CMake now creates the libzstd.so.1 symlink
|
||||
build: Improve Menson build by @lzutao
|
||||
misc: Fix symbolic link detection on FreeBSD
|
||||
misc: Use physical core count for -T0 on FreeBSD by @cemeyer
|
||||
misc: Fix zstd --list on truncated files by @kostmo
|
||||
misc: Improve logging in debug mode by @felixhandte
|
||||
misc: Add CirrusCI tests by @lwhsu
|
||||
misc: Optimize dictionary memory usage in corner cases
|
||||
misc: Improve the dictionary builder on small or homogeneous data
|
||||
misc: Fix spelling across the repo by @jsoref
|
||||
|
||||
v1.3.8
|
||||
perf: better decompression speed on large files (+7%) and cold dictionaries (+15%)
|
||||
perf: slightly better compression ratio at high compression modes
|
||||
@@ -239,7 +306,7 @@ v1.0.0
|
||||
Change Licensing, all project is now BSD, Copyright Facebook
|
||||
Small decompression speed improvement
|
||||
API : Streaming API supports legacy format
|
||||
API : ZDICT_getDictID(), ZSTD_sizeof_{CCtx, DCtx, CStream, DStream}(), ZSTD_setDStreamParamter()
|
||||
API : ZDICT_getDictID(), ZSTD_sizeof_{CCtx, DCtx, CStream, DStream}(), ZSTD_setDStreamParameter()
|
||||
CLI supports legacy formats v0.4+
|
||||
Fixed : compression fails on certain huge files, reported by Jesse McGrew
|
||||
Enhanced documentation, by Przemyslaw Skibinski
|
||||
|
||||
@@ -156,7 +156,7 @@ list:
|
||||
done \
|
||||
} | column -t -s $$'\t'
|
||||
|
||||
.PHONY: install clangtest armtest usan asan uasan
|
||||
.PHONY: install armtest usan asan uasan
|
||||
install:
|
||||
@$(MAKE) -C $(ZSTDDIR) $@
|
||||
@$(MAKE) -C $(PRGDIR) $@
|
||||
@@ -188,7 +188,7 @@ gcc7build: clean
|
||||
.PHONY: clangbuild
|
||||
clangbuild: clean
|
||||
clang -v
|
||||
CXX=clang++ CC=clang $(MAKE) all MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation"
|
||||
CXX=clang++ CC=clang CFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation" $(MAKE) all
|
||||
|
||||
m32build: clean
|
||||
gcc -v
|
||||
@@ -232,10 +232,6 @@ gcc6test: clean
|
||||
gcc-6 -v
|
||||
$(MAKE) all CC=gcc-6 MOREFLAGS="-Werror"
|
||||
|
||||
clangtest: clean
|
||||
clang -v
|
||||
$(MAKE) all CXX=clang++ CC=clang MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation"
|
||||
|
||||
armtest: clean
|
||||
$(MAKE) -C $(TESTDIR) datagen # use native, faster
|
||||
$(MAKE) -C $(TESTDIR) test CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS="-Werror -static" FUZZER_FLAGS=--no-big-tests
|
||||
|
||||
@@ -14,6 +14,7 @@ a list of known ports and bindings is provided on [Zstandard homepage](http://ww
|
||||
[![Build Status][travisDevBadge]][travisLink]
|
||||
[![Build status][AppveyorDevBadge]][AppveyorLink]
|
||||
[![Build status][CircleDevBadge]][CircleLink]
|
||||
[![Build status][CirrusDevBadge]][CirrusLink]
|
||||
|
||||
[travisDevBadge]: https://travis-ci.org/facebook/zstd.svg?branch=dev "Continuous Integration test suite"
|
||||
[travisLink]: https://travis-ci.org/facebook/zstd
|
||||
@@ -21,14 +22,16 @@ a list of known ports and bindings is provided on [Zstandard homepage](http://ww
|
||||
[AppveyorLink]: https://ci.appveyor.com/project/YannCollet/zstd-p0yf0
|
||||
[CircleDevBadge]: https://circleci.com/gh/facebook/zstd/tree/dev.svg?style=shield "Short test suite"
|
||||
[CircleLink]: https://circleci.com/gh/facebook/zstd
|
||||
[CirrusDevBadge]: https://api.cirrus-ci.com/github/facebook/zstd.svg?branch=dev
|
||||
[CirrusLink]: https://cirrus-ci.com/github/facebook/zstd
|
||||
|
||||
## Benchmarks
|
||||
|
||||
For reference, several fast compression algorithms were tested and compared
|
||||
on a server running Linux Debian (`Linux version 4.14.0-3-amd64`),
|
||||
with a Core i7-6700K CPU @ 4.0GHz,
|
||||
on a server running Arch Linux (`Linux version 5.0.5-arch1-1`),
|
||||
with a Core i9-9900K CPU @ 5.0GHz,
|
||||
using [lzbench], an open-source in-memory benchmark by @inikep
|
||||
compiled with [gcc] 7.3.0,
|
||||
compiled with [gcc] 8.2.1,
|
||||
on the [Silesia compression corpus].
|
||||
|
||||
[lzbench]: https://github.com/inikep/lzbench
|
||||
@@ -37,14 +40,14 @@ on the [Silesia compression corpus].
|
||||
|
||||
| Compressor name | Ratio | Compression| Decompress.|
|
||||
| --------------- | ------| -----------| ---------- |
|
||||
| **zstd 1.3.4 -1** | 2.877 | 470 MB/s | 1380 MB/s |
|
||||
| zlib 1.2.11 -1 | 2.743 | 110 MB/s | 400 MB/s |
|
||||
| brotli 1.0.2 -0 | 2.701 | 410 MB/s | 430 MB/s |
|
||||
| quicklz 1.5.0 -1 | 2.238 | 550 MB/s | 710 MB/s |
|
||||
| lzo1x 2.09 -1 | 2.108 | 650 MB/s | 830 MB/s |
|
||||
| lz4 1.8.1 | 2.101 | 750 MB/s | 3700 MB/s |
|
||||
| snappy 1.1.4 | 2.091 | 530 MB/s | 1800 MB/s |
|
||||
| lzf 3.6 -1 | 2.077 | 400 MB/s | 860 MB/s |
|
||||
| **zstd 1.4.0 -1** | 2.884 | 530 MB/s | 1360 MB/s |
|
||||
| zlib 1.2.11 -1 | 2.743 | 110 MB/s | 440 MB/s |
|
||||
| brotli 1.0.7 -0 | 2.701 | 430 MB/s | 470 MB/s |
|
||||
| quicklz 1.5.0 -1 | 2.238 | 600 MB/s | 800 MB/s |
|
||||
| lzo1x 2.09 -1 | 2.106 | 680 MB/s | 950 MB/s |
|
||||
| lz4 1.8.3 | 2.101 | 800 MB/s | 4220 MB/s |
|
||||
| snappy 1.1.4 | 2.073 | 580 MB/s | 2020 MB/s |
|
||||
| lzf 3.6 -1 | 2.077 | 440 MB/s | 930 MB/s |
|
||||
|
||||
[zlib]: http://www.zlib.net/
|
||||
[LZ4]: http://www.lz4.org/
|
||||
|
||||
@@ -29,3 +29,5 @@ compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
build
|
||||
lib
|
||||
!cmake/lib
|
||||
!meson/lib
|
||||
|
||||
@@ -408,6 +408,10 @@
|
||||
RelativePath="..\..\..\programs\util.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\programs\timefn.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib\compress\zstd_fast.c"
|
||||
>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
@@ -121,7 +121,7 @@
|
||||
EnableIntrinsicFunctions="true"
|
||||
OmitFramePointers="true"
|
||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
@@ -195,7 +195,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
@@ -272,7 +272,7 @@
|
||||
EnableIntrinsicFunctions="true"
|
||||
OmitFramePointers="true"
|
||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\programs"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
@@ -332,6 +332,10 @@
|
||||
RelativePath="..\..\..\programs\util.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\programs\timefn.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\programs\datagen.c"
|
||||
>
|
||||
|
||||
@@ -336,6 +336,10 @@
|
||||
RelativePath="..\..\..\programs\util.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\programs\timefn.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\programs\benchfn.c"
|
||||
>
|
||||
|
||||
@@ -167,6 +167,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\lib\common\xxhash.c" />
|
||||
<ClCompile Include="..\..\..\programs\util.c" />
|
||||
<ClCompile Include="..\..\..\programs\timefn.c" />
|
||||
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||
<ClCompile Include="..\..\..\programs\benchfn.c" />
|
||||
<ClCompile Include="..\..\..\tests\fullbench.c" />
|
||||
|
||||
@@ -156,7 +156,6 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
||||
<ClCompile Include="..\..\..\programs\util.c" />
|
||||
<ClCompile Include="..\..\..\lib\common\debug.c" />
|
||||
<ClCompile Include="..\..\..\lib\common\fse_decompress.c" />
|
||||
<ClCompile Include="..\..\..\lib\common\zstd_common.c" />
|
||||
@@ -178,6 +177,8 @@
|
||||
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
||||
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress_block.c" />
|
||||
<ClCompile Include="..\..\..\lib\decompress\zstd_ddict.c" />
|
||||
<ClCompile Include="..\..\..\programs\util.c" />
|
||||
<ClCompile Include="..\..\..\programs\timefn.c" />
|
||||
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||
<ClCompile Include="..\..\..\programs\benchfn.c" />
|
||||
<ClCompile Include="..\..\..\tests\fullbench.c" />
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
</ClCompile>
|
||||
@@ -105,7 +105,7 @@
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
</ClCompile>
|
||||
@@ -122,7 +122,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@@ -142,7 +142,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@@ -182,6 +182,7 @@
|
||||
<ClCompile Include="..\..\..\lib\dictBuilder\divsufsort.c" />
|
||||
<ClCompile Include="..\..\..\lib\dictBuilder\zdict.c" />
|
||||
<ClCompile Include="..\..\..\programs\util.c" />
|
||||
<ClCompile Include="..\..\..\programs\timefn.c" />
|
||||
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||
<ClCompile Include="..\..\..\tests\fuzzer.c" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -209,7 +209,6 @@
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AssemblerOutput>All</AssemblerOutput>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -234,7 +233,6 @@
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AssemblerOutput>All</AssemblerOutput>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
||||
@@ -90,31 +90,26 @@
|
||||
<ProjectGuid>{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>libzstd</RootNamespace>
|
||||
<TargetName>libzstd_static</TargetName>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -134,35 +129,36 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetName>libzstd_static</TargetName>
|
||||
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetName>libzstd_static</TargetName>
|
||||
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>libzstd_static</TargetName>
|
||||
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>libzstd_static</TargetName>
|
||||
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
@@ -182,7 +178,7 @@
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
@@ -202,11 +198,10 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AssemblerOutput>All</AssemblerOutput>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -224,14 +219,13 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AssemblerOutput>All</AssemblerOutput>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
<ClCompile Include="..\..\..\lib\legacy\zstd_v06.c" />
|
||||
<ClCompile Include="..\..\..\lib\legacy\zstd_v07.c" />
|
||||
<ClCompile Include="..\..\..\programs\util.c" />
|
||||
<ClCompile Include="..\..\..\programs\timefn.c" />
|
||||
<ClCompile Include="..\..\..\programs\benchfn.c" />
|
||||
<ClCompile Include="..\..\..\programs\benchzstd.c" />
|
||||
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||
|
||||
@@ -7,17 +7,57 @@
|
||||
# in the COPYING file in the root directory of this source tree).
|
||||
# ################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.9)
|
||||
|
||||
project(zstd)
|
||||
set(ZSTD_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..")
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "No build type selected, defaulting to Release")
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
cmake_minimum_required(VERSION 2.8.9 FATAL_ERROR)
|
||||
|
||||
# As of 2018-12-26 ZSTD has been validated to build with cmake version 3.13.2 new policies.
|
||||
# Set and use the newest cmake policies that are validated to work
|
||||
set(ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION "3")
|
||||
set(ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION "13") #Policies never changed at PATCH level
|
||||
if("${CMAKE_MAJOR_VERSION}" LESS 3)
|
||||
set(ZSTD_CMAKE_POLICY_VERSION "${CMAKE_VERSION}")
|
||||
elseif( "${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}" EQUAL "${CMAKE_MAJOR_VERSION}" AND
|
||||
"${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}" GREATER "${CMAKE_MINOR_VERSION}")
|
||||
set(ZSTD_CMAKE_POLICY_VERSION "${CMAKE_VERSION}")
|
||||
else()
|
||||
set(ZSTD_CMAKE_POLICY_VERSION "${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}.${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}.0")
|
||||
endif()
|
||||
cmake_policy(VERSION ${ZSTD_CMAKE_POLICY_VERSION})
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
|
||||
set(ZSTD_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..")
|
||||
set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib)
|
||||
# Parse version
|
||||
include(GetZstdLibraryVersion)
|
||||
GetZstdLibraryVersion(${LIBRARY_DIR}/zstd.h zstd_VERSION_MAJOR zstd_VERSION_MINOR zstd_VERSION_PATCH)
|
||||
|
||||
if( CMAKE_MAJOR_VERSION LESS 3 )
|
||||
## Provide cmake 3+ behavior for older versions of cmake
|
||||
project(zstd)
|
||||
set(PROJECT_VERSION_MAJOR ${zstd_VERSION_MAJOR})
|
||||
set(PROJECT_VERSION_MINOR ${zstd_VERSION_MINOR})
|
||||
set(PROJECT_VERSION_PATCH ${zstd_VERSION_PATCH})
|
||||
set(PROJECT_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}")
|
||||
enable_language(C) # Main library is in C
|
||||
enable_language(CXX) # Testing contributed code also utilizes CXX
|
||||
else()
|
||||
project(zstd
|
||||
VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}"
|
||||
LANGUAGES C # Main library is in C
|
||||
CXX # Testing contributed code also utilizes CXX
|
||||
)
|
||||
endif()
|
||||
message(STATUS "ZSTD VERSION: ${zstd_VERSION}")
|
||||
set(zstd_HOMEPAGE_URL "http://www.zstd.net")
|
||||
set(zstd_DESCRIPTION "Zstandard is a real-time compression algorithm, providing high compression ratios.")
|
||||
|
||||
# Set a default build type if none was specified
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to 'Release' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
|
||||
# Set the possible values of build type for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@@ -50,9 +50,11 @@ macro(ADD_ZSTD_COMPILATION_FLAGS)
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
separate_arguments(${flag_var})
|
||||
list(REMOVE_DUPLICATES ${flag_var})
|
||||
string(REPLACE ";" " " ${flag_var} "${${flag_var}}")
|
||||
if( ${flag_var} )
|
||||
separate_arguments(${flag_var})
|
||||
list(REMOVE_DUPLICATES ${flag_var})
|
||||
string(REPLACE ";" " " ${flag_var} "${${flag_var}}")
|
||||
endif()
|
||||
endforeach ()
|
||||
|
||||
if (MSVC AND ZSTD_USE_STATIC_RUNTIME)
|
||||
@@ -60,7 +62,9 @@ macro(ADD_ZSTD_COMPILATION_FLAGS)
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
if ( ${flag_var} )
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
endif()
|
||||
endforeach ()
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# Find LibLZ4
|
||||
#
|
||||
# Find LibLZ4 headers and library
|
||||
#
|
||||
# Result Variables
|
||||
#
|
||||
# LIBLZ4_FOUND - True if lz4 is found
|
||||
# LIBLZ4_INCLUDE_DIRS - lz4 headers directories
|
||||
# LIBLZ4_LIBRARIES - lz4 libraries
|
||||
# LIBLZ4_VERSION_MAJOR - The major version of lz4
|
||||
# LIBLZ4_VERSION_MINOR - The minor version of lz4
|
||||
# LIBLZ4_VERSION_RELEASE - The release version of lz4
|
||||
# LIBLZ4_VERSION_STRING - version number string (e.g. 1.8.3)
|
||||
#
|
||||
# Hints
|
||||
#
|
||||
# Set ``LZ4_ROOT_DIR`` to the directory of lz4.h and lz4 library
|
||||
|
||||
set(_LIBLZ4_ROOT_HINTS
|
||||
ENV LZ4_ROOT_DIR)
|
||||
|
||||
find_path( LIBLZ4_INCLUDE_DIR lz4.h
|
||||
HINTS ${_LIBLZ4_ROOT_HINTS})
|
||||
find_library( LIBLZ4_LIBRARY NAMES lz4 liblz4 liblz4_static
|
||||
HINTS ${_LIBLZ4_ROOT_HINTS})
|
||||
|
||||
if(LIBLZ4_INCLUDE_DIR)
|
||||
file(STRINGS "${LIBLZ4_INCLUDE_DIR}/lz4.h" LIBLZ4_HEADER_CONTENT REGEX "#define LZ4_VERSION_[A-Z]+ +[0-9]+")
|
||||
|
||||
string(REGEX REPLACE ".*#define LZ4_VERSION_MAJOR +([0-9]+).*" "\\1" LIBLZ4_VERSION_MAJOR "${LIBLZ4_HEADER_CONTENT}")
|
||||
string(REGEX REPLACE ".*#define LZ4_VERSION_MINOR +([0-9]+).*" "\\1" LIBLZ4_VERSION_MINOR "${LIBLZ4_HEADER_CONTENT}")
|
||||
string(REGEX REPLACE ".*#define LZ4_VERSION_RELEASE +([0-9]+).*" "\\1" LIBLZ4_VERSION_RELEASE "${LIBLZ4_HEADER_CONTENT}")
|
||||
|
||||
set(LIBLZ4_VERSION_STRING "${LIBLZ4_VERSION_MAJOR}.${LIBLZ4_VERSION_MINOR}.${LIBLZ4_VERSION_RELEASE}")
|
||||
unset(LIBLZ4_HEADER_CONTENT)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibLZ4 REQUIRED_VARS LIBLZ4_INCLUDE_DIR
|
||||
LIBLZ4_LIBRARY
|
||||
VERSION_VAR LIBLZ4_VERSION_STRING
|
||||
FAIL_MESSAGE "Could NOT find LZ4, try to set the paths to lz4.h and lz4 library in environment variable LZ4_ROOT_DIR")
|
||||
|
||||
if (LIBLZ4_FOUND)
|
||||
set(LIBLZ4_LIBRARIES ${LIBLZ4_LIBRARY})
|
||||
set(LIBLZ4_INCLUDE_DIRS ${LIBLZ4_INCLUDE_DIR})
|
||||
endif ()
|
||||
|
||||
mark_as_advanced( LIBLZ4_INCLUDE_DIR LIBLZ4_LIBRARY )
|
||||
@@ -1,9 +1,10 @@
|
||||
function(GetZstdLibraryVersion _header _major _minor _release)
|
||||
function(GetZstdLibraryVersion _header _major _minor _patch)
|
||||
# Read file content
|
||||
file(READ ${_header} CONTENT)
|
||||
|
||||
string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" VERSION_REGEX "${CONTENT}")
|
||||
set(${_major} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
set(${_minor} ${CMAKE_MATCH_2} PARENT_SCOPE)
|
||||
set(${_release} ${CMAKE_MATCH_3} PARENT_SCOPE)
|
||||
set(${_patch} ${CMAKE_MATCH_3} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
+40
-1
@@ -3,7 +3,46 @@
|
||||
Contributions to the cmake build configurations are welcome. Please
|
||||
use case sensitivity that matches modern (ie. cmake version 2.6 and above)
|
||||
conventions of using lower-case for commands, and upper-case for
|
||||
varibles.
|
||||
variables.
|
||||
|
||||
# How to build
|
||||
|
||||
As cmake doesn't support command like `cmake clean`, it's recommanded to perform a "out of source build".
|
||||
To do this, you can create a new directory and build in it:
|
||||
```sh
|
||||
cd build/cmake
|
||||
mkdir builddir
|
||||
cd builddir
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
Then you can clean all cmake caches by simpily delete the new directory:
|
||||
```sh
|
||||
rm -rf build/cmake/builddir
|
||||
```
|
||||
|
||||
And of course, you can directly build in build/cmake:
|
||||
```sh
|
||||
cd build/cmake
|
||||
cmake
|
||||
make
|
||||
```
|
||||
|
||||
To show cmake build options, you can:
|
||||
```sh
|
||||
cd build/cmake/builddir
|
||||
cmake -LH ..
|
||||
```
|
||||
|
||||
Bool options can be set to ON/OFF with -D\[option\]=\[ON/OFF\]. You can configure cmake options like this:
|
||||
```sh
|
||||
cd build/cmake/builddir
|
||||
cmake -DZSTD_BUILD_TESTS=ON -DZSTD_LEGACY_SUPPORT=ON ..
|
||||
make
|
||||
```
|
||||
|
||||
## referring
|
||||
[Looking for a 'cmake clean' command to clear up CMake output](https://stackoverflow.com/questions/9680420/looking-for-a-cmake-clean-command-to-clear-up-cmake-output)
|
||||
|
||||
# CMake Style Recommendations
|
||||
|
||||
|
||||
@@ -18,14 +18,8 @@ if(NOT ZSTD_BUILD_SHARED AND NOT ZSTD_BUILD_STATIC)
|
||||
endif()
|
||||
|
||||
# Define library directory, where sources and header files are located
|
||||
set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib)
|
||||
include_directories(${LIBRARY_DIR} ${LIBRARY_DIR}/common)
|
||||
|
||||
# Parse version
|
||||
include(GetZstdLibraryVersion)
|
||||
GetZstdLibraryVersion(${LIBRARY_DIR}/zstd.h LIBVER_MAJOR LIBVER_MINOR LIBVER_RELEASE)
|
||||
message(STATUS "ZSTD VERSION ${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}")
|
||||
|
||||
set(Sources
|
||||
${LIBRARY_DIR}/common/entropy_common.c
|
||||
${LIBRARY_DIR}/common/fse_decompress.c
|
||||
@@ -155,7 +149,8 @@ if (ZSTD_BUILD_SHARED)
|
||||
libzstd_shared
|
||||
PROPERTIES
|
||||
OUTPUT_NAME zstd
|
||||
SOVERSION ${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE})
|
||||
VERSION ${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}
|
||||
SOVERSION ${zstd_VERSION_MAJOR})
|
||||
endif ()
|
||||
|
||||
if (ZSTD_BUILD_STATIC)
|
||||
@@ -170,7 +165,7 @@ if (UNIX)
|
||||
set(PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||
set(LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
set(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
|
||||
set(VERSION "${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}")
|
||||
set(VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}")
|
||||
add_custom_target(libzstd.pc ALL
|
||||
${CMAKE_COMMAND} -DIN="${LIBRARY_DIR}/libzstd.pc.in" -DOUT="libzstd.pc"
|
||||
-DPREFIX="${PREFIX}" -DLIBDIR="${LIBDIR}" -DINCLUDEDIR="${INCLUDEDIR}" -DVERSION="${VERSION}"
|
||||
@@ -199,10 +194,12 @@ if (ZSTD_BUILD_STATIC)
|
||||
endif ()
|
||||
|
||||
# uninstall target
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
if (NOT TARGET uninstall)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
add_custom_target(uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
add_custom_target(uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
endif ()
|
||||
|
||||
@@ -26,7 +26,7 @@ if (MSVC)
|
||||
set(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstd.rc)
|
||||
endif ()
|
||||
|
||||
add_executable(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${PlatformDependResources})
|
||||
add_executable(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${PlatformDependResources})
|
||||
target_link_libraries(zstd libzstd_static)
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
||||
target_link_libraries(zstd rt)
|
||||
@@ -38,6 +38,8 @@ if (UNIX)
|
||||
add_custom_target(unzstd ALL ${CMAKE_COMMAND} -E create_symlink zstd unzstd DEPENDS zstd COMMENT "Creating unzstd symlink")
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdcat DESTINATION "bin")
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/unzstd DESTINATION "bin")
|
||||
install(PROGRAMS ${PROGRAMS_DIR}/zstdgrep DESTINATION "bin")
|
||||
install(PROGRAMS ${PROGRAMS_DIR}/zstdless DESTINATION "bin")
|
||||
|
||||
add_custom_target(zstd.1 ALL
|
||||
${CMAKE_COMMAND} -E copy ${PROGRAMS_DIR}/zstd.1 .
|
||||
@@ -63,7 +65,7 @@ if (UNIX)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdgrep.1 DESTINATION "${MAN_INSTALL_DIR}")
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdless.1 DESTINATION "${MAN_INSTALL_DIR}")
|
||||
|
||||
add_executable(zstd-frugal ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/fileio.c)
|
||||
add_executable(zstd-frugal ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/fileio.c)
|
||||
target_link_libraries(zstd-frugal libzstd_static)
|
||||
set_property(TARGET zstd-frugal APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_NOBENCH;ZSTD_NODICT")
|
||||
endif ()
|
||||
@@ -83,7 +85,9 @@ endif ()
|
||||
|
||||
option(ZSTD_ZLIB_SUPPORT "ZLIB SUPPORT" OFF)
|
||||
option(ZSTD_LZMA_SUPPORT "LZMA SUPPORT" OFF)
|
||||
option(ZSTD_LZ4_SUPPORT "LZ4 SUPPORT" OFF)
|
||||
|
||||
# Add gzip support
|
||||
if (ZSTD_ZLIB_SUPPORT)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
@@ -96,6 +100,7 @@ if (ZSTD_ZLIB_SUPPORT)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Add lzma support
|
||||
if (ZSTD_LZMA_SUPPORT)
|
||||
find_package(LibLZMA REQUIRED)
|
||||
|
||||
@@ -107,3 +112,16 @@ if (ZSTD_LZMA_SUPPORT)
|
||||
message(SEND_ERROR "lzma library is missing")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Add lz4 support
|
||||
if (ZSTD_LZ4_SUPPORT)
|
||||
find_package(LibLZ4 REQUIRED)
|
||||
|
||||
if (LIBLZ4_FOUND)
|
||||
include_directories(${LIBLZ4_INCLUDE_DIRS})
|
||||
target_link_libraries(zstd ${LIBLZ4_LIBRARIES})
|
||||
set_property(TARGET zstd APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_LZ4COMPRESS;ZSTD_LZ4DECOMPRESS")
|
||||
else ()
|
||||
message(SEND_ERROR "lz4 library is missing")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
@@ -43,13 +43,13 @@ include_directories(${TESTS_DIR} ${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/c
|
||||
add_executable(datagen ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/datagencli.c)
|
||||
target_link_libraries(datagen libzstd_static)
|
||||
|
||||
add_executable(fullbench ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${TESTS_DIR}/fullbench.c)
|
||||
add_executable(fullbench ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${TESTS_DIR}/fullbench.c)
|
||||
target_link_libraries(fullbench libzstd_static)
|
||||
|
||||
add_executable(fuzzer ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${TESTS_DIR}/fuzzer.c)
|
||||
add_executable(fuzzer ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/fuzzer.c)
|
||||
target_link_libraries(fuzzer libzstd_static)
|
||||
|
||||
if (UNIX)
|
||||
add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${TESTS_DIR}/paramgrill.c)
|
||||
add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/paramgrill.c)
|
||||
target_link_libraries(paramgrill libzstd_static m) #m is math library
|
||||
endif ()
|
||||
|
||||
@@ -7,7 +7,7 @@ modern software development tools and practices, such as unit tests,
|
||||
coverage reports, Valgrind, CCache and the like.
|
||||
|
||||
This Meson build system is provided with no guarantee and maintained
|
||||
by Dima Krasner <dima@dimakrasner.com>.
|
||||
by Dima Krasner \<dima@dimakrasner.com\>.
|
||||
|
||||
It outputs one `libzstd`, either shared or static, depending on
|
||||
`default_library` option.
|
||||
@@ -17,7 +17,7 @@ It outputs one `libzstd`, either shared or static, depending on
|
||||
`cd` to this meson directory (`build/meson`)
|
||||
|
||||
```sh
|
||||
meson --buildtype=release -D with-contrib=true -D with-tests=true -D with-contrib=true builddir
|
||||
meson setup -Dbin_programs=true -Dbin_contrib=true builddir
|
||||
cd builddir
|
||||
ninja # to build
|
||||
ninja install # to install
|
||||
|
||||
@@ -17,6 +17,7 @@ gen_html_includes = include_directories(join_paths(zstd_rootdir, 'programs'),
|
||||
gen_html = executable('gen_html',
|
||||
join_paths(zstd_rootdir, 'contrib/gen_html/gen_html.cpp'),
|
||||
include_directories: gen_html_includes,
|
||||
native: true,
|
||||
install: false)
|
||||
|
||||
# Update zstd manual
|
||||
|
||||
@@ -98,7 +98,7 @@ if use_debug
|
||||
if cc_id == compiler_gcc or cc_id == compiler_clang
|
||||
libzstd_debug_cflags = ['-Wstrict-aliasing=1', '-Wswitch-enum',
|
||||
'-Wdeclaration-after-statement', '-Wstrict-prototypes',
|
||||
'-Wundef', '-Wpointer-arith', '-Wformat-security', '-Wvla',
|
||||
'-Wundef', '-Wpointer-arith', '-Wvla',
|
||||
'-Wformat=2', '-Winit-self', '-Wfloat-equal', '-Wwrite-strings',
|
||||
'-Wredundant-decls', '-Wmissing-prototypes', '-Wc++-compat']
|
||||
endif
|
||||
@@ -116,9 +116,9 @@ libzstd = library('zstd',
|
||||
libzstd_dep = declare_dependency(link_with: libzstd,
|
||||
include_directories: libzstd_includes)
|
||||
|
||||
pkgconfig.generate(name: 'libzstd',
|
||||
pkgconfig.generate(libzstd,
|
||||
name: 'libzstd',
|
||||
filebase: 'libzstd',
|
||||
libraries: [libzstd],
|
||||
description: 'fast lossless compression algorithm library',
|
||||
version: zstd_libversion,
|
||||
url: 'http://www.zstd.net/')
|
||||
|
||||
+15
-16
@@ -11,10 +11,12 @@
|
||||
project('zstd',
|
||||
['c', 'cpp'],
|
||||
license: ['BSD', 'GPLv2'],
|
||||
default_options : ['c_std=c99',
|
||||
default_options : [
|
||||
'c_std=gnu99',
|
||||
'cpp_std=c++11',
|
||||
'buildtype=release'],
|
||||
version: '1.3.8',
|
||||
'buildtype=release'
|
||||
],
|
||||
version: 'DUMMY',
|
||||
meson_version: '>=0.47.0')
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
@@ -41,13 +43,10 @@ zstd_h_file = join_paths(meson.current_source_dir(), '../../lib/zstd.h')
|
||||
GetZstdLibraryVersion_py = files('GetZstdLibraryVersion.py')
|
||||
r = run_command(python3, GetZstdLibraryVersion_py, zstd_h_file)
|
||||
if r.returncode() == 0
|
||||
output = r.stdout().strip()
|
||||
if output.version_compare('>@0@'.format(zstd_version))
|
||||
zstd_version = output
|
||||
message('Project version is now: @0@'.format(zstd_version))
|
||||
endif
|
||||
zstd_version = r.stdout().strip()
|
||||
message('Project version is now: @0@'.format(zstd_version))
|
||||
else
|
||||
message('Cannot find project version in @0@'.format(zstd_h_file))
|
||||
error('Cannot find project version in @0@'.format(zstd_h_file))
|
||||
endif
|
||||
|
||||
zstd_libversion = zstd_version
|
||||
@@ -76,9 +75,9 @@ legacy_level = get_option('legacy_level')
|
||||
use_backtrace = get_option('backtrace')
|
||||
use_static_runtime = get_option('static_runtime')
|
||||
|
||||
build_programs = get_option('build_programs')
|
||||
build_contrib = get_option('build_contrib')
|
||||
build_tests = get_option('build_tests')
|
||||
bin_programs = get_option('bin_programs')
|
||||
bin_contrib = get_option('bin_contrib')
|
||||
bin_tests = get_option('bin_tests')
|
||||
|
||||
feature_multi_thread = get_option('multi_thread')
|
||||
feature_zlib = get_option('zlib')
|
||||
@@ -89,7 +88,7 @@ feature_lz4 = get_option('lz4')
|
||||
# Dependencies
|
||||
# =============================================================================
|
||||
|
||||
libm_dep = cc.find_library('m', required: build_tests)
|
||||
libm_dep = cc.find_library('m', required: bin_tests)
|
||||
thread_dep = dependency('threads', required: feature_multi_thread)
|
||||
use_multi_thread = thread_dep.found()
|
||||
# Arguments in dependency should be equivalent to those passed to pkg-config
|
||||
@@ -134,14 +133,14 @@ endif
|
||||
|
||||
subdir('lib')
|
||||
|
||||
if build_programs
|
||||
if bin_programs
|
||||
subdir('programs')
|
||||
endif
|
||||
|
||||
if build_tests
|
||||
if bin_tests
|
||||
subdir('tests')
|
||||
endif
|
||||
|
||||
if build_contrib
|
||||
if bin_contrib
|
||||
subdir('contrib')
|
||||
endif
|
||||
|
||||
@@ -19,11 +19,11 @@ option('backtrace', type: 'boolean', value: false,
|
||||
option('static_runtime', type: 'boolean', value: false,
|
||||
description: 'Link to static run-time libraries on MSVC')
|
||||
|
||||
option('build_programs', type: 'boolean', value: true,
|
||||
option('bin_programs', type: 'boolean', value: true,
|
||||
description: 'Enable programs build')
|
||||
option('build_tests', type: 'boolean', value: false,
|
||||
option('bin_tests', type: 'boolean', value: false,
|
||||
description: 'Enable tests build')
|
||||
option('build_contrib', type: 'boolean', value: false,
|
||||
option('bin_contrib', type: 'boolean', value: false,
|
||||
description: 'Enable contrib build')
|
||||
|
||||
option('multi_thread', type: 'feature', value: 'enabled',
|
||||
|
||||
@@ -12,6 +12,7 @@ zstd_rootdir = '../../..'
|
||||
|
||||
zstd_programs_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'),
|
||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'programs/fileio.c'),
|
||||
join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
||||
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
||||
@@ -63,6 +64,7 @@ zstd = executable('zstd',
|
||||
install: true)
|
||||
|
||||
zstd_frugal_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
join_paths(zstd_rootdir, 'programs/fileio.c')]
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ datagen = executable('datagen',
|
||||
|
||||
fullbench_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
||||
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
||||
join_paths(zstd_rootdir, 'tests/fullbench.c')]
|
||||
@@ -51,6 +52,7 @@ fullbench = executable('fullbench',
|
||||
|
||||
fuzzer_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'tests/fuzzer.c')]
|
||||
fuzzer = executable('fuzzer',
|
||||
fuzzer_sources,
|
||||
@@ -60,6 +62,7 @@ fuzzer = executable('fuzzer',
|
||||
|
||||
zbufftest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'tests/zbufftest.c')]
|
||||
zbufftest = executable('zbufftest',
|
||||
zbufftest_sources,
|
||||
@@ -70,6 +73,7 @@ zbufftest = executable('zbufftest',
|
||||
|
||||
zstreamtest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'tests/seqgen.c'),
|
||||
join_paths(zstd_rootdir, 'tests/zstreamtest.c')]
|
||||
zstreamtest = executable('zstreamtest',
|
||||
@@ -79,6 +83,7 @@ zstreamtest = executable('zstreamtest',
|
||||
install: false)
|
||||
|
||||
paramgrill_sources = [join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
||||
join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
@@ -107,15 +112,18 @@ invalidDictionaries = executable('invalidDictionaries',
|
||||
dependencies: [ libzstd_dep ],
|
||||
install: false)
|
||||
|
||||
legacy_sources = [join_paths(zstd_rootdir, 'tests/legacy.c')]
|
||||
legacy = executable('legacy',
|
||||
legacy_sources,
|
||||
# Use -Dlegacy_level build option to control it
|
||||
#c_args: '-DZSTD_LEGACY_SUPPORT=4',
|
||||
dependencies: [ libzstd_dep ],
|
||||
install: false)
|
||||
if 0 < legacy_level and legacy_level <= 4
|
||||
legacy_sources = [join_paths(zstd_rootdir, 'tests/legacy.c')]
|
||||
legacy = executable('legacy',
|
||||
legacy_sources,
|
||||
# Use -Dlegacy_level build option to control it
|
||||
#c_args: '-DZSTD_LEGACY_SUPPORT=4',
|
||||
dependencies: [ libzstd_dep ],
|
||||
install: false)
|
||||
endif
|
||||
|
||||
decodecorpus_sources = [join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'tests/decodecorpus.c')]
|
||||
decodecorpus = executable('decodecorpus',
|
||||
decodecorpus_sources,
|
||||
@@ -132,6 +140,7 @@ symbols = executable('symbols',
|
||||
install: false)
|
||||
|
||||
poolTests_sources = [join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'tests/poolTests.c'),
|
||||
join_paths(zstd_rootdir, 'lib/common/pool.c'),
|
||||
join_paths(zstd_rootdir, 'lib/common/threading.c'),
|
||||
@@ -170,7 +179,8 @@ if host_machine_os != os_windows
|
||||
args: ZSTDRTTEST,
|
||||
env: ['ZSTD=' + zstd.full_path()],
|
||||
depends: [datagen],
|
||||
timeout: 600) # Timeout should work on HDD drive
|
||||
workdir: meson.current_build_dir(),
|
||||
timeout: 2800) # Timeout should work on HDD drive
|
||||
endif
|
||||
|
||||
test('test-fullbench-1',
|
||||
@@ -188,7 +198,7 @@ if use_zlib
|
||||
test('test-fuzzer',
|
||||
fuzzer,
|
||||
args: ['-v', FUZZERTEST] + FUZZER_FLAGS,
|
||||
timeout: 240)
|
||||
timeout: 480)
|
||||
endif
|
||||
|
||||
test('test-zbuff',
|
||||
@@ -198,7 +208,7 @@ test('test-zbuff',
|
||||
test('test-zstream-1',
|
||||
zstreamtest,
|
||||
args: ['-v', ZSTREAM_TESTTIME] + FUZZER_FLAGS,
|
||||
timeout: 120)
|
||||
timeout: 240)
|
||||
test('test-zstream-2',
|
||||
zstreamtest,
|
||||
args: ['-mt', '-t1', ZSTREAM_TESTTIME] + FUZZER_FLAGS,
|
||||
@@ -210,7 +220,9 @@ test('test-zstream-3',
|
||||
test('test-longmatch', longmatch, timeout: 36)
|
||||
test('test-invalidDictionaries', invalidDictionaries) # should be fast
|
||||
test('test-symbols', symbols) # should be fast
|
||||
test('test-legacy', legacy) # should be fast
|
||||
if 0 < legacy_level and legacy_level <= 4
|
||||
test('test-legacy', legacy) # should be fast
|
||||
endif
|
||||
test('test-decodecorpus',
|
||||
decodecorpus,
|
||||
args: ['-t', DECODECORPUS_TESTTIME],
|
||||
|
||||
@@ -13,7 +13,7 @@ CPPFLAGS += -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
|
||||
CFLAGS ?= -O3
|
||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||
-Wstrict-prototypes -Wundef -Wformat-security \
|
||||
-Wstrict-prototypes -Wundef \
|
||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||
-Wredundant-decls
|
||||
CFLAGS += $(DEBUGFLAGS)
|
||||
@@ -22,10 +22,10 @@ FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(MULTITHREAD_LDFLAGS)
|
||||
|
||||
all: adapt datagen
|
||||
|
||||
adapt: $(ZSTD_FILES) $(PRGDIR)/util.c adapt.c
|
||||
adapt: $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c adapt.c
|
||||
$(CC) $(FLAGS) $^ -o $@
|
||||
|
||||
adapt-debug: $(ZSTD_FILES) $(PRGDIR)/util.c adapt.c
|
||||
adapt-debug: $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c adapt.c
|
||||
$(CC) $(FLAGS) -DDEBUG_MODE=2 $^ -o adapt
|
||||
|
||||
datagen : $(PRGDIR)/datagen.c datagencli.c
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string.h> /* memset */
|
||||
#include "zstd_internal.h"
|
||||
#include "util.h"
|
||||
#include "timefn.h" /* UTIL_time_t, UTIL_getTime, UTIL_getSpanTimeMicro */
|
||||
|
||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define PRINT(...) fprintf(stdout, __VA_ARGS__)
|
||||
|
||||
@@ -5,7 +5,7 @@ The `Dockerfile` script requires a version of `docker` >= 17.05
|
||||
|
||||
## Installing docker
|
||||
|
||||
The officiel docker install docs use a ppa with a modern version available:
|
||||
The official docker install docs use a ppa with a modern version available:
|
||||
https://docs.docker.com/install/linux/docker-ce/ubuntu/
|
||||
|
||||
## How to run
|
||||
|
||||
@@ -127,7 +127,7 @@ dictInfo* createDictFromFiles(sampleInfo *info, unsigned maxDictSize,
|
||||
|
||||
|
||||
/** compressWithDict() :
|
||||
* Compress samples from sample buffer given dicionary stored on dictionary buffer and compression level
|
||||
* Compress samples from sample buffer given dictionary stored on dictionary buffer and compression level
|
||||
* @return compression ratio
|
||||
*/
|
||||
double compressWithDict(sampleInfo *srcInfo, dictInfo* dInfo, int compressionLevel, int displayLevel) {
|
||||
@@ -194,7 +194,7 @@ double compressWithDict(sampleInfo *srcInfo, dictInfo* dInfo, int compressionLev
|
||||
totalCompressedSize += compressedSize;
|
||||
}
|
||||
|
||||
/* Sum orignal sizes */
|
||||
/* Sum original sizes */
|
||||
for (i = 0; i<srcInfo->nbSamples; i++) {
|
||||
totalOriginalSize += srcInfo->samplesSizes[i];
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ typedef struct {
|
||||
*
|
||||
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
|
||||
*
|
||||
* Once the dmer with hash value d is in the dictionay we set F(d) = F(d)/2.
|
||||
* Once the dmer with hash value d is in the dictionary we set F(d) = F(d)/2.
|
||||
*/
|
||||
static FASTCOVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
||||
U32 *freqs, U32 begin,U32 end,
|
||||
@@ -149,7 +149,7 @@ static FASTCOVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
||||
while (activeSegment.end < end) {
|
||||
/* Get hash value of current dmer */
|
||||
const size_t index = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, parameters.f, ctx->d);
|
||||
/* Add frequency of this index to score if this is the first occurence of index in active segment */
|
||||
/* Add frequency of this index to score if this is the first occurrence of index in active segment */
|
||||
if (ctx->segmentFreqs[index] == 0) {
|
||||
activeSegment.score += freqs[index];
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ CFLAGS ?= -O3
|
||||
CFLAGS += -std=gnu99
|
||||
DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||
-Wstrict-aliasing=1 -Wswitch-enum \
|
||||
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \
|
||||
-Wstrict-prototypes -Wundef -Wpointer-arith \
|
||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||
-Wredundant-decls
|
||||
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||
@@ -28,14 +28,17 @@ default: largeNbDicts
|
||||
|
||||
all : largeNbDicts
|
||||
|
||||
largeNbDicts: util.o benchfn.o datagen.o xxhash.o largeNbDicts.c $(LIBZSTD)
|
||||
largeNbDicts: util.o timefn.o benchfn.o datagen.o xxhash.o largeNbDicts.c $(LIBZSTD)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
.PHONY: $(LIBZSTD)
|
||||
$(LIBZSTD):
|
||||
$(MAKE) -C $(LIBDIR) libzstd.a CFLAGS="$(CFLAGS)"
|
||||
|
||||
benchfn.o : $(PROGDIR)/benchfn.c
|
||||
benchfn.o: $(PROGDIR)/benchfn.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
||||
|
||||
timefn.o: $(PROGDIR)/timefn.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
||||
|
||||
datagen.o: $(PROGDIR)/datagen.c
|
||||
@@ -48,6 +51,7 @@ util.o: $(PROGDIR)/util.c
|
||||
xxhash.o : $(LIBDIR)/common/xxhash.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
||||
|
||||
|
||||
clean:
|
||||
$(RM) *.o
|
||||
$(MAKE) -C $(LIBDIR) clean > /dev/null
|
||||
|
||||
@@ -424,7 +424,7 @@ static ddict_collection_t createDDictCollection(const void* dictBuffer, size_t d
|
||||
}
|
||||
|
||||
|
||||
/* mess with adresses, so that linear scanning dictionaries != linear address scanning */
|
||||
/* mess with addresses, so that linear scanning dictionaries != linear address scanning */
|
||||
void shuffleDictionaries(ddict_collection_t dicts)
|
||||
{
|
||||
size_t const nbDicts = dicts.nbDDict;
|
||||
|
||||
@@ -4,7 +4,7 @@ Date: Mon, 17 Jul 2017 17:08:19 -0700
|
||||
Subject: [PATCH v5 2/5] lib: Add zstd modules
|
||||
|
||||
Add zstd compression and decompression kernel modules.
|
||||
zstd offers a wide varity of compression speed and quality trade-offs.
|
||||
zstd offers a wide variety of compression speed and quality trade-offs.
|
||||
It can compress at speeds approaching lz4, and quality approaching lzma.
|
||||
zstd decompressions at speeds more than twice as fast as zlib, and
|
||||
decompression speed remains roughly the same across all compression levels.
|
||||
@@ -21,7 +21,7 @@ will be easier to keep the kernel zstd up to date.
|
||||
I benchmarked zstd compression as a special character device. I ran zstd
|
||||
and zlib compression at several levels, as well as performing no
|
||||
compression, which measure the time spent copying the data to kernel space.
|
||||
Data is passed to the compresser 4096 B at a time. The benchmark file is
|
||||
Data is passed to the compressor 4096 B at a time. The benchmark file is
|
||||
located in the upstream zstd source repository under
|
||||
`contrib/linux-kernel/zstd_compress_test.c` [2].
|
||||
|
||||
@@ -86,7 +86,7 @@ Tested in userland using the test-suite in the zstd repo under
|
||||
`contrib/linux-kernel/test/UserlandTest.cpp` [5] by mocking the kernel
|
||||
functions. Fuzz tested using libfuzzer [6] with the fuzz harnesses under
|
||||
`contrib/linux-kernel/test/{RoundTripCrash.c,DecompressCrash.c}` [7] [8]
|
||||
with ASAN, UBSAN, and MSAN. Additionaly, it was tested while testing the
|
||||
with ASAN, UBSAN, and MSAN. Additionally, it was tested while testing the
|
||||
BtrFS and SquashFS patches coming next.
|
||||
|
||||
[1] https://clang.llvm.org/docs/ClangFormat.html
|
||||
@@ -4200,14 +4200,14 @@ index 0000000..ff18ae6
|
||||
+ BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
|
||||
+ U32 const fcsCode =
|
||||
+ params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */
|
||||
+ BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
|
||||
+ BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
|
||||
+ size_t pos;
|
||||
+
|
||||
+ if (dstCapacity < ZSTD_frameHeaderSize_max)
|
||||
+ return ERROR(dstSize_tooSmall);
|
||||
+
|
||||
+ ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER);
|
||||
+ op[4] = frameHeaderDecriptionByte;
|
||||
+ op[4] = frameHeaderDescriptionByte;
|
||||
+ pos = 5;
|
||||
+ if (!singleSegment)
|
||||
+ op[pos++] = windowLogByte;
|
||||
@@ -8812,8 +8812,8 @@ index 0000000..ef3d174
|
||||
+ U32 position = 0;
|
||||
+ U32 symbol;
|
||||
+ for (symbol = 0; symbol <= maxSymbolValue; symbol++) {
|
||||
+ int nbOccurences;
|
||||
+ for (nbOccurences = 0; nbOccurences < normalizedCounter[symbol]; nbOccurences++) {
|
||||
+ int nbOccurrences;
|
||||
+ for (nbOccurrences = 0; nbOccurrences < normalizedCounter[symbol]; nbOccurrences++) {
|
||||
+ tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
||||
+ position = (position + step) & tableMask;
|
||||
+ while (position > highThreshold)
|
||||
@@ -9944,7 +9944,7 @@ index 0000000..2143da2
|
||||
+ HUF_repeat_none, /**< Cannot use the previous table */
|
||||
+ HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
|
||||
+ 4}X_repeat */
|
||||
+ HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */
|
||||
+ HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */
|
||||
+} HUF_repeat;
|
||||
+/** HUF_compress4X_repeat() :
|
||||
+* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
|
||||
|
||||
@@ -11,7 +11,7 @@ Signed-off-by: Nick Terrell <terrelln@fb.com>
|
||||
---
|
||||
v4 -> v5:
|
||||
- Fix patch documentation to reflect that Sean Purcell is the author
|
||||
- Don't strip trailing whitespace of unreleated code
|
||||
- Don't strip trailing whitespace of unrelated code
|
||||
- Make zstd_display_options() static
|
||||
|
||||
v5 -> v6:
|
||||
@@ -224,7 +224,7 @@ index 0000000..dcab75a
|
||||
+ * set the default options, this is to ensure any user supplied
|
||||
+ * -X options on the appending mksquashfs command line are over-ridden.
|
||||
+ *
|
||||
+ * This function returns 0 on sucessful extraction of options, and -1 on error.
|
||||
+ * This function returns 0 on successful extraction of options, and -1 on error.
|
||||
+ */
|
||||
+static int zstd_extract_options(int block_size, void *buffer, int size)
|
||||
+{
|
||||
|
||||
@@ -2436,14 +2436,14 @@ static size_t ZSTD_writeFrameHeader(void *dst, size_t dstCapacity, ZSTD_paramete
|
||||
BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
|
||||
U32 const fcsCode =
|
||||
params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */
|
||||
BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
|
||||
BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
|
||||
size_t pos;
|
||||
|
||||
if (dstCapacity < ZSTD_frameHeaderSize_max)
|
||||
return ERROR(dstSize_tooSmall);
|
||||
|
||||
ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER);
|
||||
op[4] = frameHeaderDecriptionByte;
|
||||
op[4] = frameHeaderDescriptionByte;
|
||||
pos = 5;
|
||||
if (!singleSegment)
|
||||
op[pos++] = windowLogByte;
|
||||
|
||||
@@ -141,8 +141,8 @@ size_t FSE_buildCTable_wksp(FSE_CTable *ct, const short *normalizedCounter, unsi
|
||||
U32 position = 0;
|
||||
U32 symbol;
|
||||
for (symbol = 0; symbol <= maxSymbolValue; symbol++) {
|
||||
int nbOccurences;
|
||||
for (nbOccurences = 0; nbOccurences < normalizedCounter[symbol]; nbOccurences++) {
|
||||
int nbOccurrences;
|
||||
for (nbOccurrences = 0; nbOccurrences < normalizedCounter[symbol]; nbOccurrences++) {
|
||||
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
||||
position = (position + step) & tableMask;
|
||||
while (position > highThreshold)
|
||||
|
||||
@@ -134,7 +134,7 @@ typedef enum {
|
||||
HUF_repeat_none, /**< Cannot use the previous table */
|
||||
HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
|
||||
4}X_repeat */
|
||||
HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */
|
||||
HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */
|
||||
} HUF_repeat;
|
||||
/** HUF_compress4X_repeat() :
|
||||
* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef LINUX_COMIPLER_H_
|
||||
#define LINUX_COMIPLER_H_
|
||||
#ifndef LINUX_COMPILER_H_
|
||||
#define LINUX_COMPILER_H_
|
||||
|
||||
#ifndef __always_inline
|
||||
# define __always_inline inline
|
||||
@@ -9,4 +9,4 @@
|
||||
# define noinline __attribute__((__noinline__))
|
||||
#endif
|
||||
|
||||
#endif // LINUX_COMIPLER_H_
|
||||
#endif // LINUX_COMPILER_H_
|
||||
|
||||
@@ -190,13 +190,15 @@ $(ZSTDDIR)/libzstd.a: $(ZSTD_FILES)
|
||||
CFLAGS="$(ALL_CFLAGS)" LDFLAGS="$(ALL_LDFLAGS)" $(MAKE) -C $(ZSTDDIR) libzstd.a
|
||||
|
||||
# Rules to build the tests
|
||||
test/RoundTripTest$(EXT): test/RoundTripTest.o $(PROGDIR)/datagen.o Options.o \
|
||||
test/RoundTripTest$(EXT): test/RoundTripTest.o $(PROGDIR)/datagen.o \
|
||||
$(PROGDIR)/util.o Options.o \
|
||||
Pzstd.o SkippableFrame.o $(ZSTDDIR)/libzstd.a
|
||||
$(LD_COMMAND)
|
||||
|
||||
test/%Test$(EXT): PZSTD_LDFLAGS += $(GTEST_LIB)
|
||||
test/%Test$(EXT): LIBS += -lgtest -lgtest_main
|
||||
test/%Test$(EXT): test/%Test.o $(PROGDIR)/datagen.o Options.o Pzstd.o \
|
||||
test/%Test$(EXT): test/%Test.o $(PROGDIR)/datagen.o \
|
||||
$(PROGDIR)/util.o Options.o Pzstd.o \
|
||||
SkippableFrame.o $(ZSTDDIR)/libzstd.a
|
||||
$(LD_COMMAND)
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ static std::uint64_t handleOneInput(const Options &options,
|
||||
SharedState& state) {
|
||||
auto inputSize = fileSizeOrZero(inputFile);
|
||||
// WorkQueue outlives ThreadPool so in the case of error we are certain
|
||||
// we don't accidently try to call push() on it after it is destroyed
|
||||
// we don't accidentally try to call push() on it after it is destroyed
|
||||
WorkQueue<std::shared_ptr<BufferWorkQueue>> outs{options.numThreads + 1};
|
||||
std::uint64_t bytesRead;
|
||||
std::uint64_t bytesWritten;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
/**
|
||||
* A subset of `folly/Range.h`.
|
||||
* All code copied verbatiam modulo formatting
|
||||
* All code copied verbatim modulo formatting
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ class ResourcePool {
|
||||
|
||||
/**
|
||||
* @returns A unique pointer to a resource. The resource is null iff
|
||||
* there are no avaiable resources and `factory()` returns null.
|
||||
* there are no available resources and `factory()` returns null.
|
||||
*/
|
||||
UniquePtr get() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
+2
-2
@@ -12,8 +12,8 @@ __`zstd_compression_format.md`__ : This document defines the Zstandard compressi
|
||||
Compliant decoders must adhere to this document,
|
||||
and compliant encoders must generate data that follows it.
|
||||
|
||||
Should you look for ressources to develop your own port of Zstandard algorithm,
|
||||
you may find the following ressources useful :
|
||||
Should you look for resources to develop your own port of Zstandard algorithm,
|
||||
you may find the following resources useful :
|
||||
|
||||
__`educational_decoder`__ : This directory contains an implementation of a Zstandard decoder,
|
||||
compliant with the Zstandard compression format.
|
||||
|
||||
@@ -7,7 +7,7 @@ CPPFLAGS += -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
|
||||
CFLAGS ?= -O3
|
||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||
-Wstrict-prototypes -Wundef -Wformat-security \
|
||||
-Wstrict-prototypes -Wundef \
|
||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||
-Wredundant-decls
|
||||
CFLAGS += $(DEBUGFLAGS)
|
||||
|
||||
@@ -358,7 +358,7 @@ static u32 copy_literals(const size_t seq, istream_t *litstream,
|
||||
ostream_t *const out);
|
||||
|
||||
// Given an offset code from a sequence command (either an actual offset value
|
||||
// or an index for previous offset), computes the correct offset and udpates
|
||||
// or an index for previous offset), computes the correct offset and updates
|
||||
// the offset history
|
||||
static size_t compute_offset(sequence_command_t seq, u64 *const offset_hist);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ Distribution of this document is unlimited.
|
||||
|
||||
### Version
|
||||
|
||||
0.3.1 (25/10/18)
|
||||
0.3.2 (17/07/19)
|
||||
|
||||
|
||||
Introduction
|
||||
@@ -390,9 +390,7 @@ A block can contain any number of bytes (even zero), up to
|
||||
- Window_Size
|
||||
- 128 KB
|
||||
|
||||
A `Compressed_Block` has the extra restriction that `Block_Size` is always
|
||||
strictly less than the decompressed size.
|
||||
If this condition cannot be respected,
|
||||
If this condition cannot be respected when generating a `Compressed_Block`,
|
||||
the block must be sent uncompressed instead (`Raw_Block`).
|
||||
|
||||
|
||||
@@ -1655,6 +1653,7 @@ or at least provide a meaningful error code explaining for which reason it canno
|
||||
|
||||
Version changes
|
||||
---------------
|
||||
- 0.3.2 : remove additional block size restriction on compressed blocks
|
||||
- 0.3.1 : minor clarification regarding offset history update rules
|
||||
- 0.3.0 : minor edits to match RFC8478
|
||||
- 0.2.9 : clarifications for huffman weights direct representation, by Ulrich Kunitz
|
||||
|
||||
+533
-400
@@ -1,26 +1,26 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>zstd 1.3.8 Manual</title>
|
||||
<title>zstd 1.4.1 Manual</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>zstd 1.3.8 Manual</h1>
|
||||
<h1>zstd 1.4.1 Manual</h1>
|
||||
<hr>
|
||||
<a name="Contents"></a><h2>Contents</h2>
|
||||
<ol>
|
||||
<li><a href="#Chapter1">Introduction</a></li>
|
||||
<li><a href="#Chapter2">Version</a></li>
|
||||
<li><a href="#Chapter3">Default constant</a></li>
|
||||
<li><a href="#Chapter4">Simple API</a></li>
|
||||
<li><a href="#Chapter5">Explicit context</a></li>
|
||||
<li><a href="#Chapter6">Simple dictionary API</a></li>
|
||||
<li><a href="#Chapter7">Bulk processing dictionary API</a></li>
|
||||
<li><a href="#Chapter8">Streaming</a></li>
|
||||
<li><a href="#Chapter9">Streaming compression - HowTo</a></li>
|
||||
<li><a href="#Chapter10">Streaming decompression - HowTo</a></li>
|
||||
<li><a href="#Chapter11">ADVANCED AND EXPERIMENTAL FUNCTIONS</a></li>
|
||||
<li><a href="#Chapter12">Candidate API for promotion to stable status</a></li>
|
||||
<li><a href="#Chapter13">Advanced compression API</a></li>
|
||||
<li><a href="#Chapter3">Simple API</a></li>
|
||||
<li><a href="#Chapter4">Explicit context</a></li>
|
||||
<li><a href="#Chapter5">Advanced compression API</a></li>
|
||||
<li><a href="#Chapter6">Advanced decompression API</a></li>
|
||||
<li><a href="#Chapter7">Streaming</a></li>
|
||||
<li><a href="#Chapter8">Streaming compression - HowTo</a></li>
|
||||
<li><a href="#Chapter9">Streaming decompression - HowTo</a></li>
|
||||
<li><a href="#Chapter10">Simple dictionary API</a></li>
|
||||
<li><a href="#Chapter11">Bulk processing dictionary API</a></li>
|
||||
<li><a href="#Chapter12">Dictionary helper functions</a></li>
|
||||
<li><a href="#Chapter13">Advanced dictionary and prefix API</a></li>
|
||||
<li><a href="#Chapter14">experimental API (static linking only)</a></li>
|
||||
<li><a href="#Chapter15">Frame size functions</a></li>
|
||||
<li><a href="#Chapter16">Memory management</a></li>
|
||||
@@ -30,8 +30,7 @@
|
||||
<li><a href="#Chapter20">Buffer-less and synchronous inner streaming functions</a></li>
|
||||
<li><a href="#Chapter21">Buffer-less streaming compression (synchronous mode)</a></li>
|
||||
<li><a href="#Chapter22">Buffer-less streaming decompression (synchronous mode)</a></li>
|
||||
<li><a href="#Chapter23">ZSTD_getFrameHeader() :</a></li>
|
||||
<li><a href="#Chapter24">Block level API</a></li>
|
||||
<li><a href="#Chapter23">Block level API</a></li>
|
||||
</ol>
|
||||
<hr>
|
||||
<a name="Chapter1"></a><h2>Introduction</h2><pre>
|
||||
@@ -69,9 +68,7 @@
|
||||
|
||||
<pre><b>unsigned ZSTD_versionNumber(void); </b>/**< to check runtime library version */<b>
|
||||
</b></pre><BR>
|
||||
<a name="Chapter3"></a><h2>Default constant</h2><pre></pre>
|
||||
|
||||
<a name="Chapter4"></a><h2>Simple API</h2><pre></pre>
|
||||
<a name="Chapter3"></a><h2>Simple API</h2><pre></pre>
|
||||
|
||||
<pre><b>size_t ZSTD_compress( void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
@@ -126,18 +123,32 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
|
||||
@return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
|
||||
</b><p> `src` should point to the start of a ZSTD frame or skippable frame.
|
||||
`srcSize` must be >= first frame size
|
||||
@return : the compressed size of the first frame starting at `src`,
|
||||
suitable to pass as `srcSize` to `ZSTD_decompress` or similar,
|
||||
or an error code if input is invalid
|
||||
</p></pre><BR>
|
||||
|
||||
<h3>Helper functions</h3><pre></pre><b><pre>#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) </b>/* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */<b>
|
||||
size_t ZSTD_compressBound(size_t srcSize); </b>/*!< maximum compressed size in worst case single-pass scenario */<b>
|
||||
unsigned ZSTD_isError(size_t code); </b>/*!< tells if a `size_t` function result is an error code */<b>
|
||||
const char* ZSTD_getErrorName(size_t code); </b>/*!< provides readable string from an error code */<b>
|
||||
int ZSTD_minCLevel(void); </b>/*!< minimum negative compression level allowed */<b>
|
||||
int ZSTD_maxCLevel(void); </b>/*!< maximum compression level available */<b>
|
||||
</pre></b><BR>
|
||||
<a name="Chapter5"></a><h2>Explicit context</h2><pre></pre>
|
||||
<a name="Chapter4"></a><h2>Explicit context</h2><pre></pre>
|
||||
|
||||
<h3>Compression context</h3><pre> When compressing many times,
|
||||
it is recommended to allocate a context just once, and re-use it for each successive compression operation.
|
||||
it is recommended to allocate a context just once,
|
||||
and re-use it for each successive compression operation.
|
||||
This will make workload friendlier for system's memory.
|
||||
Use one context per thread for parallel execution in multi-threaded environments.
|
||||
Note : re-using context is just a speed / resource optimization.
|
||||
It doesn't change the compression ratio, which remains identical.
|
||||
Note 2 : In multi-threaded environments,
|
||||
use one different context per thread for parallel execution.
|
||||
|
||||
</pre><b><pre>typedef struct ZSTD_CCtx_s ZSTD_CCtx;
|
||||
ZSTD_CCtx* ZSTD_createCCtx(void);
|
||||
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx);
|
||||
@@ -169,228 +180,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter6"></a><h2>Simple dictionary API</h2><pre></pre>
|
||||
|
||||
<pre><b>size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize,
|
||||
int compressionLevel);
|
||||
</b><p> Compression at an explicit compression level using a Dictionary.
|
||||
A dictionary can be any arbitrary data segment (also called a prefix),
|
||||
or a buffer with specified information (see dictBuilder/zdict.h).
|
||||
Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
It's intended for a dictionary used only once.
|
||||
Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize);
|
||||
</b><p> Decompression using a known Dictionary.
|
||||
Dictionary must be identical to the one used during compression.
|
||||
Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
It's intended for a dictionary used only once.
|
||||
Note : When `dict == NULL || dictSize < 8` no dictionary is used.
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter7"></a><h2>Bulk processing dictionary API</h2><pre></pre>
|
||||
|
||||
<pre><b>ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
|
||||
int compressionLevel);
|
||||
</b><p> When compressing multiple messages / blocks using the same dictionary, it's recommended to load it only once.
|
||||
ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup cost.
|
||||
ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
|
||||
`dictBuffer` can be released after ZSTD_CDict creation, because its content is copied within CDict.
|
||||
Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate `dictBuffer` content.
|
||||
Note : A ZSTD_CDict can be created from an empty dictBuffer, but it is inefficient when used to compress small data.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
|
||||
</b><p> Function frees memory allocated by ZSTD_createCDict().
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_CDict* cdict);
|
||||
</b><p> Compression using a digested Dictionary.
|
||||
Recommended when same dictionary is used multiple times.
|
||||
Note : compression level is _decided at dictionary creation time_,
|
||||
and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no)
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
|
||||
</b><p> Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||
dictBuffer can be released after DDict creation, as its content is copied inside DDict.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
|
||||
</b><p> Function frees memory allocated with ZSTD_createDDict()
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_DDict* ddict);
|
||||
</b><p> Decompression using a digested Dictionary.
|
||||
Recommended when same dictionary is used multiple times.
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter8"></a><h2>Streaming</h2><pre></pre>
|
||||
|
||||
<pre><b>typedef struct ZSTD_inBuffer_s {
|
||||
const void* src; </b>/**< start of input buffer */<b>
|
||||
size_t size; </b>/**< size of input buffer */<b>
|
||||
size_t pos; </b>/**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */<b>
|
||||
} ZSTD_inBuffer;
|
||||
</b></pre><BR>
|
||||
<pre><b>typedef struct ZSTD_outBuffer_s {
|
||||
void* dst; </b>/**< start of output buffer */<b>
|
||||
size_t size; </b>/**< size of output buffer */<b>
|
||||
size_t pos; </b>/**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */<b>
|
||||
} ZSTD_outBuffer;
|
||||
</b></pre><BR>
|
||||
<a name="Chapter9"></a><h2>Streaming compression - HowTo</h2><pre>
|
||||
A ZSTD_CStream object is required to track streaming operation.
|
||||
Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
|
||||
ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
|
||||
It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
|
||||
|
||||
For parallel execution, use one separate ZSTD_CStream per thread.
|
||||
|
||||
note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
|
||||
|
||||
Parameters are sticky : when starting a new compression on the same context,
|
||||
it will re-use the same sticky parameters as previous compression session.
|
||||
When in doubt, it's recommended to fully initialize the context before usage.
|
||||
Use ZSTD_initCStream() to set the parameter to a selected compression level.
|
||||
Use advanced API (ZSTD_CCtx_setParameter(), etc.) to set more specific parameters.
|
||||
|
||||
Use ZSTD_compressStream() as many times as necessary to consume input stream.
|
||||
The function will automatically update both `pos` fields within `input` and `output`.
|
||||
Note that the function may not consume the entire input,
|
||||
for example, because the output buffer is already full,
|
||||
in which case `input.pos < input.size`.
|
||||
The caller must check if input has been entirely consumed.
|
||||
If not, the caller must make some room to receive more compressed data,
|
||||
and then present again remaining input data.
|
||||
@return : a size hint, preferred nb of bytes to use as input for next function call
|
||||
or an error code, which can be tested using ZSTD_isError().
|
||||
Note 1 : it's just a hint, to help latency a little, any value will work fine.
|
||||
Note 2 : size hint is guaranteed to be <= ZSTD_CStreamInSize()
|
||||
|
||||
At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
|
||||
using ZSTD_flushStream(). `output->pos` will be updated.
|
||||
Note that, if `output->size` is too small, a single invocation of ZSTD_flushStream() might not be enough (return code > 0).
|
||||
In which case, make some room to receive more compressed data, and call again ZSTD_flushStream().
|
||||
@return : 0 if internal buffers are entirely flushed,
|
||||
>0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
|
||||
or an error code, which can be tested using ZSTD_isError().
|
||||
|
||||
ZSTD_endStream() instructs to finish a frame.
|
||||
It will perform a flush and write frame epilogue.
|
||||
The epilogue is required for decoders to consider a frame completed.
|
||||
flush() operation is the same, and follows same rules as ZSTD_flushStream().
|
||||
@return : 0 if frame fully completed and fully flushed,
|
||||
>0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
|
||||
or an error code, which can be tested using ZSTD_isError().
|
||||
|
||||
|
||||
<BR></pre>
|
||||
|
||||
<pre><b>typedef ZSTD_CCtx ZSTD_CStream; </b>/**< CCtx and CStream are now effectively same object (>= v1.3.0) */<b>
|
||||
</b></pre><BR>
|
||||
<h3>ZSTD_CStream management functions</h3><pre></pre><b><pre>ZSTD_CStream* ZSTD_createCStream(void);
|
||||
size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
|
||||
</pre></b><BR>
|
||||
<h3>Streaming compression functions</h3><pre></pre><b><pre>size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
|
||||
size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
</pre></b><BR>
|
||||
<pre><b>size_t ZSTD_CStreamInSize(void); </b>/**< recommended size for input buffer */<b>
|
||||
</b></pre><BR>
|
||||
<pre><b>size_t ZSTD_CStreamOutSize(void); </b>/**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */<b>
|
||||
</b></pre><BR>
|
||||
<a name="Chapter10"></a><h2>Streaming decompression - HowTo</h2><pre>
|
||||
A ZSTD_DStream object is required to track streaming operations.
|
||||
Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
|
||||
ZSTD_DStream objects can be re-used multiple times.
|
||||
|
||||
Use ZSTD_initDStream() to start a new decompression operation.
|
||||
@return : recommended first input size
|
||||
Alternatively, use advanced API to set specific properties.
|
||||
|
||||
Use ZSTD_decompressStream() repetitively to consume your input.
|
||||
The function will update both `pos` fields.
|
||||
If `input.pos < input.size`, some input has not been consumed.
|
||||
It's up to the caller to present again remaining data.
|
||||
The function tries to flush all data decoded immediately, respecting output buffer size.
|
||||
If `output.pos < output.size`, decoder has flushed everything it could.
|
||||
But if `output.pos == output.size`, there might be some data left within internal buffers.,
|
||||
In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
|
||||
Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
|
||||
@return : 0 when a frame is completely decoded and fully flushed,
|
||||
or an error code, which can be tested using ZSTD_isError(),
|
||||
or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
|
||||
the return value is a suggested next input size (just a hint for better latency)
|
||||
that will never request more than the remaining frame size.
|
||||
|
||||
<BR></pre>
|
||||
|
||||
<pre><b>typedef ZSTD_DCtx ZSTD_DStream; </b>/**< DCtx and DStream are now effectively same object (>= v1.3.0) */<b>
|
||||
</b></pre><BR>
|
||||
<h3>ZSTD_DStream management functions</h3><pre></pre><b><pre>ZSTD_DStream* ZSTD_createDStream(void);
|
||||
size_t ZSTD_freeDStream(ZSTD_DStream* zds);
|
||||
</pre></b><BR>
|
||||
<h3>Streaming decompression functions</h3><pre></pre><b><pre>size_t ZSTD_initDStream(ZSTD_DStream* zds);
|
||||
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
</pre></b><BR>
|
||||
<pre><b>size_t ZSTD_DStreamInSize(void); </b>/*!< recommended size for input buffer */<b>
|
||||
</b></pre><BR>
|
||||
<pre><b>size_t ZSTD_DStreamOutSize(void); </b>/*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */<b>
|
||||
</b></pre><BR>
|
||||
<a name="Chapter11"></a><h2>ADVANCED AND EXPERIMENTAL FUNCTIONS</h2><pre>
|
||||
The definitions in the following section are considered experimental.
|
||||
They are provided for advanced scenarios.
|
||||
They should never be used with a dynamic library, as prototypes may change in the future.
|
||||
Use them only in association with static linking.
|
||||
|
||||
<BR></pre>
|
||||
|
||||
<a name="Chapter12"></a><h2>Candidate API for promotion to stable status</h2><pre>
|
||||
The following symbols and constants form the "staging area" :
|
||||
they are considered to join "stable API" by v1.4.0.
|
||||
The proposal is written so that it can be made stable "as is",
|
||||
though it's still possible to suggest improvements.
|
||||
Staging is in fact last chance for changes,
|
||||
the API is locked once reaching "stable" status.
|
||||
|
||||
<BR></pre>
|
||||
|
||||
<pre><b>int ZSTD_minCLevel(void); </b>/*!< minimum negative compression level allowed */<b>
|
||||
</b></pre><BR>
|
||||
<pre><b>size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
|
||||
</b><p> `src` should point to the start of a ZSTD frame or skippable frame.
|
||||
`srcSize` must be >= first frame size
|
||||
@return : the compressed size of the first frame starting at `src`,
|
||||
suitable to pass as `srcSize` to `ZSTD_decompress` or similar,
|
||||
or an error code if input is invalid
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
|
||||
size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
|
||||
size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
|
||||
size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
|
||||
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
|
||||
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
</b><p> These functions give the _current_ memory usage of selected object.
|
||||
Note that object memory usage can evolve (increase or decrease) over time.
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter13"></a><h2>Advanced compression API</h2><pre></pre>
|
||||
<a name="Chapter5"></a><h2>Advanced compression API</h2><pre></pre>
|
||||
|
||||
<pre><b>typedef enum { ZSTD_fast=1,
|
||||
ZSTD_dfast=2,
|
||||
@@ -407,7 +197,10 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
</b></pre><BR>
|
||||
<pre><b>typedef enum {
|
||||
|
||||
</b>/* compression parameters */<b>
|
||||
</b>/* compression parameters<b>
|
||||
* Note: When compressing with a ZSTD_CDict these parameters are superseded
|
||||
* by the parameters used to construct the ZSTD_CDict. See ZSTD_CCtx_refCDict()
|
||||
* for more info (superseded-by-cdict). */
|
||||
ZSTD_c_compressionLevel=100, </b>/* Update all compression parameters according to pre-defined cLevel table<b>
|
||||
* Default level is ZSTD_CLEVEL_DEFAULT==3.
|
||||
* Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.
|
||||
@@ -529,6 +322,8 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
* ZSTD_c_format
|
||||
* ZSTD_c_forceMaxWindow
|
||||
* ZSTD_c_forceAttachDict
|
||||
* ZSTD_c_literalCompressionMode
|
||||
* ZSTD_c_targetCBlockSize
|
||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||
* note : never ever use experimentalParam? names directly;
|
||||
* also, the enums values themselves are unstable and can still change.
|
||||
@@ -536,7 +331,9 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
ZSTD_c_experimentalParam1=500,
|
||||
ZSTD_c_experimentalParam2=10,
|
||||
ZSTD_c_experimentalParam3=1000,
|
||||
ZSTD_c_experimentalParam4=1001
|
||||
ZSTD_c_experimentalParam4=1001,
|
||||
ZSTD_c_experimentalParam5=1002,
|
||||
ZSTD_c_experimentalParam6=1003,
|
||||
} ZSTD_cParameter;
|
||||
</b></pre><BR>
|
||||
<pre><b>typedef struct {
|
||||
@@ -580,62 +377,10 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
Note 3 : Whenever all input data is provided and consumed in a single round,
|
||||
for example with ZSTD_compress2(),
|
||||
or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),
|
||||
this value is automatically overriden by srcSize instead.
|
||||
this value is automatically overridden by srcSize instead.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
||||
</b><p> Create an internal CDict from `dict` buffer.
|
||||
Decompression will have to use same dictionary.
|
||||
@result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,
|
||||
meaning "return to no-dictionary mode".
|
||||
Note 1 : Dictionary is sticky, it will be used for all future compressed frames.
|
||||
To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters).
|
||||
Note 2 : Loading a dictionary involves building tables.
|
||||
It's also a CPU consuming operation, with non-negligible impact on latency.
|
||||
Tables are dependent on compression parameters, and for this reason,
|
||||
compression parameters can no longer be changed after loading a dictionary.
|
||||
Note 3 :`dict` content will be copied internally.
|
||||
Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.
|
||||
In such a case, dictionary buffer must outlive its users.
|
||||
Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()
|
||||
to precisely select how dictionary content must be interpreted.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
|
||||
</b><p> Reference a prepared dictionary, to be used for all next compressed frames.
|
||||
Note that compression parameters are enforced from within CDict,
|
||||
and supercede any compression parameter previously set within CCtx.
|
||||
The dictionary will remain valid for future compressed frames using same CCtx.
|
||||
@result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
Special : Referencing a NULL CDict means "return to no-dictionary mode".
|
||||
Note 1 : Currently, only one dictionary can be managed.
|
||||
Referencing a new dictionary effectively "discards" any previous one.
|
||||
Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
|
||||
const void* prefix, size_t prefixSize);
|
||||
</b><p> Reference a prefix (single-usage dictionary) for next compressed frame.
|
||||
A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
|
||||
Decompression will need same prefix to properly regenerate data.
|
||||
Compressing with a prefix is similar in outcome as performing a diff and compressing it,
|
||||
but performs much faster, especially during decompression (compression speed is tunable with compression level).
|
||||
@result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary
|
||||
Note 1 : Prefix buffer is referenced. It **must** outlive compression.
|
||||
Its content must remain unmodified during compression.
|
||||
Note 2 : If the intention is to diff some large src data blob with some prior version of itself,
|
||||
ensure that the window size is large enough to contain the entire source.
|
||||
See ZSTD_c_windowLog.
|
||||
Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.
|
||||
It's a CPU consuming operation, with non-negligible impact on latency.
|
||||
If there is a need to use the same prefix multiple times, consider loadDictionary instead.
|
||||
Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dm_rawContent).
|
||||
Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>typedef enum {
|
||||
ZSTD_reset_session_only = 1,
|
||||
ZSTD_reset_parameters = 2,
|
||||
@@ -672,42 +417,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>typedef enum {
|
||||
ZSTD_e_continue=0, </b>/* collect more data, encoder decides when to output compressed result, for optimal compression ratio */<b>
|
||||
ZSTD_e_flush=1, </b>/* flush any data provided so far,<b>
|
||||
* it creates (at least) one new block, that can be decoded immediately on reception;
|
||||
* frame will continue: any future data can still reference previously compressed data, improving compression. */
|
||||
ZSTD_e_end=2 </b>/* flush any remaining data _and_ close current frame.<b>
|
||||
* note that frame is only closed after compressed data is fully flushed (return value == 0).
|
||||
* After that point, any additional data starts a new frame.
|
||||
* note : each frame is independent (does not reference any content from previous frame). */
|
||||
} ZSTD_EndDirective;
|
||||
</b></pre><BR>
|
||||
<pre><b>size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective endOp);
|
||||
</b><p> Behaves about the same as ZSTD_compressStream, with additional control on end directive.
|
||||
- Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
|
||||
- Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
|
||||
- outpot->pos must be <= dstCapacity, input->pos must be <= srcSize
|
||||
- outpot->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
|
||||
- When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
|
||||
- When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
|
||||
and then immediately returns, just indicating that there is some data remaining to be flushed.
|
||||
The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
|
||||
- Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
|
||||
- @return provides a minimum amount of data remaining to be flushed from internal buffers
|
||||
or an error code, which can be tested using ZSTD_isError().
|
||||
if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
|
||||
This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
|
||||
For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
|
||||
- after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
|
||||
only ZSTD_e_end or ZSTD_e_flush operations are allowed.
|
||||
Before starting a new compression job, or changing compression parameters,
|
||||
it is required to fully flush internal buffers.
|
||||
|
||||
</p></pre><BR>
|
||||
<a name="Chapter6"></a><h2>Advanced decompression API</h2><pre></pre>
|
||||
|
||||
<pre><b>typedef enum {
|
||||
|
||||
@@ -715,7 +425,8 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
* the streaming API will refuse to allocate memory buffer
|
||||
* in order to protect the host from unreasonable memory requirements.
|
||||
* This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
|
||||
* By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) */
|
||||
* By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).
|
||||
* Special: value 0 means "use default maximum windowLog". */
|
||||
|
||||
</b>/* note : additional experimental parameters are also available<b>
|
||||
* within the experimental section of the API.
|
||||
@@ -746,6 +457,347 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
|
||||
</b><p> Return a DCtx to clean state.
|
||||
Session and parameters can be reset jointly or separately.
|
||||
Parameters can only be reset when no active frame is being decompressed.
|
||||
@return : 0, or an error code, which can be tested with ZSTD_isError()
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter7"></a><h2>Streaming</h2><pre></pre>
|
||||
|
||||
<pre><b>typedef struct ZSTD_inBuffer_s {
|
||||
const void* src; </b>/**< start of input buffer */<b>
|
||||
size_t size; </b>/**< size of input buffer */<b>
|
||||
size_t pos; </b>/**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */<b>
|
||||
} ZSTD_inBuffer;
|
||||
</b></pre><BR>
|
||||
<pre><b>typedef struct ZSTD_outBuffer_s {
|
||||
void* dst; </b>/**< start of output buffer */<b>
|
||||
size_t size; </b>/**< size of output buffer */<b>
|
||||
size_t pos; </b>/**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */<b>
|
||||
} ZSTD_outBuffer;
|
||||
</b></pre><BR>
|
||||
<a name="Chapter8"></a><h2>Streaming compression - HowTo</h2><pre>
|
||||
A ZSTD_CStream object is required to track streaming operation.
|
||||
Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
|
||||
ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
|
||||
It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
|
||||
|
||||
For parallel execution, use one separate ZSTD_CStream per thread.
|
||||
|
||||
note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
|
||||
|
||||
Parameters are sticky : when starting a new compression on the same context,
|
||||
it will re-use the same sticky parameters as previous compression session.
|
||||
When in doubt, it's recommended to fully initialize the context before usage.
|
||||
Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),
|
||||
ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to
|
||||
set more specific parameters, the pledged source size, or load a dictionary.
|
||||
|
||||
Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to
|
||||
consume input stream. The function will automatically update both `pos`
|
||||
fields within `input` and `output`.
|
||||
Note that the function may not consume the entire input, for example, because
|
||||
the output buffer is already full, in which case `input.pos < input.size`.
|
||||
The caller must check if input has been entirely consumed.
|
||||
If not, the caller must make some room to receive more compressed data,
|
||||
and then present again remaining input data.
|
||||
note: ZSTD_e_continue is guaranteed to make some forward progress when called,
|
||||
but doesn't guarantee maximal forward progress. This is especially relevant
|
||||
when compressing with multiple threads. The call won't block if it can
|
||||
consume some input, but if it can't it will wait for some, but not all,
|
||||
output to be flushed.
|
||||
@return : provides a minimum amount of data remaining to be flushed from internal buffers
|
||||
or an error code, which can be tested using ZSTD_isError().
|
||||
|
||||
At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
|
||||
using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.
|
||||
Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).
|
||||
In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.
|
||||
You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the
|
||||
operation.
|
||||
note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will
|
||||
block until the flush is complete or the output buffer is full.
|
||||
@return : 0 if internal buffers are entirely flushed,
|
||||
>0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
|
||||
or an error code, which can be tested using ZSTD_isError().
|
||||
|
||||
Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.
|
||||
It will perform a flush and write frame epilogue.
|
||||
The epilogue is required for decoders to consider a frame completed.
|
||||
flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.
|
||||
You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to
|
||||
start a new frame.
|
||||
note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will
|
||||
block until the flush is complete or the output buffer is full.
|
||||
@return : 0 if frame fully completed and fully flushed,
|
||||
>0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
|
||||
or an error code, which can be tested using ZSTD_isError().
|
||||
|
||||
|
||||
<BR></pre>
|
||||
|
||||
<pre><b>typedef ZSTD_CCtx ZSTD_CStream; </b>/**< CCtx and CStream are now effectively same object (>= v1.3.0) */<b>
|
||||
</b></pre><BR>
|
||||
<h3>ZSTD_CStream management functions</h3><pre></pre><b><pre>ZSTD_CStream* ZSTD_createCStream(void);
|
||||
size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
|
||||
</pre></b><BR>
|
||||
<h3>Streaming compression functions</h3><pre></pre><b><pre>typedef enum {
|
||||
ZSTD_e_continue=0, </b>/* collect more data, encoder decides when to output compressed result, for optimal compression ratio */<b>
|
||||
ZSTD_e_flush=1, </b>/* flush any data provided so far,<b>
|
||||
* it creates (at least) one new block, that can be decoded immediately on reception;
|
||||
* frame will continue: any future data can still reference previously compressed data, improving compression.
|
||||
* note : multithreaded compression will block to flush as much output as possible. */
|
||||
ZSTD_e_end=2 </b>/* flush any remaining data _and_ close current frame.<b>
|
||||
* note that frame is only closed after compressed data is fully flushed (return value == 0).
|
||||
* After that point, any additional data starts a new frame.
|
||||
* note : each frame is independent (does not reference any content from previous frame).
|
||||
: note : multithreaded compression will block to flush as much output as possible. */
|
||||
} ZSTD_EndDirective;
|
||||
</pre></b><BR>
|
||||
<pre><b>size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective endOp);
|
||||
</b><p> Behaves about the same as ZSTD_compressStream, with additional control on end directive.
|
||||
- Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
|
||||
- Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
|
||||
- output->pos must be <= dstCapacity, input->pos must be <= srcSize
|
||||
- output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
|
||||
- When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
|
||||
- When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
|
||||
and then immediately returns, just indicating that there is some data remaining to be flushed.
|
||||
The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
|
||||
- Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
|
||||
- @return provides a minimum amount of data remaining to be flushed from internal buffers
|
||||
or an error code, which can be tested using ZSTD_isError().
|
||||
if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
|
||||
This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
|
||||
For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
|
||||
- after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
|
||||
only ZSTD_e_end or ZSTD_e_flush operations are allowed.
|
||||
Before starting a new compression job, or changing compression parameters,
|
||||
it is required to fully flush internal buffers.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CStreamInSize(void); </b>/**< recommended size for input buffer */<b>
|
||||
</b></pre><BR>
|
||||
<pre><b>size_t ZSTD_CStreamOutSize(void); </b>/**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */<b>
|
||||
</b></pre><BR>
|
||||
<pre><b>size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
|
||||
</b>/*!<b>
|
||||
* Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).
|
||||
* NOTE: The return value is different. ZSTD_compressStream() returns a hint for
|
||||
* the next read size (if non-zero and not an error). ZSTD_compressStream2()
|
||||
* returns the minimum nb of bytes left to flush (if non-zero and not an error).
|
||||
*/
|
||||
size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
</b>/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */<b>
|
||||
size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
</b>/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */<b>
|
||||
size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
</b><p>
|
||||
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
|
||||
ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter9"></a><h2>Streaming decompression - HowTo</h2><pre>
|
||||
A ZSTD_DStream object is required to track streaming operations.
|
||||
Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
|
||||
ZSTD_DStream objects can be re-used multiple times.
|
||||
|
||||
Use ZSTD_initDStream() to start a new decompression operation.
|
||||
@return : recommended first input size
|
||||
Alternatively, use advanced API to set specific properties.
|
||||
|
||||
Use ZSTD_decompressStream() repetitively to consume your input.
|
||||
The function will update both `pos` fields.
|
||||
If `input.pos < input.size`, some input has not been consumed.
|
||||
It's up to the caller to present again remaining data.
|
||||
The function tries to flush all data decoded immediately, respecting output buffer size.
|
||||
If `output.pos < output.size`, decoder has flushed everything it could.
|
||||
But if `output.pos == output.size`, there might be some data left within internal buffers.,
|
||||
In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
|
||||
Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
|
||||
@return : 0 when a frame is completely decoded and fully flushed,
|
||||
or an error code, which can be tested using ZSTD_isError(),
|
||||
or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
|
||||
the return value is a suggested next input size (just a hint for better latency)
|
||||
that will never request more than the remaining frame size.
|
||||
|
||||
<BR></pre>
|
||||
|
||||
<pre><b>typedef ZSTD_DCtx ZSTD_DStream; </b>/**< DCtx and DStream are now effectively same object (>= v1.3.0) */<b>
|
||||
</b></pre><BR>
|
||||
<h3>ZSTD_DStream management functions</h3><pre></pre><b><pre>ZSTD_DStream* ZSTD_createDStream(void);
|
||||
size_t ZSTD_freeDStream(ZSTD_DStream* zds);
|
||||
</pre></b><BR>
|
||||
<h3>Streaming decompression functions</h3><pre></pre><b><pre></pre></b><BR>
|
||||
<pre><b>size_t ZSTD_DStreamInSize(void); </b>/*!< recommended size for input buffer */<b>
|
||||
</b></pre><BR>
|
||||
<pre><b>size_t ZSTD_DStreamOutSize(void); </b>/*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */<b>
|
||||
</b></pre><BR>
|
||||
<a name="Chapter10"></a><h2>Simple dictionary API</h2><pre></pre>
|
||||
|
||||
<pre><b>size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize,
|
||||
int compressionLevel);
|
||||
</b><p> Compression at an explicit compression level using a Dictionary.
|
||||
A dictionary can be any arbitrary data segment (also called a prefix),
|
||||
or a buffer with specified information (see dictBuilder/zdict.h).
|
||||
Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
It's intended for a dictionary used only once.
|
||||
Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize);
|
||||
</b><p> Decompression using a known Dictionary.
|
||||
Dictionary must be identical to the one used during compression.
|
||||
Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
It's intended for a dictionary used only once.
|
||||
Note : When `dict == NULL || dictSize < 8` no dictionary is used.
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter11"></a><h2>Bulk processing dictionary API</h2><pre></pre>
|
||||
|
||||
<pre><b>ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
|
||||
int compressionLevel);
|
||||
</b><p> When compressing multiple messages / blocks using the same dictionary, it's recommended to load it only once.
|
||||
ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup cost.
|
||||
ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
|
||||
`dictBuffer` can be released after ZSTD_CDict creation, because its content is copied within CDict.
|
||||
Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate `dictBuffer` content.
|
||||
Note : A ZSTD_CDict can be created from an empty dictBuffer, but it is inefficient when used to compress small data.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
|
||||
</b><p> Function frees memory allocated by ZSTD_createCDict().
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_CDict* cdict);
|
||||
</b><p> Compression using a digested Dictionary.
|
||||
Recommended when same dictionary is used multiple times.
|
||||
Note : compression level is _decided at dictionary creation time_,
|
||||
and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no)
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
|
||||
</b><p> Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||
dictBuffer can be released after DDict creation, as its content is copied inside DDict.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
|
||||
</b><p> Function frees memory allocated with ZSTD_createDDict()
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_DDict* ddict);
|
||||
</b><p> Decompression using a digested Dictionary.
|
||||
Recommended when same dictionary is used multiple times.
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter12"></a><h2>Dictionary helper functions</h2><pre></pre>
|
||||
|
||||
<pre><b>unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
|
||||
</b><p> Provides the dictID stored within dictionary.
|
||||
if @return == 0, the dictionary is not conformant with Zstandard specification.
|
||||
It can still be loaded, but as a content-only dictionary.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
||||
</b><p> Provides the dictID of the dictionary loaded into `ddict`.
|
||||
If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
||||
Non-conformant dictionaries can still be loaded, but as content-only dictionaries.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
</b><p> Provides the dictID required to decompressed the frame stored within `src`.
|
||||
If @return == 0, the dictID could not be decoded.
|
||||
This could for one of the following reasons :
|
||||
- The frame does not require a dictionary to be decoded (most common case).
|
||||
- The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
|
||||
Note : this use case also happens when using a non-conformant dictionary.
|
||||
- `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
|
||||
- This is not a Zstandard frame.
|
||||
When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code.
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter13"></a><h2>Advanced dictionary and prefix API</h2><pre>
|
||||
This API allows dictionaries to be used with ZSTD_compress2(),
|
||||
ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
|
||||
only reset with the context is reset with ZSTD_reset_parameters or
|
||||
ZSTD_reset_session_and_parameters. Prefixes are single-use.
|
||||
<BR></pre>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
||||
</b><p> Create an internal CDict from `dict` buffer.
|
||||
Decompression will have to use same dictionary.
|
||||
@result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,
|
||||
meaning "return to no-dictionary mode".
|
||||
Note 1 : Dictionary is sticky, it will be used for all future compressed frames.
|
||||
To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters).
|
||||
Note 2 : Loading a dictionary involves building tables.
|
||||
It's also a CPU consuming operation, with non-negligible impact on latency.
|
||||
Tables are dependent on compression parameters, and for this reason,
|
||||
compression parameters can no longer be changed after loading a dictionary.
|
||||
Note 3 :`dict` content will be copied internally.
|
||||
Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.
|
||||
In such a case, dictionary buffer must outlive its users.
|
||||
Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()
|
||||
to precisely select how dictionary content must be interpreted.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
|
||||
</b><p> Reference a prepared dictionary, to be used for all next compressed frames.
|
||||
Note that compression parameters are enforced from within CDict,
|
||||
and supersede any compression parameter previously set within CCtx.
|
||||
The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
|
||||
The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
|
||||
The dictionary will remain valid for future compressed frames using same CCtx.
|
||||
@result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
Special : Referencing a NULL CDict means "return to no-dictionary mode".
|
||||
Note 1 : Currently, only one dictionary can be managed.
|
||||
Referencing a new dictionary effectively "discards" any previous one.
|
||||
Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
|
||||
const void* prefix, size_t prefixSize);
|
||||
</b><p> Reference a prefix (single-usage dictionary) for next compressed frame.
|
||||
A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
|
||||
Decompression will need same prefix to properly regenerate data.
|
||||
Compressing with a prefix is similar in outcome as performing a diff and compressing it,
|
||||
but performs much faster, especially during decompression (compression speed is tunable with compression level).
|
||||
@result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary
|
||||
Note 1 : Prefix buffer is referenced. It **must** outlive compression.
|
||||
Its content must remain unmodified during compression.
|
||||
Note 2 : If the intention is to diff some large src data blob with some prior version of itself,
|
||||
ensure that the window size is large enough to contain the entire source.
|
||||
See ZSTD_c_windowLog.
|
||||
Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.
|
||||
It's a CPU consuming operation, with non-negligible impact on latency.
|
||||
If there is a need to use the same prefix multiple times, consider loadDictionary instead.
|
||||
Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dm_rawContent).
|
||||
Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
||||
</b><p> Create an internal DDict from dict buffer,
|
||||
to be used to decompress next frames.
|
||||
@@ -793,12 +845,14 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
|
||||
</b><p> Return a DCtx to clean state.
|
||||
Session and parameters can be reset jointly or separately.
|
||||
Parameters can only be reset when no active frame is being decompressed.
|
||||
@return : 0, or an error code, which can be tested with ZSTD_isError()
|
||||
|
||||
<pre><b>size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
|
||||
size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
|
||||
size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
|
||||
size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
|
||||
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
|
||||
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
</b><p> These functions give the _current_ memory usage of selected object.
|
||||
Note that object memory usage can evolve (increase or decrease) over time.
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter14"></a><h2>experimental API (static linking only)</h2><pre>
|
||||
@@ -890,12 +944,21 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
ZSTD_dictForceCopy = 2, </b>/* Always copy the dictionary. */<b>
|
||||
} ZSTD_dictAttachPref_e;
|
||||
</b></pre><BR>
|
||||
<pre><b>typedef enum {
|
||||
ZSTD_lcm_auto = 0, </b>/**< Automatically determine the compression mode based on the compression level.<b>
|
||||
* Negative compression levels will be uncompressed, and positive compression
|
||||
* levels will be compressed. */
|
||||
ZSTD_lcm_huffman = 1, </b>/**< Always attempt Huffman compression. Uncompressed literals will still be<b>
|
||||
* emitted if Huffman compression is not profitable. */
|
||||
ZSTD_lcm_uncompressed = 2, </b>/**< Always emit uncompressed literals. */<b>
|
||||
} ZSTD_literalCompressionMode_e;
|
||||
</b></pre><BR>
|
||||
<a name="Chapter15"></a><h2>Frame size functions</h2><pre></pre>
|
||||
|
||||
<pre><b>unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
|
||||
</b><p> `src` should point the start of a series of ZSTD encoded and/or skippable frames
|
||||
</b><p> `src` should point to the start of a series of ZSTD encoded and/or skippable frames
|
||||
`srcSize` must be the _exact_ size of this series
|
||||
(i.e. there should be a frame boundary exactly at `srcSize` bytes after `src`)
|
||||
(i.e. there should be a frame boundary at `src + srcSize`)
|
||||
@return : - decompressed size of all data in all successive frames
|
||||
- if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN
|
||||
- if an error occurred: ZSTD_CONTENTSIZE_ERROR
|
||||
@@ -915,6 +978,21 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
however it does mean that all frame data must be present and valid.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
|
||||
</b><p> `src` should point to the start of a series of ZSTD encoded and/or skippable frames
|
||||
`srcSize` must be the _exact_ size of this series
|
||||
(i.e. there should be a frame boundary at `src + srcSize`)
|
||||
@return : - upper-bound for the decompressed size of all data in all successive frames
|
||||
- if an error occured: ZSTD_CONTENTSIZE_ERROR
|
||||
|
||||
note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame.
|
||||
note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
|
||||
in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.
|
||||
note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:
|
||||
upper-bound = # blocks * min(128 KB, Window_Size)
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
|
||||
</b><p> srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
|
||||
@return : size of the Frame Header,
|
||||
@@ -933,7 +1011,7 @@ size_t ZSTD_estimateDCtxSize(void);
|
||||
It will also consider src size to be arbitrarily "large", which is worst case.
|
||||
If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation.
|
||||
ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
|
||||
ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
Note : CCtx size estimation is only correct for single-threaded compression.
|
||||
</p></pre><BR>
|
||||
|
||||
@@ -946,7 +1024,7 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
|
||||
It will also consider src size to be arbitrarily "large", which is worst case.
|
||||
If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
|
||||
ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
|
||||
ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
Note : CStream size estimation is only correct for single-threaded compression.
|
||||
ZSTD_DStream memory budget depends on window Size.
|
||||
This information can be passed manually, using ZSTD_estimateDStreamSize,
|
||||
@@ -1011,22 +1089,26 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; </b>/**< t
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
</b><p> @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
||||
`estimatedSrcSize` value is optional, select 0 if not known
|
||||
</b><p> @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
||||
`estimatedSrcSize` value is optional, select 0 if not known
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
</b><p> same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
|
||||
All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0
|
||||
</b><p> same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
|
||||
All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
</b><p> Ensure param values remain within authorized range
|
||||
</b><p> Ensure param values remain within authorized range.
|
||||
@return 0 on success, or an error code (can be checked with ZSTD_isError())
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
|
||||
</b><p> optimize params for a given `srcSize` and `dictSize`.
|
||||
both values are optional, select `0` if unknown.
|
||||
`srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
`dictSize` must be `0` when there is no dictionary.
|
||||
cPar can be invalid : all parameters will be clamped within valid range in the @return struct.
|
||||
This function never fails (wide contract)
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
|
||||
@@ -1072,10 +1154,10 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; </b>/**< t
|
||||
size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
|
||||
</b><p> Quick howto :
|
||||
- ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
|
||||
- ZSTD_CCtxParam_setParameter() : Push parameters one by one into
|
||||
an existing ZSTD_CCtx_params structure.
|
||||
This is similar to
|
||||
ZSTD_CCtx_setParameter().
|
||||
- ZSTD_CCtxParams_setParameter() : Push parameters one by one into
|
||||
an existing ZSTD_CCtx_params structure.
|
||||
This is similar to
|
||||
ZSTD_CCtx_setParameter().
|
||||
- ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to
|
||||
an existing CCtx.
|
||||
These parameters will be applied to
|
||||
@@ -1105,7 +1187,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
|
||||
<pre><b>size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
|
||||
</b><p> Similar to ZSTD_CCtx_setParameter.
|
||||
Set one compression parameter, selected by enum ZSTD_cParameter.
|
||||
Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
|
||||
@@ -1113,7 +1195,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtxParam_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
||||
<pre><b>size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
||||
</b><p> Similar to ZSTD_CCtx_getParameter.
|
||||
Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
|
||||
@result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
@@ -1158,30 +1240,6 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
|
||||
it must remain read accessible throughout the lifetime of DDict
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
|
||||
</b><p> Provides the dictID stored within dictionary.
|
||||
if @return == 0, the dictionary is not conformant with Zstandard specification.
|
||||
It can still be loaded, but as a content-only dictionary.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
||||
</b><p> Provides the dictID of the dictionary loaded into `ddict`.
|
||||
If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
||||
Non-conformant dictionaries can still be loaded, but as content-only dictionaries.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
</b><p> Provides the dictID required to decompressed the frame stored within `src`.
|
||||
If @return == 0, the dictID could not be decoded.
|
||||
This could for one of the following reasons :
|
||||
- The frame does not require a dictionary to be decoded (most common case).
|
||||
- The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
|
||||
Note : this use case also happens when using a non-conformant dictionary.
|
||||
- `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
|
||||
- This is not a Zstandard frame.
|
||||
When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
||||
</b><p> Same as ZSTD_DCtx_loadDictionary(),
|
||||
but references `dict` content instead of copying it into `dctx`.
|
||||
@@ -1233,15 +1291,69 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
|
||||
redundant functions will be deprecated, and then at some point removed.
|
||||
<BR></pre>
|
||||
|
||||
<h3>Advanced Streaming compression functions</h3><pre></pre><b><pre>size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); </b>/**< pledgedSrcSize must be correct. If it is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, "0" also disables frame content size field. It may be enabled in the future. */<b>
|
||||
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); </b>/**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.*/<b>
|
||||
<h3>Advanced Streaming compression functions</h3><pre></pre><b><pre></b>/**! ZSTD_initCStream_srcSize() :<b>
|
||||
* This function is deprecated, and equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
|
||||
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
||||
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
||||
*
|
||||
* pledgedSrcSize must be correct. If it is not known at init time, use
|
||||
* ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
|
||||
* "0" also disables frame content size field. It may be enabled in the future.
|
||||
*/
|
||||
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize);
|
||||
</b>/**! ZSTD_initCStream_usingDict() :<b>
|
||||
* This function is deprecated, and is equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
||||
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
|
||||
*
|
||||
* Creates of an internal CDict (incompatible with static CCtx), except if
|
||||
* dict == NULL or dictSize < 8, in which case no dict is used.
|
||||
* Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if
|
||||
* it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
|
||||
*/
|
||||
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel);
|
||||
</b>/**! ZSTD_initCStream_advanced() :<b>
|
||||
* This function is deprecated, and is approximately equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_setZstdParams(zcs, params); // Set the zstd params and leave the rest as-is
|
||||
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
||||
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
|
||||
*
|
||||
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
|
||||
* value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy.
|
||||
*/
|
||||
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize); </b>/**< pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy. */<b>
|
||||
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); </b>/**< note : cdict will just be referenced, and must outlive compression session */<b>
|
||||
size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize); </b>/**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters. pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. */<b>
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize);
|
||||
</b>/**! ZSTD_initCStream_usingCDict() :<b>
|
||||
* This function is deprecated, and equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_refCDict(zcs, cdict);
|
||||
*
|
||||
* note : cdict will just be referenced, and must outlive compression session
|
||||
*/
|
||||
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
|
||||
</b>/**! ZSTD_initCStream_usingCDict_advanced() :<b>
|
||||
* This function is deprecated, and is approximately equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_setZstdFrameParams(zcs, fParams); // Set the zstd frame params and leave the rest as-is
|
||||
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
||||
* ZSTD_CCtx_refCDict(zcs, cdict);
|
||||
*
|
||||
* same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
|
||||
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
|
||||
* value ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
*/
|
||||
size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize);
|
||||
</pre></b><BR>
|
||||
<pre><b>size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
||||
</b><p> start a new frame, using same parameters from previous frame.
|
||||
</b><p> This function is deprecated, and is equivalent to:
|
||||
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
||||
|
||||
start a new frame, using same parameters from previous frame.
|
||||
This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
|
||||
Note that zcs must be init at least once before using ZSTD_resetCStream().
|
||||
If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
@@ -1276,9 +1388,32 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict*
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<h3>Advanced Streaming decompression functions</h3><pre></pre><b><pre>size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); </b>/**< note: no dictionary will be used if dict == NULL or dictSize < 8 */<b>
|
||||
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); </b>/**< note : ddict is referenced, it must outlive decompression session */<b>
|
||||
size_t ZSTD_resetDStream(ZSTD_DStream* zds); </b>/**< re-use decompression parameters from previous init; saves dictionary loading */<b>
|
||||
<h3>Advanced Streaming decompression functions</h3><pre></pre><b><pre></b>/**<b>
|
||||
* This function is deprecated, and is equivalent to:
|
||||
*
|
||||
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
* ZSTD_DCtx_loadDictionary(zds, dict, dictSize);
|
||||
*
|
||||
* note: no dictionary will be used if dict == NULL or dictSize < 8
|
||||
*/
|
||||
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
|
||||
</b>/**<b>
|
||||
* This function is deprecated, and is equivalent to:
|
||||
*
|
||||
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
* ZSTD_DCtx_refDDict(zds, ddict);
|
||||
*
|
||||
* note : ddict is referenced, it must outlive decompression session
|
||||
*/
|
||||
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
|
||||
</b>/**<b>
|
||||
* This function is deprecated, and is equivalent to:
|
||||
*
|
||||
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
*
|
||||
* re-use decompression parameters from previous init; saves dictionary loading
|
||||
*/
|
||||
size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
</pre></b><BR>
|
||||
<a name="Chapter20"></a><h2>Buffer-less and synchronous inner streaming functions</h2><pre>
|
||||
This is an advanced API, giving full control over buffer management, for users which need direct control over memory.
|
||||
@@ -1405,23 +1540,21 @@ typedef struct {
|
||||
unsigned checksumFlag;
|
||||
} ZSTD_frameHeader;
|
||||
</pre></b><BR>
|
||||
<a name="Chapter23"></a><h2>ZSTD_getFrameHeader() :</h2><pre> decode Frame Header, or requires larger `srcSize`.
|
||||
<pre><b>size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); </b>/**< doesn't consume input */<b>
|
||||
</b>/*! ZSTD_getFrameHeader_advanced() :<b>
|
||||
* same as ZSTD_getFrameHeader(),
|
||||
* with added capability to select a format (like ZSTD_f_zstd1_magicless) */
|
||||
size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
|
||||
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); </b>/**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */<b>
|
||||
</b><p> decode Frame Header, or requires larger `srcSize`.
|
||||
@return : 0, `zfhPtr` is correctly filled,
|
||||
>0, `srcSize` is too small, value is wanted `srcSize` amount,
|
||||
or an error code, which can be tested using ZSTD_isError()
|
||||
<BR></pre>
|
||||
|
||||
<pre><b>size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); </b>/**< doesn't consume input */<b>
|
||||
</b></pre><BR>
|
||||
<pre><b>size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
|
||||
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); </b>/**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */<b>
|
||||
</b><p> same as ZSTD_getFrameHeader(),
|
||||
with added capability to select a format (like ZSTD_f_zstd1_magicless)
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
|
||||
</b></pre><BR>
|
||||
<a name="Chapter24"></a><h2>Block level API</h2><pre></pre>
|
||||
<a name="Chapter23"></a><h2>Block level API</h2><pre></pre>
|
||||
|
||||
<pre><b></b><p> Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes).
|
||||
User will have to take in charge required information to regenerate data, such as compressed and content sizes.
|
||||
|
||||
+8
-9
@@ -25,28 +25,28 @@ all: simple_compression simple_decompression \
|
||||
$(LIB) :
|
||||
$(MAKE) -C ../lib libzstd.a
|
||||
|
||||
simple_compression : simple_compression.c utils.h $(LIB)
|
||||
simple_compression : simple_compression.c common.h $(LIB)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||
|
||||
simple_decompression : simple_decompression.c utils.h $(LIB)
|
||||
simple_decompression : simple_decompression.c common.h $(LIB)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||
|
||||
multiple_simple_compression : multiple_simple_compression.c utils.h $(LIB)
|
||||
multiple_simple_compression : multiple_simple_compression.c common.h $(LIB)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||
|
||||
dictionary_compression : dictionary_compression.c utils.h $(LIB)
|
||||
dictionary_compression : dictionary_compression.c common.h $(LIB)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||
|
||||
dictionary_decompression : dictionary_decompression.c utils.h $(LIB)
|
||||
dictionary_decompression : dictionary_decompression.c common.h $(LIB)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||
|
||||
streaming_compression : streaming_compression.c utils.h $(LIB)
|
||||
streaming_compression : streaming_compression.c common.h $(LIB)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||
|
||||
multiple_streaming_compression : multiple_streaming_compression.c utils.h $(LIB)
|
||||
multiple_streaming_compression : multiple_streaming_compression.c common.h $(LIB)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||
|
||||
streaming_decompression : streaming_decompression.c utils.h $(LIB)
|
||||
streaming_decompression : streaming_decompression.c common.h $(LIB)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||
|
||||
streaming_memory_usage : streaming_memory_usage.c $(LIB)
|
||||
@@ -77,7 +77,6 @@ test: all
|
||||
@echo -- Edge cases detection
|
||||
! ./streaming_decompression tmp # invalid input, must fail
|
||||
! ./simple_decompression tmp # invalid input, must fail
|
||||
! ./simple_decompression tmp.zst # unknown input size, must fail
|
||||
touch tmpNull # create 0-size file
|
||||
./simple_compression tmpNull
|
||||
./simple_decompression tmpNull.zst # 0-size frame : must work
|
||||
|
||||
@@ -11,15 +11,15 @@
|
||||
/*
|
||||
* This header file has common utility functions used in examples.
|
||||
*/
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <stdlib.h> // malloc, free, exit
|
||||
#include <stdio.h> // fprintf, perror, fopen, etc.
|
||||
#include <string.h> // strlen, strcat, memset, strerror
|
||||
#include <string.h> // strerror
|
||||
#include <errno.h> // errno
|
||||
#include <assert.h> // assert
|
||||
#include <sys/stat.h> // stat
|
||||
#include <zstd.h>
|
||||
|
||||
/*
|
||||
* Define the returned error code from utility functions.
|
||||
@@ -34,7 +34,34 @@ typedef enum {
|
||||
ERROR_saveFile = 7,
|
||||
ERROR_malloc = 8,
|
||||
ERROR_largeFile = 9,
|
||||
} UTILS_ErrorCode;
|
||||
} COMMON_ErrorCode;
|
||||
|
||||
/*! CHECK
|
||||
* Check that the condition holds. If it doesn't print a message and die.
|
||||
*/
|
||||
#define CHECK(cond, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
fprintf(stderr, \
|
||||
"%s:%d CHECK(%s) failed: ", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#cond); \
|
||||
fprintf(stderr, "" __VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*! CHECK_ZSTD
|
||||
* Check the zstd error code and die if an error occurred after printing a
|
||||
* message.
|
||||
*/
|
||||
#define CHECK_ZSTD(fn, ...) \
|
||||
do { \
|
||||
size_t const err = (fn); \
|
||||
CHECK(!ZSTD_isError(err), "%s", ZSTD_getErrorName(err)); \
|
||||
} while (0)
|
||||
|
||||
/*! fsize_orDie() :
|
||||
* Get the size of a given file path.
|
||||
@@ -56,7 +83,7 @@ static size_t fsize_orDie(const char *filename)
|
||||
* 2. if off_t -> size_t type conversion results in discrepancy,
|
||||
* the file size is too large for type size_t.
|
||||
*/
|
||||
if ((fileSize < 0) || (fileSize != (off_t)size)) {
|
||||
if ((fileSize < 0) || (fileSize != (off_t)size)) {
|
||||
fprintf(stderr, "%s : filesize too large \n", filename);
|
||||
exit(ERROR_largeFile);
|
||||
}
|
||||
@@ -150,10 +177,10 @@ static void* malloc_orDie(size_t size)
|
||||
* @return If successful this function will load file into buffer and
|
||||
* return file size, otherwise it will printout an error to stderr and exit.
|
||||
*/
|
||||
static size_t loadFile_orDie(const char* fileName, void* buffer, int bufferSize)
|
||||
static size_t loadFile_orDie(const char* fileName, void* buffer, size_t bufferSize)
|
||||
{
|
||||
size_t const fileSize = fsize_orDie(fileName);
|
||||
assert(fileSize <= bufferSize);
|
||||
CHECK(fileSize <= bufferSize, "File too large!");
|
||||
|
||||
FILE* const inFile = fopen_orDie(fileName, "rb");
|
||||
size_t const readSize = fread(buffer, 1, fileSize, inFile);
|
||||
@@ -7,13 +7,11 @@
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
#include <stdlib.h> // malloc, exit
|
||||
#include <stdio.h> // printf
|
||||
#include <string.h> // strerror
|
||||
#include <errno.h> // errno
|
||||
#include <sys/stat.h> // stat
|
||||
#include <stdlib.h> // free
|
||||
#include <string.h> // memset, strcat
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "utils.h"
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
/* createDict() :
|
||||
`dictFileName` is supposed to have been created using `zstd --train` */
|
||||
@@ -23,10 +21,7 @@ static ZSTD_CDict* createCDict_orDie(const char* dictFileName, int cLevel)
|
||||
printf("loading dictionary %s \n", dictFileName);
|
||||
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
|
||||
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel);
|
||||
if (!cdict) {
|
||||
fprintf(stderr, "ZSTD_createCDict error \n");
|
||||
exit(7);
|
||||
}
|
||||
CHECK(cdict != NULL, "ZSTD_createCDict() failed!");
|
||||
free(dictBuffer);
|
||||
return cdict;
|
||||
}
|
||||
@@ -39,13 +34,16 @@ static void compress(const char* fname, const char* oname, const ZSTD_CDict* cdi
|
||||
size_t const cBuffSize = ZSTD_compressBound(fSize);
|
||||
void* const cBuff = malloc_orDie(cBuffSize);
|
||||
|
||||
/* Compress using the dictionary.
|
||||
* This function writes the dictionary id, and content size into the header.
|
||||
* But, it doesn't use a checksum. You can control these options using the
|
||||
* advanced API: ZSTD_CCtx_setParameter(), ZSTD_CCtx_refCDict(),
|
||||
* and ZSTD_compress2().
|
||||
*/
|
||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); }
|
||||
CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||
size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict);
|
||||
if (ZSTD_isError(cSize)) {
|
||||
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
|
||||
exit(7);
|
||||
}
|
||||
CHECK_ZSTD(cSize);
|
||||
|
||||
saveFile_orDie(oname, cBuff, cSize);
|
||||
|
||||
|
||||
@@ -9,15 +9,10 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h> // malloc, exit
|
||||
#include <stdio.h> // printf
|
||||
#include <string.h> // strerror
|
||||
#include <errno.h> // errno
|
||||
#include <sys/stat.h> // stat
|
||||
#define ZSTD_STATIC_LINKING_ONLY // ZSTD_findDecompressedSize
|
||||
#include <stdlib.h> // free
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "utils.h"
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
/* createDict() :
|
||||
`dictFileName` is supposed to have been created using `zstd --train` */
|
||||
@@ -27,7 +22,7 @@ static ZSTD_DDict* createDict_orDie(const char* dictFileName)
|
||||
printf("loading dictionary %s \n", dictFileName);
|
||||
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
|
||||
ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize);
|
||||
if (ddict==NULL) { fprintf(stderr, "ZSTD_createDDict error \n"); exit(5); }
|
||||
CHECK(ddict != NULL, "ZSTD_createDDict() failed!");
|
||||
free(dictBuffer);
|
||||
return ddict;
|
||||
}
|
||||
@@ -36,24 +31,40 @@ static void decompress(const char* fname, const ZSTD_DDict* ddict)
|
||||
{
|
||||
size_t cSize;
|
||||
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
|
||||
unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize);
|
||||
if (rSize==ZSTD_CONTENTSIZE_ERROR) {
|
||||
fprintf(stderr, "%s : it was not compressed by zstd.\n", fname);
|
||||
exit(5);
|
||||
} else if (rSize==ZSTD_CONTENTSIZE_UNKNOWN) {
|
||||
fprintf(stderr, "%s : original size unknown \n", fname);
|
||||
exit(6);
|
||||
}
|
||||
|
||||
/* Read the content size from the frame header. For simplicity we require
|
||||
* that it is always present. By default, zstd will write the content size
|
||||
* in the header when it is known. If you can't guarantee that the frame
|
||||
* content size is always written into the header, either use streaming
|
||||
* decompression, or ZSTD_decompressBound().
|
||||
*/
|
||||
unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
|
||||
CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, "%s: not compressed by zstd!", fname);
|
||||
CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, "%s: original size unknown!", fname);
|
||||
void* const rBuff = malloc_orDie((size_t)rSize);
|
||||
|
||||
/* Check that the dictionary ID matches.
|
||||
* If a non-zstd dictionary is used, then both will be zero.
|
||||
* By default zstd always writes the dictionary ID into the frame.
|
||||
* Zstd will check if there is a dictionary ID mismatch as well.
|
||||
*/
|
||||
unsigned const expectedDictID = ZSTD_getDictID_fromDDict(ddict);
|
||||
unsigned const actualDictID = ZSTD_getDictID_fromFrame(cBuff, cSize);
|
||||
CHECK(actualDictID == expectedDictID,
|
||||
"DictID mismatch: expected %u got %u",
|
||||
expectedDictID,
|
||||
actualDictID);
|
||||
|
||||
/* Decompress using the dictionary.
|
||||
* If you need to control the decompression parameters, then use the
|
||||
* advanced API: ZSTD_DCtx_setParameter(), ZSTD_DCtx_refDDict(), and
|
||||
* ZSTD_decompressDCtx().
|
||||
*/
|
||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||
if (dctx==NULL) { fprintf(stderr, "ZSTD_createDCtx() error \n"); exit(10); }
|
||||
CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
|
||||
size_t const dSize = ZSTD_decompress_usingDDict(dctx, rBuff, rSize, cBuff, cSize, ddict);
|
||||
if (dSize != rSize) {
|
||||
fprintf(stderr, "error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize));
|
||||
exit(7);
|
||||
}
|
||||
CHECK_ZSTD(dSize);
|
||||
/* When zstd knows the content size, it will error if it doesn't match. */
|
||||
CHECK(dSize == rSize, "Impossible because zstd will check this condition!");
|
||||
|
||||
/* success */
|
||||
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
|
||||
|
||||
@@ -8,13 +8,11 @@
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // malloc, free, exit
|
||||
#include <stdio.h> // fprintf, perror, fopen, etc.
|
||||
#include <string.h> // strlen, strcat, memset, strerror
|
||||
#include <errno.h> // errno
|
||||
#include <sys/stat.h> // stat
|
||||
#include <stdio.h> // printf
|
||||
#include <stdlib.h> // free
|
||||
#include <string.h> // memcpy, strlen
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "utils.h"
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
typedef struct {
|
||||
void* fBuffer;
|
||||
@@ -28,7 +26,7 @@ typedef struct {
|
||||
* allocate memory for buffers big enough to compress all files
|
||||
* as well as memory for output file name (ofn)
|
||||
*/
|
||||
static resources createResources_orDie(int argc, const char** argv, char **ofn, int* ofnBufferLen)
|
||||
static resources createResources_orDie(int argc, const char** argv, char **ofn, size_t* ofnBufferLen)
|
||||
{
|
||||
size_t maxFilenameLength=0;
|
||||
size_t maxFileSize = 0;
|
||||
@@ -52,7 +50,7 @@ static resources createResources_orDie(int argc, const char** argv, char **ofn,
|
||||
ress.fBuffer = malloc_orDie(ress.fBufferSize);
|
||||
ress.cBuffer = malloc_orDie(ress.cBufferSize);
|
||||
ress.cctx = ZSTD_createCCtx();
|
||||
if (ress.cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); }
|
||||
CHECK(ress.cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||
return ress;
|
||||
}
|
||||
|
||||
@@ -69,16 +67,17 @@ static void compressFile_orDie(resources ress, const char* fname, const char* on
|
||||
{
|
||||
size_t fSize = loadFile_orDie(fname, ress.fBuffer, ress.fBufferSize);
|
||||
|
||||
/* Compress using the context.
|
||||
* If you need more control over parameters, use the advanced API:
|
||||
* ZSTD_CCtx_setParameter(), and ZSTD_compress2().
|
||||
*/
|
||||
size_t const cSize = ZSTD_compressCCtx(ress.cctx, ress.cBuffer, ress.cBufferSize, ress.fBuffer, fSize, 1);
|
||||
if (ZSTD_isError(cSize)) {
|
||||
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
|
||||
exit(8);
|
||||
}
|
||||
CHECK_ZSTD(cSize);
|
||||
|
||||
saveFile_orDie(oname, ress.cBuffer, cSize);
|
||||
|
||||
/* success */
|
||||
// printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname);
|
||||
printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname);
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
@@ -94,21 +93,21 @@ int main(int argc, const char** argv)
|
||||
|
||||
/* memory allocation for outFilename and resources */
|
||||
char* outFilename;
|
||||
int outFilenameBufferLen;
|
||||
resources const ress = createResources_orDie(argc, argv, &outFilename, &outFilenameBufferLen);
|
||||
size_t outFilenameBufferLen;
|
||||
resources const ress = createResources_orDie(argc, argv, &outFilename, &outFilenameBufferLen);
|
||||
|
||||
/* compress files with shared context, input and output buffers */
|
||||
int argNb;
|
||||
for (argNb = 1; argNb < argc; argNb++) {
|
||||
const char* const inFilename = argv[argNb];
|
||||
int inFilenameLen = strlen(inFilename);
|
||||
assert(inFilenameLen + 5 <= outFilenameBufferLen);
|
||||
size_t const inFilenameLen = strlen(inFilename);
|
||||
CHECK(inFilenameLen + 5 <= outFilenameBufferLen, "File name too long!");
|
||||
memcpy(outFilename, inFilename, inFilenameLen);
|
||||
memcpy(outFilename+inFilenameLen, ".zst", 5);
|
||||
compressFile_orDie(ress, inFilename, outFilename);
|
||||
}
|
||||
|
||||
/* free momery */
|
||||
/* free memory */
|
||||
freeResources(ress,outFilename);
|
||||
|
||||
printf("compressed %i files \n", argc-1);
|
||||
|
||||
@@ -14,66 +14,80 @@
|
||||
* All structures and buffers will be created only once,
|
||||
* and shared across all compression operations */
|
||||
|
||||
#include <stdlib.h> // malloc, exit
|
||||
#include <stdio.h> // fprintf, perror, feof
|
||||
#include <string.h> // strerror
|
||||
#include <errno.h> // errno
|
||||
#define ZSTD_STATIC_LINKING_ONLY // streaming API defined as "experimental" for the time being
|
||||
#include <stdio.h> // printf
|
||||
#include <stdlib.h> // free
|
||||
#include <string.h> // memset, strcat
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "utils.h"
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
typedef struct {
|
||||
void* buffIn;
|
||||
void* buffOut;
|
||||
size_t buffInSize;
|
||||
size_t buffOutSize;
|
||||
ZSTD_CStream* cstream;
|
||||
} resources ;
|
||||
ZSTD_CCtx* cctx;
|
||||
} resources;
|
||||
|
||||
static resources createResources_orDie()
|
||||
static resources createResources_orDie(int cLevel)
|
||||
{
|
||||
resources ress;
|
||||
ress.buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */
|
||||
ress.buffOutSize= ZSTD_CStreamOutSize(); /* can always flush a full block */
|
||||
ress.buffIn = malloc_orDie(ress.buffInSize);
|
||||
ress.buffOut= malloc_orDie(ress.buffOutSize);
|
||||
ress.cstream = ZSTD_createCStream();
|
||||
if (ress.cstream==NULL) { fprintf(stderr, "ZSTD_createCStream() error \n"); exit(10); }
|
||||
ress.cctx = ZSTD_createCCtx();
|
||||
CHECK(ress.cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||
|
||||
/* Set any compression parameters you want here.
|
||||
* They will persist for every compression operation.
|
||||
* Here we set the compression level, and enable the checksum.
|
||||
*/
|
||||
CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) );
|
||||
CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, 1) );
|
||||
return ress;
|
||||
}
|
||||
|
||||
static void freeResources(resources ress)
|
||||
{
|
||||
ZSTD_freeCStream(ress.cstream);
|
||||
ZSTD_freeCCtx(ress.cctx);
|
||||
free(ress.buffIn);
|
||||
free(ress.buffOut);
|
||||
}
|
||||
|
||||
static void compressFile_orDie(resources ress, const char* fname, const char* outName, int cLevel)
|
||||
static void compressFile_orDie(resources ress, const char* fname, const char* outName)
|
||||
{
|
||||
// Open the input and output files.
|
||||
FILE* const fin = fopen_orDie(fname, "rb");
|
||||
FILE* const fout = fopen_orDie(outName, "wb");
|
||||
|
||||
size_t const initResult = ZSTD_initCStream(ress.cstream, cLevel);
|
||||
if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initCStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); }
|
||||
/* Reset the context to a clean state to start a new compression operation.
|
||||
* The parameters are sticky, so we keep the compression level and extra
|
||||
* parameters that we set in createResources_orDie().
|
||||
*/
|
||||
CHECK_ZSTD( ZSTD_CCtx_reset(ress.cctx, ZSTD_reset_session_only) );
|
||||
|
||||
size_t const toRead = ress.buffInSize;
|
||||
size_t read;
|
||||
while ( (read = fread_orDie(ress.buffIn, toRead, fin)) ) {
|
||||
/* This loop is the same as streaming_compression.c.
|
||||
* See that file for detailed comments.
|
||||
*/
|
||||
int const lastChunk = (read < toRead);
|
||||
ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;
|
||||
|
||||
size_t read, toRead = ress.buffInSize;
|
||||
while( (read = fread_orDie(ress.buffIn, toRead, fin)) ) {
|
||||
ZSTD_inBuffer input = { ress.buffIn, read, 0 };
|
||||
while (input.pos < input.size) {
|
||||
int finished;
|
||||
do {
|
||||
ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 };
|
||||
toRead = ZSTD_compressStream(ress.cstream, &output , &input); /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */
|
||||
if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_compressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); }
|
||||
if (toRead > ress.buffInSize) toRead = ress.buffInSize; /* Safely handle when `buffInSize` is manually changed to a smaller value */
|
||||
size_t const remaining = ZSTD_compressStream2(ress.cctx, &output, &input, mode);
|
||||
CHECK_ZSTD(remaining);
|
||||
fwrite_orDie(ress.buffOut, output.pos, fout);
|
||||
}
|
||||
finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
|
||||
} while (!finished);
|
||||
CHECK(input.pos == input.size,
|
||||
"Impossible: zstd only returns 0 when the input is completely consumed!");
|
||||
}
|
||||
|
||||
ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 };
|
||||
size_t const remainingToFlush = ZSTD_endStream(ress.cstream, &output); /* close frame */
|
||||
if (remainingToFlush) { fprintf(stderr, "not fully flushed"); exit(13); }
|
||||
fwrite_orDie(ress.buffOut, output.pos, fout);
|
||||
|
||||
fclose_orDie(fout);
|
||||
fclose_orDie(fin);
|
||||
}
|
||||
@@ -89,7 +103,8 @@ int main(int argc, const char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
resources const ress = createResources_orDie();
|
||||
int const cLevel = 7;
|
||||
resources const ress = createResources_orDie(cLevel);
|
||||
void* ofnBuffer = NULL;
|
||||
size_t ofnbSize = 0;
|
||||
|
||||
@@ -106,7 +121,7 @@ int main(int argc, const char** argv)
|
||||
memset(ofnBuffer, 0, ofnSize);
|
||||
strcat(ofnBuffer, ifn);
|
||||
strcat(ofnBuffer, ".zst");
|
||||
compressFile_orDie(ress, ifn, ofnBuffer, 7);
|
||||
compressFile_orDie(ress, ifn, ofnBuffer);
|
||||
}
|
||||
|
||||
freeResources(ress);
|
||||
|
||||
@@ -8,13 +8,11 @@
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // malloc, free, exit
|
||||
#include <stdio.h> // fprintf, perror, fopen, etc.
|
||||
#include <string.h> // strlen, strcat, memset, strerror
|
||||
#include <errno.h> // errno
|
||||
#include <sys/stat.h> // stat
|
||||
#include <stdio.h> // printf
|
||||
#include <stdlib.h> // free
|
||||
#include <string.h> // strlen, strcat, memset
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "utils.h"
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
static void compress_orDie(const char* fname, const char* oname)
|
||||
{
|
||||
@@ -23,11 +21,12 @@ static void compress_orDie(const char* fname, const char* oname)
|
||||
size_t const cBuffSize = ZSTD_compressBound(fSize);
|
||||
void* const cBuff = malloc_orDie(cBuffSize);
|
||||
|
||||
/* Compress.
|
||||
* If you are doing many compressions, you may want to reuse the context.
|
||||
* See the multiple_simple_compression.c example.
|
||||
*/
|
||||
size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1);
|
||||
if (ZSTD_isError(cSize)) {
|
||||
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
|
||||
exit(8);
|
||||
}
|
||||
CHECK_ZSTD(cSize);
|
||||
|
||||
saveFile_orDie(oname, cBuff, cSize);
|
||||
|
||||
|
||||
@@ -8,37 +8,36 @@
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // malloc, exit
|
||||
#include <stdio.h> // printf
|
||||
#include <string.h> // strerror
|
||||
#include <errno.h> // errno
|
||||
#include <sys/stat.h> // stat
|
||||
#define ZSTD_STATIC_LINKING_ONLY // ZSTD_findDecompressedSize
|
||||
#include <stdlib.h> // free
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "utils.h"
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
static void decompress(const char* fname)
|
||||
{
|
||||
size_t cSize;
|
||||
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
|
||||
unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize);
|
||||
if (rSize==ZSTD_CONTENTSIZE_ERROR) {
|
||||
fprintf(stderr, "%s : it was not compressed by zstd.\n", fname);
|
||||
exit(5);
|
||||
} else if (rSize==ZSTD_CONTENTSIZE_UNKNOWN) {
|
||||
fprintf(stderr,
|
||||
"%s : original size unknown. Use streaming decompression instead.\n", fname);
|
||||
exit(6);
|
||||
}
|
||||
/* Read the content size from the frame header. For simplicity we require
|
||||
* that it is always present. By default, zstd will write the content size
|
||||
* in the header when it is known. If you can't guarantee that the frame
|
||||
* content size is always written into the header, either use streaming
|
||||
* decompression, or ZSTD_decompressBound().
|
||||
*/
|
||||
unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
|
||||
CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, "%s: not compressed by zstd!", fname);
|
||||
CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, "%s: original size unknown!", fname);
|
||||
|
||||
void* const rBuff = malloc_orDie((size_t)rSize);
|
||||
|
||||
/* Decompress.
|
||||
* If you are doing many decompressions, you may want to reuse the context
|
||||
* and use ZSTD_decompressDCtx(). If you want to set advanced parameters,
|
||||
* use ZSTD_DCtx_setParameter().
|
||||
*/
|
||||
size_t const dSize = ZSTD_decompress(rBuff, rSize, cBuff, cSize);
|
||||
|
||||
if (dSize != rSize) {
|
||||
fprintf(stderr, "error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize));
|
||||
exit(7);
|
||||
}
|
||||
CHECK_ZSTD(dSize);
|
||||
/* When zstd knows the content size, it will error if it doesn't match. */
|
||||
CHECK(dSize == rSize, "Impossible because zstd will check this condition!");
|
||||
|
||||
/* success */
|
||||
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
|
||||
|
||||
@@ -9,54 +9,79 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h> // malloc, free, exit
|
||||
#include <stdio.h> // fprintf, perror, feof, fopen, etc.
|
||||
#include <string.h> // strlen, memset, strcat
|
||||
#include <stdio.h> // printf
|
||||
#include <stdlib.h> // free
|
||||
#include <string.h> // memset, strcat, strlen
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "utils.h"
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
|
||||
static void compressFile_orDie(const char* fname, const char* outName, int cLevel)
|
||||
{
|
||||
/* Open the input and output files. */
|
||||
FILE* const fin = fopen_orDie(fname, "rb");
|
||||
FILE* const fout = fopen_orDie(outName, "wb");
|
||||
size_t const buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */
|
||||
/* Create the input and output buffers.
|
||||
* They may be any size, but we recommend using these functions to size them.
|
||||
* Performance will only suffer significantly for very tiny buffers.
|
||||
*/
|
||||
size_t const buffInSize = ZSTD_CStreamInSize();
|
||||
void* const buffIn = malloc_orDie(buffInSize);
|
||||
size_t const buffOutSize = ZSTD_CStreamOutSize(); /* can always flush a full block */
|
||||
size_t const buffOutSize = ZSTD_CStreamOutSize();
|
||||
void* const buffOut = malloc_orDie(buffOutSize);
|
||||
|
||||
ZSTD_CStream* const cstream = ZSTD_createCStream();
|
||||
if (cstream==NULL) { fprintf(stderr, "ZSTD_createCStream() error \n"); exit(10); }
|
||||
size_t const initResult = ZSTD_initCStream(cstream, cLevel);
|
||||
if (ZSTD_isError(initResult)) {
|
||||
fprintf(stderr, "ZSTD_initCStream() error : %s \n",
|
||||
ZSTD_getErrorName(initResult));
|
||||
exit(11);
|
||||
}
|
||||
/* Create the context. */
|
||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||
|
||||
size_t read, toRead = buffInSize;
|
||||
while( (read = fread_orDie(buffIn, toRead, fin)) ) {
|
||||
/* Set any parameters you want.
|
||||
* Here we set the compression level, and enable the checksum.
|
||||
*/
|
||||
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel) );
|
||||
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) );
|
||||
|
||||
/* This loop read from the input file, compresses that entire chunk,
|
||||
* and writes all output produced to the output file.
|
||||
*/
|
||||
size_t const toRead = buffInSize;
|
||||
size_t read;
|
||||
while ((read = fread_orDie(buffIn, toRead, fin))) {
|
||||
/* Select the flush mode.
|
||||
* If the read may not be finished (read == toRead) we use
|
||||
* ZSTD_e_continue. If this is the last chunk, we use ZSTD_e_end.
|
||||
* Zstd optimizes the case where the first flush mode is ZSTD_e_end,
|
||||
* since it knows it is compressing the entire source in one pass.
|
||||
*/
|
||||
int const lastChunk = (read < toRead);
|
||||
ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;
|
||||
/* Set the input buffer to what we just read.
|
||||
* We compress until the input buffer is empty, each time flushing the
|
||||
* output.
|
||||
*/
|
||||
ZSTD_inBuffer input = { buffIn, read, 0 };
|
||||
while (input.pos < input.size) {
|
||||
int finished;
|
||||
do {
|
||||
/* Compress into the output buffer and write all of the output to
|
||||
* the file so we can reuse the buffer next iteration.
|
||||
*/
|
||||
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
|
||||
toRead = ZSTD_compressStream(cstream, &output , &input); /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */
|
||||
if (ZSTD_isError(toRead)) {
|
||||
fprintf(stderr, "ZSTD_compressStream() error : %s \n",
|
||||
ZSTD_getErrorName(toRead));
|
||||
exit(12);
|
||||
}
|
||||
if (toRead > buffInSize) toRead = buffInSize; /* Safely handle case when `buffInSize` is manually changed to a value < ZSTD_CStreamInSize()*/
|
||||
size_t const remaining = ZSTD_compressStream2(cctx, &output , &input, mode);
|
||||
CHECK_ZSTD(remaining);
|
||||
fwrite_orDie(buffOut, output.pos, fout);
|
||||
}
|
||||
/* If we're on the last chunk we're finished when zstd returns 0,
|
||||
* which means its consumed all the input AND finished the frame.
|
||||
* Otherwise, we're finished when we've consumed all the input.
|
||||
*/
|
||||
finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
|
||||
} while (!finished);
|
||||
CHECK(input.pos == input.size,
|
||||
"Impossible: zstd only returns 0 when the input is completely consumed!");
|
||||
}
|
||||
|
||||
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
|
||||
size_t const remainingToFlush = ZSTD_endStream(cstream, &output); /* close frame */
|
||||
if (remainingToFlush) { fprintf(stderr, "not fully flushed"); exit(13); }
|
||||
fwrite_orDie(buffOut, output.pos, fout);
|
||||
|
||||
ZSTD_freeCStream(cstream);
|
||||
ZSTD_freeCCtx(cctx);
|
||||
fclose_orDie(fout);
|
||||
fclose_orDie(fin); free(buffIn);
|
||||
fclose_orDie(fin);
|
||||
free(buffIn);
|
||||
free(buffOut);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,10 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h> // malloc, exit
|
||||
#include <stdio.h> // fprintf, perror, feof
|
||||
#include <string.h> // strerror
|
||||
#include <errno.h> // errno
|
||||
#include <stdio.h> // fprintf
|
||||
#include <stdlib.h> // free
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "utils.h"
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
static void decompressFile_orDie(const char* fname)
|
||||
{
|
||||
@@ -25,26 +23,40 @@ static void decompressFile_orDie(const char* fname)
|
||||
size_t const buffOutSize = ZSTD_DStreamOutSize(); /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */
|
||||
void* const buffOut = malloc_orDie(buffOutSize);
|
||||
|
||||
ZSTD_DStream* const dstream = ZSTD_createDStream();
|
||||
if (dstream==NULL) { fprintf(stderr, "ZSTD_createDStream() error \n"); exit(10); }
|
||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||
CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
|
||||
|
||||
/* In more complex scenarios, a file may consist of multiple appended frames (ex : pzstd).
|
||||
* The following example decompresses only the first frame.
|
||||
* It is compatible with other provided streaming examples */
|
||||
size_t const initResult = ZSTD_initDStream(dstream);
|
||||
if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initDStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); }
|
||||
size_t read, toRead = initResult;
|
||||
/* This loop assumes that the input file is one or more concatenated zstd
|
||||
* streams. This example won't work if there is trailing non-zstd data at
|
||||
* the end, but streaming decompression in general handles this case.
|
||||
* ZSTD_decompressStream() returns 0 exactly when the frame is completed,
|
||||
* and doesn't consume input after the frame.
|
||||
*/
|
||||
size_t const toRead = buffInSize;
|
||||
size_t read;
|
||||
while ( (read = fread_orDie(buffIn, toRead, fin)) ) {
|
||||
ZSTD_inBuffer input = { buffIn, read, 0 };
|
||||
/* Given a valid frame, zstd won't consume the last byte of the frame
|
||||
* until it has flushed all of the decompressed data of the frame.
|
||||
* Therefore, instead of checking if the return code is 0, we can
|
||||
* decompress just check if input.pos < input.size.
|
||||
*/
|
||||
while (input.pos < input.size) {
|
||||
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
|
||||
toRead = ZSTD_decompressStream(dstream, &output , &input); /* toRead : size of next compressed block */
|
||||
if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_decompressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); }
|
||||
/* The return code is zero if the frame is complete, but there may
|
||||
* be multiple frames concatenated together. Zstd will automatically
|
||||
* reset the context when a frame is complete. Still, calling
|
||||
* ZSTD_DCtx_reset() can be useful to reset the context to a clean
|
||||
* state, for instance if the last decompression call returned an
|
||||
* error.
|
||||
*/
|
||||
size_t const ret = ZSTD_decompressStream(dctx, &output , &input);
|
||||
CHECK_ZSTD(ret);
|
||||
fwrite_orDie(buffOut, output.pos, fout);
|
||||
}
|
||||
}
|
||||
|
||||
ZSTD_freeDStream(dstream);
|
||||
ZSTD_freeDCtx(dctx);
|
||||
fclose_orDie(fin);
|
||||
fclose_orDie(fout);
|
||||
free(buffIn);
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
|
||||
/*=== Dependencies ===*/
|
||||
#include <stdio.h> /* printf */
|
||||
#include <stdio.h> // printf
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
#include "zstd.h"
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
|
||||
/*=== functions ===*/
|
||||
@@ -61,90 +62,75 @@ int main(int argc, char const *argv[]) {
|
||||
char const dataToCompress[INPUT_SIZE] = "abcde";
|
||||
char compressedData[COMPRESSED_SIZE];
|
||||
char decompressedData[INPUT_SIZE];
|
||||
ZSTD_CStream* const cstream = ZSTD_createCStream();
|
||||
if (cstream==NULL) {
|
||||
printf("Level %i : ZSTD_CStream Memory allocation failure \n", compressionLevel);
|
||||
return 1;
|
||||
}
|
||||
/* the ZSTD_CCtx_params structure is a way to save parameters and use
|
||||
* them across multiple contexts. We use them here so we can call the
|
||||
* function ZSTD_estimateCStreamSize_usingCCtxParams().
|
||||
*/
|
||||
ZSTD_CCtx_params* const cctxParams = ZSTD_createCCtxParams();
|
||||
CHECK(cctxParams != NULL, "ZSTD_createCCtxParams() failed!");
|
||||
|
||||
/* forces compressor to use maximum memory size for given compression level,
|
||||
* by not providing any information on input size */
|
||||
ZSTD_parameters params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
||||
if (wLog) { /* special mode : specific wLog */
|
||||
printf("Using custom compression parameter : level 1 + wLog=%u \n", wLog);
|
||||
params = ZSTD_getParams(1 /*compressionLevel*/,
|
||||
1 << wLog /*estimatedSrcSize*/,
|
||||
0 /*no dictionary*/);
|
||||
size_t const error = ZSTD_initCStream_advanced(cstream, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN);
|
||||
if (ZSTD_isError(error)) {
|
||||
printf("ZSTD_initCStream_advanced error : %s \n", ZSTD_getErrorName(error));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
size_t const error = ZSTD_initCStream(cstream, compressionLevel);
|
||||
if (ZSTD_isError(error)) {
|
||||
printf("ZSTD_initCStream error : %s \n", ZSTD_getErrorName(error));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* Set the compression level. */
|
||||
CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_compressionLevel, compressionLevel) );
|
||||
/* Set the window log.
|
||||
* The value 0 means use the default window log, which is equivalent to
|
||||
* not setting it.
|
||||
*/
|
||||
CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, wLog) );
|
||||
|
||||
/* Force the compressor to allocate the maximum memory size for a given
|
||||
* level by not providing the pledged source size, or calling
|
||||
* ZSTD_compressStream2() with ZSTD_e_end.
|
||||
*/
|
||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||
CHECK_ZSTD( ZSTD_CCtx_setParametersUsingCCtxParams(cctx, cctxParams) );
|
||||
size_t compressedSize;
|
||||
{ ZSTD_inBuffer inBuff = { dataToCompress, sizeof(dataToCompress), 0 };
|
||||
{
|
||||
ZSTD_inBuffer inBuff = { dataToCompress, sizeof(dataToCompress), 0 };
|
||||
ZSTD_outBuffer outBuff = { compressedData, sizeof(compressedData), 0 };
|
||||
size_t const cError = ZSTD_compressStream(cstream, &outBuff, &inBuff);
|
||||
if (ZSTD_isError(cError)) {
|
||||
printf("ZSTD_compressStream error : %s \n", ZSTD_getErrorName(cError));
|
||||
return 1;
|
||||
}
|
||||
size_t const fError = ZSTD_endStream(cstream, &outBuff);
|
||||
if (ZSTD_isError(fError)) {
|
||||
printf("ZSTD_endStream error : %s \n", ZSTD_getErrorName(fError));
|
||||
return 1;
|
||||
}
|
||||
CHECK_ZSTD( ZSTD_compressStream(cctx, &outBuff, &inBuff) );
|
||||
size_t const remaining = ZSTD_endStream(cctx, &outBuff);
|
||||
CHECK_ZSTD(remaining);
|
||||
CHECK(remaining == 0, "Frame not flushed!");
|
||||
compressedSize = outBuff.pos;
|
||||
}
|
||||
|
||||
ZSTD_DStream* dstream = ZSTD_createDStream();
|
||||
if (dstream==NULL) {
|
||||
printf("Level %i : ZSTD_DStream Memory allocation failure \n", compressionLevel);
|
||||
return 1;
|
||||
}
|
||||
{ size_t const error = ZSTD_initDStream(dstream);
|
||||
if (ZSTD_isError(error)) {
|
||||
printf("ZSTD_initDStream error : %s \n", ZSTD_getErrorName(error));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* forces decompressor to use maximum memory size, as decompressed size is not known */
|
||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||
CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
|
||||
/* Set the maximum allowed window log.
|
||||
* The value 0 means use the default window log, which is equivalent to
|
||||
* not setting it.
|
||||
*/
|
||||
CHECK_ZSTD( ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, wLog) );
|
||||
/* forces decompressor to use maximum memory size, since the
|
||||
* decompressed size is not stored in the frame header.
|
||||
*/
|
||||
{ ZSTD_inBuffer inBuff = { compressedData, compressedSize, 0 };
|
||||
ZSTD_outBuffer outBuff = { decompressedData, sizeof(decompressedData), 0 };
|
||||
size_t const dResult = ZSTD_decompressStream(dstream, &outBuff, &inBuff);
|
||||
if (ZSTD_isError(dResult)) {
|
||||
printf("ZSTD_decompressStream error : %s \n", ZSTD_getErrorName(dResult));
|
||||
return 1;
|
||||
}
|
||||
if (dResult != 0) {
|
||||
printf("ZSTD_decompressStream error : unfinished decompression \n");
|
||||
return 1;
|
||||
}
|
||||
if (outBuff.pos != sizeof(dataToCompress)) {
|
||||
printf("ZSTD_decompressStream error : incorrect decompression \n");
|
||||
return 1;
|
||||
}
|
||||
size_t const remaining = ZSTD_decompressStream(dctx, &outBuff, &inBuff);
|
||||
CHECK_ZSTD(remaining);
|
||||
CHECK(remaining == 0, "Frame not complete!");
|
||||
CHECK(outBuff.pos == sizeof(dataToCompress), "Bad decompression!");
|
||||
}
|
||||
|
||||
size_t const cstreamSize = ZSTD_sizeof_CStream(cstream);
|
||||
size_t const cstreamEstimatedSize = wLog ?
|
||||
ZSTD_estimateCStreamSize_usingCParams(params.cParams) :
|
||||
ZSTD_estimateCStreamSize(compressionLevel);
|
||||
size_t const dstreamSize = ZSTD_sizeof_DStream(dstream);
|
||||
size_t const cstreamSize = ZSTD_sizeof_CStream(cctx);
|
||||
size_t const cstreamEstimatedSize = ZSTD_estimateCStreamSize_usingCCtxParams(cctxParams);
|
||||
size_t const dstreamSize = ZSTD_sizeof_DStream(dctx);
|
||||
size_t const dstreamEstimatedSize = ZSTD_estimateDStreamSize_fromFrame(compressedData, compressedSize);
|
||||
|
||||
printf("Level %2i : Compression Mem = %5u KB (estimated : %5u KB) ; Decompression Mem = %4u KB \n",
|
||||
CHECK(cstreamSize <= cstreamEstimatedSize, "Compression mem (%u) > estimated (%u)",
|
||||
(unsigned)cstreamSize, (unsigned)cstreamEstimatedSize);
|
||||
CHECK(dstreamSize <= dstreamEstimatedSize, "Decompression mem (%u) > estimated (%u)",
|
||||
(unsigned)dstreamSize, (unsigned)dstreamEstimatedSize);
|
||||
|
||||
printf("Level %2i : Compression Mem = %5u KB (estimated : %5u KB) ; Decompression Mem = %4u KB (estimated : %5u KB)\n",
|
||||
compressionLevel,
|
||||
(unsigned)(cstreamSize>>10), (unsigned)(cstreamEstimatedSize>>10), (unsigned)(dstreamSize>>10));
|
||||
(unsigned)(cstreamSize>>10), (unsigned)(cstreamEstimatedSize>>10),
|
||||
(unsigned)(dstreamSize>>10), (unsigned)(dstreamEstimatedSize>>10));
|
||||
|
||||
ZSTD_freeDStream(dstream);
|
||||
ZSTD_freeCStream(cstream);
|
||||
ZSTD_freeDCtx(dctx);
|
||||
ZSTD_freeCCtx(cctx);
|
||||
ZSTD_freeCCtxParams(cctxParams);
|
||||
if (wLog) break; /* single test */
|
||||
}
|
||||
return 0;
|
||||
|
||||
+12
-3
@@ -17,6 +17,7 @@ LIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT))
|
||||
LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT))
|
||||
LIBVER := $(shell echo $(LIBVER_SCRIPT))
|
||||
VERSION?= $(LIBVER)
|
||||
CCVER := $(shell $(CC) --version)
|
||||
|
||||
CPPFLAGS+= -I. -I./common -DXXH_NAMESPACE=ZSTD_
|
||||
ifeq ($(OS),Windows_NT) # MinGW assumed
|
||||
@@ -25,7 +26,7 @@ endif
|
||||
CFLAGS ?= -O3
|
||||
DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \
|
||||
-Wstrict-prototypes -Wundef -Wpointer-arith \
|
||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||
-Wredundant-decls -Wmissing-prototypes -Wc++-compat
|
||||
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||
@@ -45,6 +46,10 @@ ZDICT_FILES := $(sort $(wildcard dictBuilder/*.c))
|
||||
ZDEPR_FILES := $(sort $(wildcard deprecated/*.c))
|
||||
ZSTD_FILES := $(ZSTDCOMMON_FILES)
|
||||
|
||||
ifeq ($(findstring GCC,$(CCVER)),GCC)
|
||||
decompress/zstd_decompress_block.o : CFLAGS+=-fno-tree-vectorize
|
||||
endif
|
||||
|
||||
ZSTD_LEGACY_SUPPORT ?= 5
|
||||
ZSTD_LIB_COMPRESSION ?= 1
|
||||
ZSTD_LIB_DECOMPRESSION ?= 1
|
||||
@@ -56,6 +61,7 @@ ZSTD_FORCE_DECOMPRESS_SHORT ?= 0
|
||||
ZSTD_FORCE_DECOMPRESS_LONG ?= 0
|
||||
ZSTD_NO_INLINE ?= 0
|
||||
ZSTD_STRIP_ERROR_STRINGS ?= 0
|
||||
ZSTD_LEGACY_MULTITHREADED_API ?= 0
|
||||
|
||||
ifeq ($(ZSTD_LIB_COMPRESSION), 0)
|
||||
ZSTD_LIB_DICTBUILDER = 0
|
||||
@@ -107,6 +113,10 @@ ifneq ($(ZSTD_STRIP_ERROR_STRINGS), 0)
|
||||
CFLAGS += -DZSTD_STRIP_ERROR_STRINGS
|
||||
endif
|
||||
|
||||
ifneq ($(ZSTD_LEGACY_MULTITHREADED_API), 0)
|
||||
CFLAGS += -DZSTD_LEGACY_MULTITHREADED_API
|
||||
endif
|
||||
|
||||
ifneq ($(ZSTD_LEGACY_SUPPORT), 0)
|
||||
ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0)
|
||||
ZSTD_FILES += $(shell ls legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]')
|
||||
@@ -151,8 +161,7 @@ ifneq (,$(filter Windows%,$(OS)))
|
||||
LIBZSTD = dll\libzstd.dll
|
||||
$(LIBZSTD): $(ZSTD_FILES)
|
||||
@echo compiling dynamic library $(LIBVER)
|
||||
@$(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -shared $^ -o $@
|
||||
dlltool -D $@ -d dll\libzstd.def -l dll\libzstd.lib
|
||||
$(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -Wl,--out-implib,dll\libzstd.lib -shared $^ -o $@
|
||||
|
||||
else
|
||||
|
||||
|
||||
+4
-2
@@ -31,8 +31,6 @@ note that it's necessary to request the `-pthread` flag during link stage.
|
||||
|
||||
Multithreading capabilities are exposed
|
||||
via the [advanced API defined in `lib/zstd.h`](https://github.com/facebook/zstd/blob/v1.3.8/lib/zstd.h#L592).
|
||||
This API is still labelled experimental,
|
||||
but is expected to become "stable" in the near future.
|
||||
|
||||
|
||||
#### API
|
||||
@@ -110,6 +108,10 @@ The file structure is designed to make this selection manually achievable for an
|
||||
which removes the error messages that are otherwise returned by
|
||||
`ZSTD_getErrorName`.
|
||||
|
||||
- While invoking `make libzstd`, the build macro `ZSTD_LEGACY_MULTITHREADED_API=1`
|
||||
will expose the deprecated `ZSTDMT` API exposed by `zstdmt_compress.h` in
|
||||
the shared library, which is now hidden by default.
|
||||
|
||||
|
||||
#### Windows : using MinGW+MSYS to create DLL
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
/**
|
||||
* FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
|
||||
* parameters. They must be inlined for the compiler to elimininate the constant
|
||||
* parameters. They must be inlined for the compiler to eliminate the constant
|
||||
* branches.
|
||||
*/
|
||||
#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
||||
@@ -127,6 +127,13 @@
|
||||
} \
|
||||
}
|
||||
|
||||
/* vectorization */
|
||||
#if !defined(__clang__) && defined(__GNUC__)
|
||||
# define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
|
||||
#else
|
||||
# define DONT_VECTORIZE
|
||||
#endif
|
||||
|
||||
/* disable warnings */
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# include <intrin.h> /* For Visual 2005 */
|
||||
|
||||
+1
-1
@@ -358,7 +358,7 @@ size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size
|
||||
typedef enum {
|
||||
FSE_repeat_none, /**< Cannot use the previous table */
|
||||
FSE_repeat_check, /**< Can use the previous table but it must be checked */
|
||||
FSE_repeat_valid /**< Can use the previous table and it is asumed to be valid */
|
||||
FSE_repeat_valid /**< Can use the previous table and it is assumed to be valid */
|
||||
} FSE_repeat;
|
||||
|
||||
/* *****************************************
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
* This file will hold wrapper for systems, which do not support pthreads
|
||||
*/
|
||||
|
||||
/* create fake symbol to avoid empty trnaslation unit warning */
|
||||
int g_ZSTD_threading_useles_symbol;
|
||||
/* create fake symbol to avoid empty translation unit warning */
|
||||
int g_ZSTD_threading_useless_symbol;
|
||||
|
||||
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
||||
|
||||
|
||||
+2
-2
@@ -66,10 +66,10 @@
|
||||
/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
|
||||
|
||||
/*!XXH_FORCE_NATIVE_FORMAT :
|
||||
* By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
|
||||
* By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
|
||||
* Results are therefore identical for little-endian and big-endian CPU.
|
||||
* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
|
||||
* Should endian-independance be of no importance for your application, you may set the #define below to 1,
|
||||
* Should endian-independence be of no importance for your application, you may set the #define below to 1,
|
||||
* to improve speed for Big-endian CPU.
|
||||
* This option has no impact on Little_Endian CPU.
|
||||
*/
|
||||
|
||||
+113
-8
@@ -34,7 +34,6 @@
|
||||
#endif
|
||||
#include "xxhash.h" /* XXH_reset, update, digest */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -53,8 +52,50 @@ extern "C" {
|
||||
#undef MAX
|
||||
#define MIN(a,b) ((a)<(b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a)>(b) ? (a) : (b))
|
||||
#define CHECK_F(f) { size_t const errcod = f; if (ERR_isError(errcod)) return errcod; } /* check and Forward error code */
|
||||
#define CHECK_E(f, e) { size_t const errcod = f; if (ERR_isError(errcod)) return ERROR(e); } /* check and send Error code */
|
||||
|
||||
/**
|
||||
* Return the specified error if the condition evaluates to true.
|
||||
*
|
||||
* In debug modes, prints additional information. In order to do that
|
||||
* (particularly, printing the conditional that failed), this can't just wrap
|
||||
* RETURN_ERROR().
|
||||
*/
|
||||
#define RETURN_ERROR_IF(cond, err, ...) \
|
||||
if (cond) { \
|
||||
RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \
|
||||
RAWLOG(3, ": " __VA_ARGS__); \
|
||||
RAWLOG(3, "\n"); \
|
||||
return ERROR(err); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally return the specified error.
|
||||
*
|
||||
* In debug modes, prints additional information.
|
||||
*/
|
||||
#define RETURN_ERROR(err, ...) \
|
||||
do { \
|
||||
RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \
|
||||
RAWLOG(3, ": " __VA_ARGS__); \
|
||||
RAWLOG(3, "\n"); \
|
||||
return ERROR(err); \
|
||||
} while(0);
|
||||
|
||||
/**
|
||||
* If the provided expression evaluates to an error code, returns that error code.
|
||||
*
|
||||
* In debug modes, prints additional information.
|
||||
*/
|
||||
#define FORWARD_IF_ERROR(err, ...) \
|
||||
do { \
|
||||
size_t const err_code = (err); \
|
||||
if (ERR_isError(err_code)) { \
|
||||
RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \
|
||||
RAWLOG(3, ": " __VA_ARGS__); \
|
||||
RAWLOG(3, "\n"); \
|
||||
return err_code; \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -151,19 +192,72 @@ static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
|
||||
* Shared functions to include for inlining
|
||||
*********************************************/
|
||||
static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
|
||||
|
||||
#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }
|
||||
static void ZSTD_copy16(void* dst, const void* src) { memcpy(dst, src, 16); }
|
||||
#define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; }
|
||||
|
||||
#define WILDCOPY_OVERLENGTH 8
|
||||
#define VECLEN 16
|
||||
|
||||
typedef enum {
|
||||
ZSTD_no_overlap,
|
||||
ZSTD_overlap_src_before_dst,
|
||||
/* ZSTD_overlap_dst_before_src, */
|
||||
} ZSTD_overlap_e;
|
||||
|
||||
/*! ZSTD_wildcopy() :
|
||||
* custom version of memcpy(), can overwrite up to WILDCOPY_OVERLENGTH bytes (if length==0) */
|
||||
#define WILDCOPY_OVERLENGTH 8
|
||||
MEM_STATIC void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)
|
||||
MEM_STATIC FORCE_INLINE_ATTR DONT_VECTORIZE
|
||||
void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e ovtype)
|
||||
{
|
||||
ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src;
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
BYTE* const oend = op + length;
|
||||
do
|
||||
COPY8(op, ip)
|
||||
while (op < oend);
|
||||
|
||||
assert(diff >= 8 || (ovtype == ZSTD_no_overlap && diff < -8));
|
||||
if (length < VECLEN || (ovtype == ZSTD_overlap_src_before_dst && diff < VECLEN)) {
|
||||
do
|
||||
COPY8(op, ip)
|
||||
while (op < oend);
|
||||
}
|
||||
else {
|
||||
if ((length & 8) == 0)
|
||||
COPY8(op, ip);
|
||||
do {
|
||||
COPY16(op, ip);
|
||||
}
|
||||
while (op < oend);
|
||||
}
|
||||
}
|
||||
|
||||
/*! ZSTD_wildcopy_16min() :
|
||||
* same semantics as ZSTD_wilcopy() except guaranteed to be able to copy 16 bytes at the start */
|
||||
MEM_STATIC FORCE_INLINE_ATTR DONT_VECTORIZE
|
||||
void ZSTD_wildcopy_16min(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e ovtype)
|
||||
{
|
||||
ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src;
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
BYTE* const oend = op + length;
|
||||
|
||||
assert(length >= 8);
|
||||
assert(diff >= 8 || (ovtype == ZSTD_no_overlap && diff < -8));
|
||||
|
||||
if (ovtype == ZSTD_overlap_src_before_dst && diff < VECLEN) {
|
||||
do
|
||||
COPY8(op, ip)
|
||||
while (op < oend);
|
||||
}
|
||||
else {
|
||||
if ((length & 8) == 0)
|
||||
COPY8(op, ip);
|
||||
do {
|
||||
COPY16(op, ip);
|
||||
}
|
||||
while (op < oend);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC void ZSTD_wildcopy_e(void* dst, const void* src, void* dstEnd) /* should be faster for decoding, but strangely, not verified on all platform */
|
||||
@@ -200,6 +294,17 @@ typedef struct {
|
||||
U32 longLengthPos;
|
||||
} seqStore_t;
|
||||
|
||||
/**
|
||||
* Contains the compressed frame size and an upper-bound for the decompressed frame size.
|
||||
* Note: before using `compressedSize`, check for errors using ZSTD_isError().
|
||||
* similarly, before using `decompressedBound`, check for errors using:
|
||||
* `decompressedBound != ZSTD_CONTENTSIZE_ERROR`
|
||||
*/
|
||||
typedef struct {
|
||||
size_t compressedSize;
|
||||
unsigned long long decompressedBound;
|
||||
} ZSTD_frameSizeInfo; /* decompress & legacy */
|
||||
|
||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */
|
||||
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
|
||||
|
||||
|
||||
@@ -129,9 +129,9 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
|
||||
{ U32 position = 0;
|
||||
U32 symbol;
|
||||
for (symbol=0; symbol<=maxSymbolValue; symbol++) {
|
||||
int nbOccurences;
|
||||
int nbOccurrences;
|
||||
int const freq = normalizedCounter[symbol];
|
||||
for (nbOccurences=0; nbOccurences<freq; nbOccurences++) {
|
||||
for (nbOccurrences=0; nbOccurrences<freq; nbOccurrences++) {
|
||||
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
||||
position = (position + step) & tableMask;
|
||||
while (position > highThreshold)
|
||||
|
||||
+598
-413
@@ -103,12 +103,31 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
|
||||
return cctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears and frees all of the dictionaries in the CCtx.
|
||||
*/
|
||||
static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
|
||||
{
|
||||
ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem);
|
||||
ZSTD_freeCDict(cctx->localDict.cdict);
|
||||
memset(&cctx->localDict, 0, sizeof(cctx->localDict));
|
||||
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
|
||||
cctx->cdict = NULL;
|
||||
}
|
||||
|
||||
static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)
|
||||
{
|
||||
size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;
|
||||
size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);
|
||||
return bufferSize + cdictSize;
|
||||
}
|
||||
|
||||
static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
|
||||
{
|
||||
assert(cctx != NULL);
|
||||
assert(cctx->staticSize == 0);
|
||||
ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
|
||||
ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL;
|
||||
ZSTD_clearAllDicts(cctx);
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
|
||||
#endif
|
||||
@@ -117,7 +136,8 @@ static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
|
||||
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
||||
{
|
||||
if (cctx==NULL) return 0; /* support free on NULL */
|
||||
if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
|
||||
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
|
||||
"not compatible with static CCtx");
|
||||
ZSTD_freeCCtxContent(cctx);
|
||||
ZSTD_free(cctx, cctx->customMem);
|
||||
return 0;
|
||||
@@ -139,7 +159,7 @@ size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
|
||||
{
|
||||
if (cctx==NULL) return 0; /* support sizeof on NULL */
|
||||
return sizeof(*cctx) + cctx->workSpaceSize
|
||||
+ ZSTD_sizeof_CDict(cctx->cdictLocal)
|
||||
+ ZSTD_sizeof_localDict(cctx->localDict)
|
||||
+ ZSTD_sizeof_mtctx(cctx);
|
||||
}
|
||||
|
||||
@@ -195,7 +215,7 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
|
||||
}
|
||||
|
||||
size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
|
||||
if (!cctxParams) { return ERROR(GENERIC); }
|
||||
RETURN_ERROR_IF(!cctxParams, GENERIC);
|
||||
memset(cctxParams, 0, sizeof(*cctxParams));
|
||||
cctxParams->compressionLevel = compressionLevel;
|
||||
cctxParams->fParams.contentSizeFlag = 1;
|
||||
@@ -204,8 +224,8 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel)
|
||||
|
||||
size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
|
||||
{
|
||||
if (!cctxParams) { return ERROR(GENERIC); }
|
||||
CHECK_F( ZSTD_checkCParams(params.cParams) );
|
||||
RETURN_ERROR_IF(!cctxParams, GENERIC);
|
||||
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
|
||||
memset(cctxParams, 0, sizeof(*cctxParams));
|
||||
cctxParams->cParams = params.cParams;
|
||||
cctxParams->fParams = params.fParams;
|
||||
@@ -359,6 +379,17 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
||||
bounds.upperBound = ZSTD_dictForceCopy; /* note : how to ensure at compile time that this is the highest value enum ? */
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_literalCompressionMode:
|
||||
ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed);
|
||||
bounds.lowerBound = ZSTD_lcm_auto;
|
||||
bounds.upperBound = ZSTD_lcm_uncompressed;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_targetCBlockSize:
|
||||
bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN;
|
||||
bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX;
|
||||
return bounds;
|
||||
|
||||
default:
|
||||
{ ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 };
|
||||
return boundError;
|
||||
@@ -378,10 +409,22 @@ static int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BOUNDCHECK(cParam, val) { \
|
||||
if (!ZSTD_cParam_withinBounds(cParam,val)) { \
|
||||
return ERROR(parameter_outOfBound); \
|
||||
} }
|
||||
/* ZSTD_cParam_clampBounds:
|
||||
* Clamps the value into the bounded range.
|
||||
*/
|
||||
static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
|
||||
{
|
||||
ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
|
||||
if (ZSTD_isError(bounds.error)) return bounds.error;
|
||||
if (*value < bounds.lowerBound) *value = bounds.lowerBound;
|
||||
if (*value > bounds.upperBound) *value = bounds.upperBound;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define BOUNDCHECK(cParam, val) { \
|
||||
RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
|
||||
parameter_outOfBound); \
|
||||
}
|
||||
|
||||
|
||||
static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
|
||||
@@ -413,6 +456,8 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
|
||||
case ZSTD_c_ldmBucketSizeLog:
|
||||
case ZSTD_c_ldmHashRateLog:
|
||||
case ZSTD_c_forceAttachDict:
|
||||
case ZSTD_c_literalCompressionMode:
|
||||
case ZSTD_c_targetCBlockSize:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -425,18 +470,17 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
|
||||
if (ZSTD_isUpdateAuthorized(param)) {
|
||||
cctx->cParamsChanged = 1;
|
||||
} else {
|
||||
return ERROR(stage_wrong);
|
||||
RETURN_ERROR(stage_wrong);
|
||||
} }
|
||||
|
||||
switch(param)
|
||||
{
|
||||
case ZSTD_c_format :
|
||||
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
||||
case ZSTD_c_nbWorkers:
|
||||
RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,
|
||||
"MT not compatible with static alloc");
|
||||
break;
|
||||
|
||||
case ZSTD_c_compressionLevel:
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
||||
|
||||
case ZSTD_c_windowLog:
|
||||
case ZSTD_c_hashLog:
|
||||
case ZSTD_c_chainLog:
|
||||
@@ -444,49 +488,33 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
|
||||
case ZSTD_c_minMatch:
|
||||
case ZSTD_c_targetLength:
|
||||
case ZSTD_c_strategy:
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
||||
|
||||
case ZSTD_c_ldmHashRateLog:
|
||||
case ZSTD_c_format:
|
||||
case ZSTD_c_contentSizeFlag:
|
||||
case ZSTD_c_checksumFlag:
|
||||
case ZSTD_c_dictIDFlag:
|
||||
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
||||
|
||||
case ZSTD_c_forceMaxWindow : /* Force back-references to remain < windowSize,
|
||||
* even when referencing into Dictionary content.
|
||||
* default : 0 when using a CDict, 1 when using a Prefix */
|
||||
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
||||
|
||||
case ZSTD_c_forceMaxWindow:
|
||||
case ZSTD_c_forceAttachDict:
|
||||
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
||||
|
||||
case ZSTD_c_nbWorkers:
|
||||
if ((value!=0) && cctx->staticSize) {
|
||||
return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
|
||||
}
|
||||
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
||||
|
||||
case ZSTD_c_literalCompressionMode:
|
||||
case ZSTD_c_jobSize:
|
||||
case ZSTD_c_overlapLog:
|
||||
case ZSTD_c_rsyncable:
|
||||
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
||||
|
||||
case ZSTD_c_enableLongDistanceMatching:
|
||||
case ZSTD_c_ldmHashLog:
|
||||
case ZSTD_c_ldmMinMatch:
|
||||
case ZSTD_c_ldmBucketSizeLog:
|
||||
case ZSTD_c_ldmHashRateLog:
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
||||
case ZSTD_c_targetCBlockSize:
|
||||
break;
|
||||
|
||||
default: return ERROR(parameter_unsupported);
|
||||
default: RETURN_ERROR(parameter_unsupported);
|
||||
}
|
||||
return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
|
||||
}
|
||||
|
||||
size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
ZSTD_cParameter param, int value)
|
||||
size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
ZSTD_cParameter param, int value)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_CCtxParam_setParameter (%i, %i)", (int)param, value);
|
||||
DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value);
|
||||
switch(param)
|
||||
{
|
||||
case ZSTD_c_format :
|
||||
@@ -495,11 +523,9 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
return (size_t)CCtxParams->format;
|
||||
|
||||
case ZSTD_c_compressionLevel : {
|
||||
int cLevel = value;
|
||||
if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
|
||||
if (cLevel < ZSTD_minCLevel()) cLevel = ZSTD_minCLevel();
|
||||
if (cLevel) { /* 0 : does not change current level */
|
||||
CCtxParams->compressionLevel = cLevel;
|
||||
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
|
||||
if (value) { /* 0 : does not change current level */
|
||||
CCtxParams->compressionLevel = value;
|
||||
}
|
||||
if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
|
||||
return 0; /* return type (size_t) cannot represent negative values */
|
||||
@@ -573,33 +599,55 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
return CCtxParams->attachDictPref;
|
||||
}
|
||||
|
||||
case ZSTD_c_literalCompressionMode : {
|
||||
const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value;
|
||||
BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
|
||||
CCtxParams->literalCompressionMode = lcm;
|
||||
return CCtxParams->literalCompressionMode;
|
||||
}
|
||||
|
||||
case ZSTD_c_nbWorkers :
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
if (value!=0) return ERROR(parameter_unsupported);
|
||||
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
||||
return 0;
|
||||
#else
|
||||
return ZSTDMT_CCtxParam_setNbWorkers(CCtxParams, value);
|
||||
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
|
||||
CCtxParams->nbWorkers = value;
|
||||
return CCtxParams->nbWorkers;
|
||||
#endif
|
||||
|
||||
case ZSTD_c_jobSize :
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
return ERROR(parameter_unsupported);
|
||||
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
||||
return 0;
|
||||
#else
|
||||
return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_jobSize, value);
|
||||
/* Adjust to the minimum non-default value. */
|
||||
if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)
|
||||
value = ZSTDMT_JOBSIZE_MIN;
|
||||
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
|
||||
assert(value >= 0);
|
||||
CCtxParams->jobSize = value;
|
||||
return CCtxParams->jobSize;
|
||||
#endif
|
||||
|
||||
case ZSTD_c_overlapLog :
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
return ERROR(parameter_unsupported);
|
||||
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
||||
return 0;
|
||||
#else
|
||||
return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_overlapLog, value);
|
||||
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
|
||||
CCtxParams->overlapLog = value;
|
||||
return CCtxParams->overlapLog;
|
||||
#endif
|
||||
|
||||
case ZSTD_c_rsyncable :
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
return ERROR(parameter_unsupported);
|
||||
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
||||
return 0;
|
||||
#else
|
||||
return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_rsyncable, value);
|
||||
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
|
||||
CCtxParams->rsyncable = value;
|
||||
return CCtxParams->rsyncable;
|
||||
#endif
|
||||
|
||||
case ZSTD_c_enableLongDistanceMatching :
|
||||
@@ -625,21 +673,27 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
return CCtxParams->ldmParams.bucketSizeLog;
|
||||
|
||||
case ZSTD_c_ldmHashRateLog :
|
||||
if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
|
||||
return ERROR(parameter_outOfBound);
|
||||
RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
|
||||
parameter_outOfBound);
|
||||
CCtxParams->ldmParams.hashRateLog = value;
|
||||
return CCtxParams->ldmParams.hashRateLog;
|
||||
|
||||
default: return ERROR(parameter_unsupported);
|
||||
case ZSTD_c_targetCBlockSize :
|
||||
if (value!=0) /* 0 ==> default */
|
||||
BOUNDCHECK(ZSTD_c_targetCBlockSize, value);
|
||||
CCtxParams->targetCBlockSize = value;
|
||||
return CCtxParams->targetCBlockSize;
|
||||
|
||||
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
||||
}
|
||||
}
|
||||
|
||||
size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value)
|
||||
{
|
||||
return ZSTD_CCtxParam_getParameter(&cctx->requestedParams, param, value);
|
||||
return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
|
||||
}
|
||||
|
||||
size_t ZSTD_CCtxParam_getParameter(
|
||||
size_t ZSTD_CCtxParams_getParameter(
|
||||
ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value)
|
||||
{
|
||||
switch(param)
|
||||
@@ -651,13 +705,13 @@ size_t ZSTD_CCtxParam_getParameter(
|
||||
*value = CCtxParams->compressionLevel;
|
||||
break;
|
||||
case ZSTD_c_windowLog :
|
||||
*value = CCtxParams->cParams.windowLog;
|
||||
*value = (int)CCtxParams->cParams.windowLog;
|
||||
break;
|
||||
case ZSTD_c_hashLog :
|
||||
*value = CCtxParams->cParams.hashLog;
|
||||
*value = (int)CCtxParams->cParams.hashLog;
|
||||
break;
|
||||
case ZSTD_c_chainLog :
|
||||
*value = CCtxParams->cParams.chainLog;
|
||||
*value = (int)CCtxParams->cParams.chainLog;
|
||||
break;
|
||||
case ZSTD_c_searchLog :
|
||||
*value = CCtxParams->cParams.searchLog;
|
||||
@@ -686,6 +740,9 @@ size_t ZSTD_CCtxParam_getParameter(
|
||||
case ZSTD_c_forceAttachDict :
|
||||
*value = CCtxParams->attachDictPref;
|
||||
break;
|
||||
case ZSTD_c_literalCompressionMode :
|
||||
*value = CCtxParams->literalCompressionMode;
|
||||
break;
|
||||
case ZSTD_c_nbWorkers :
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
assert(CCtxParams->nbWorkers == 0);
|
||||
@@ -694,7 +751,7 @@ size_t ZSTD_CCtxParam_getParameter(
|
||||
break;
|
||||
case ZSTD_c_jobSize :
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
return ERROR(parameter_unsupported);
|
||||
RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
|
||||
#else
|
||||
assert(CCtxParams->jobSize <= INT_MAX);
|
||||
*value = (int)CCtxParams->jobSize;
|
||||
@@ -702,14 +759,14 @@ size_t ZSTD_CCtxParam_getParameter(
|
||||
#endif
|
||||
case ZSTD_c_overlapLog :
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
return ERROR(parameter_unsupported);
|
||||
RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
|
||||
#else
|
||||
*value = CCtxParams->overlapLog;
|
||||
break;
|
||||
#endif
|
||||
case ZSTD_c_rsyncable :
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
return ERROR(parameter_unsupported);
|
||||
RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
|
||||
#else
|
||||
*value = CCtxParams->rsyncable;
|
||||
break;
|
||||
@@ -729,7 +786,10 @@ size_t ZSTD_CCtxParam_getParameter(
|
||||
case ZSTD_c_ldmHashRateLog :
|
||||
*value = CCtxParams->ldmParams.hashRateLog;
|
||||
break;
|
||||
default: return ERROR(parameter_unsupported);
|
||||
case ZSTD_c_targetCBlockSize :
|
||||
*value = (int)CCtxParams->targetCBlockSize;
|
||||
break;
|
||||
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -745,8 +805,8 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
||||
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
|
||||
RETURN_ERROR_IF(cctx->cdict, stage_wrong);
|
||||
|
||||
cctx->requestedParams = *params;
|
||||
return 0;
|
||||
@@ -755,33 +815,71 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
|
||||
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the local dict using the requested parameters.
|
||||
* NOTE: This does not use the pledged src size, because it may be used for more
|
||||
* than one compression.
|
||||
*/
|
||||
static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
|
||||
{
|
||||
ZSTD_localDict* const dl = &cctx->localDict;
|
||||
ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
|
||||
&cctx->requestedParams, 0, dl->dictSize);
|
||||
if (dl->dict == NULL) {
|
||||
/* No local dictionary. */
|
||||
assert(dl->dictBuffer == NULL);
|
||||
assert(dl->cdict == NULL);
|
||||
assert(dl->dictSize == 0);
|
||||
return 0;
|
||||
}
|
||||
if (dl->cdict != NULL) {
|
||||
assert(cctx->cdict == dl->cdict);
|
||||
/* Local dictionary already initialized. */
|
||||
return 0;
|
||||
}
|
||||
assert(dl->dictSize > 0);
|
||||
assert(cctx->cdict == NULL);
|
||||
assert(cctx->prefixDict.dict == NULL);
|
||||
|
||||
dl->cdict = ZSTD_createCDict_advanced(
|
||||
dl->dict,
|
||||
dl->dictSize,
|
||||
ZSTD_dlm_byRef,
|
||||
dl->dictContentType,
|
||||
cParams,
|
||||
cctx->customMem);
|
||||
RETURN_ERROR_IF(!dl->cdict, memory_allocation);
|
||||
cctx->cdict = dl->cdict;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTD_CCtx_loadDictionary_advanced(
|
||||
ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
|
||||
ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
|
||||
{
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
|
||||
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
|
||||
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
|
||||
"no malloc for static CCtx");
|
||||
DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
|
||||
ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */
|
||||
if (dict==NULL || dictSize==0) { /* no dictionary mode */
|
||||
cctx->cdictLocal = NULL;
|
||||
cctx->cdict = NULL;
|
||||
ZSTD_clearAllDicts(cctx); /* in case one already exists */
|
||||
if (dict == NULL || dictSize == 0) /* no dictionary mode */
|
||||
return 0;
|
||||
if (dictLoadMethod == ZSTD_dlm_byRef) {
|
||||
cctx->localDict.dict = dict;
|
||||
} else {
|
||||
ZSTD_compressionParameters const cParams =
|
||||
ZSTD_getCParamsFromCCtxParams(&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize);
|
||||
cctx->cdictLocal = ZSTD_createCDict_advanced(
|
||||
dict, dictSize,
|
||||
dictLoadMethod, dictContentType,
|
||||
cParams, cctx->customMem);
|
||||
cctx->cdict = cctx->cdictLocal;
|
||||
if (cctx->cdictLocal == NULL)
|
||||
return ERROR(memory_allocation);
|
||||
void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem);
|
||||
RETURN_ERROR_IF(!dictBuffer, memory_allocation);
|
||||
memcpy(dictBuffer, dict, dictSize);
|
||||
cctx->localDict.dictBuffer = dictBuffer;
|
||||
cctx->localDict.dict = dictBuffer;
|
||||
}
|
||||
cctx->localDict.dictSize = dictSize;
|
||||
cctx->localDict.dictContentType = dictContentType;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -801,9 +899,10 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
|
||||
|
||||
size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
|
||||
{
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
|
||||
/* Free the existing local cdict (if any) to save memory. */
|
||||
ZSTD_clearAllDicts(cctx);
|
||||
cctx->cdict = cdict;
|
||||
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* exclusive */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -815,8 +914,8 @@ size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSiz
|
||||
size_t ZSTD_CCtx_refPrefix_advanced(
|
||||
ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
||||
{
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
cctx->cdict = NULL; /* prefix discards any prior cdict */
|
||||
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
|
||||
ZSTD_clearAllDicts(cctx);
|
||||
cctx->prefixDict.dict = prefix;
|
||||
cctx->prefixDict.dictSize = prefixSize;
|
||||
cctx->prefixDict.dictContentType = dictContentType;
|
||||
@@ -834,8 +933,8 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
|
||||
}
|
||||
if ( (reset == ZSTD_reset_parameters)
|
||||
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
cctx->cdict = NULL;
|
||||
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
|
||||
ZSTD_clearAllDicts(cctx);
|
||||
return ZSTD_CCtxParams_reset(&cctx->requestedParams);
|
||||
}
|
||||
return 0;
|
||||
@@ -847,12 +946,12 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
|
||||
@return : 0, or an error code if one value is beyond authorized range */
|
||||
size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
|
||||
{
|
||||
BOUNDCHECK(ZSTD_c_windowLog, cParams.windowLog);
|
||||
BOUNDCHECK(ZSTD_c_chainLog, cParams.chainLog);
|
||||
BOUNDCHECK(ZSTD_c_hashLog, cParams.hashLog);
|
||||
BOUNDCHECK(ZSTD_c_searchLog, cParams.searchLog);
|
||||
BOUNDCHECK(ZSTD_c_minMatch, cParams.minMatch);
|
||||
BOUNDCHECK(ZSTD_c_targetLength,cParams.targetLength);
|
||||
BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog);
|
||||
BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog);
|
||||
BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog);
|
||||
BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog);
|
||||
BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch);
|
||||
BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength);
|
||||
BOUNDCHECK(ZSTD_c_strategy, cParams.strategy);
|
||||
return 0;
|
||||
}
|
||||
@@ -868,7 +967,7 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
|
||||
if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
|
||||
else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
|
||||
}
|
||||
# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, int)
|
||||
# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
|
||||
CLAMP(ZSTD_c_windowLog, cParams.windowLog);
|
||||
CLAMP(ZSTD_c_chainLog, cParams.chainLog);
|
||||
CLAMP(ZSTD_c_hashLog, cParams.hashLog);
|
||||
@@ -888,10 +987,11 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
|
||||
}
|
||||
|
||||
/** ZSTD_adjustCParams_internal() :
|
||||
optimize `cPar` for a given input (`srcSize` and `dictSize`).
|
||||
mostly downsizing to reduce memory consumption and initialization latency.
|
||||
Both `srcSize` and `dictSize` are optional (use 0 if unknown).
|
||||
Note : cPar is assumed validated. Use ZSTD_checkCParams() to ensure this condition. */
|
||||
* optimize `cPar` for a specified input (`srcSize` and `dictSize`).
|
||||
* mostly downsize to reduce memory consumption and initialization latency.
|
||||
* `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
|
||||
* note : for the time being, `srcSize==0` means "unknown" too, for compatibility with older convention.
|
||||
* condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
|
||||
static ZSTD_compressionParameters
|
||||
ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
||||
unsigned long long srcSize,
|
||||
@@ -901,7 +1001,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
||||
static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
|
||||
assert(ZSTD_checkCParams(cPar)==0);
|
||||
|
||||
if (dictSize && (srcSize+1<2) /* srcSize unknown */ )
|
||||
if (dictSize && (srcSize+1<2) /* ZSTD_CONTENTSIZE_UNKNOWN and 0 mean "unknown" */ )
|
||||
srcSize = minSrcSize; /* presumed small when there is a dictionary */
|
||||
else if (srcSize == 0)
|
||||
srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
|
||||
@@ -922,7 +1022,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
||||
}
|
||||
|
||||
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
|
||||
cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
|
||||
cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */
|
||||
|
||||
return cPar;
|
||||
}
|
||||
@@ -932,7 +1032,7 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
|
||||
unsigned long long srcSize,
|
||||
size_t dictSize)
|
||||
{
|
||||
cPar = ZSTD_clampCParams(cPar);
|
||||
cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
|
||||
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
|
||||
}
|
||||
|
||||
@@ -973,8 +1073,7 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
|
||||
|
||||
size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
||||
{
|
||||
/* Estimate CCtx size is supported for single-threaded compression only. */
|
||||
if (params->nbWorkers > 0) { return ERROR(GENERIC); }
|
||||
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
|
||||
{ ZSTD_compressionParameters const cParams =
|
||||
ZSTD_getCParamsFromCCtxParams(params, 0, 0);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
||||
@@ -1022,10 +1121,12 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel)
|
||||
|
||||
size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
||||
{
|
||||
if (params->nbWorkers > 0) { return ERROR(GENERIC); }
|
||||
{ size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog);
|
||||
size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize;
|
||||
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
|
||||
{ ZSTD_compressionParameters const cParams =
|
||||
ZSTD_getCParamsFromCCtxParams(params, 0, 0);
|
||||
size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
||||
size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
|
||||
size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
|
||||
size_t const streamingSize = inBuffSize + outBuffSize;
|
||||
|
||||
@@ -1197,15 +1298,14 @@ static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
|
||||
}
|
||||
|
||||
/*! ZSTD_invalidateMatchState()
|
||||
* Invalidate all the matches in the match finder tables.
|
||||
* Requires nextSrc and base to be set (can be NULL).
|
||||
* Invalidate all the matches in the match finder tables.
|
||||
* Requires nextSrc and base to be set (can be NULL).
|
||||
*/
|
||||
static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
|
||||
{
|
||||
ZSTD_window_clear(&ms->window);
|
||||
|
||||
ms->nextToUpdate = ms->window.dictLimit;
|
||||
ms->nextToUpdate3 = ms->window.dictLimit;
|
||||
ms->loadedDictEnd = 0;
|
||||
ms->opt.litLengthSum = 0; /* force reset of btopt stats */
|
||||
ms->dictMatchState = NULL;
|
||||
@@ -1242,15 +1342,17 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pl
|
||||
|
||||
typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
|
||||
|
||||
typedef enum { ZSTD_resetTarget_CDict, ZSTD_resetTarget_CCtx } ZSTD_resetTarget_e;
|
||||
|
||||
static void*
|
||||
ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
||||
void* ptr,
|
||||
const ZSTD_compressionParameters* cParams,
|
||||
ZSTD_compResetPolicy_e const crp, U32 const forCCtx)
|
||||
ZSTD_compResetPolicy_e const crp, ZSTD_resetTarget_e const forWho)
|
||||
{
|
||||
size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
|
||||
size_t const hSize = ((size_t)1) << cParams->hashLog;
|
||||
U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
|
||||
U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
|
||||
size_t const h3Size = ((size_t)1) << hashLog3;
|
||||
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
||||
|
||||
@@ -1264,7 +1366,7 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
||||
ZSTD_invalidateMatchState(ms);
|
||||
|
||||
/* opt parser space */
|
||||
if (forCCtx && (cParams->strategy >= ZSTD_btopt)) {
|
||||
if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {
|
||||
DEBUGLOG(4, "reserving optimal parser space");
|
||||
ms->opt.litFreq = (unsigned*)ptr;
|
||||
ms->opt.litLengthFreq = ms->opt.litFreq + (1<<Litbits);
|
||||
@@ -1292,6 +1394,19 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* ZSTD_indexTooCloseToMax() :
|
||||
* minor optimization : prefer memset() rather than reduceIndex()
|
||||
* which is measurably slow in some circumstances (reported for Visual Studio).
|
||||
* Works when re-using a context for a lot of smallish inputs :
|
||||
* if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN,
|
||||
* memset() will be triggered before reduceIndex().
|
||||
*/
|
||||
#define ZSTD_INDEXOVERFLOW_MARGIN (16 MB)
|
||||
static int ZSTD_indexTooCloseToMax(ZSTD_window_t w)
|
||||
{
|
||||
return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);
|
||||
}
|
||||
|
||||
#define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */
|
||||
#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 /* when workspace is continuously too large
|
||||
* during at least this number of times,
|
||||
@@ -1303,7 +1418,7 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
||||
note : `params` are assumed fully validated at this stage */
|
||||
static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
ZSTD_CCtx_params params,
|
||||
U64 pledgedSrcSize,
|
||||
U64 const pledgedSrcSize,
|
||||
ZSTD_compResetPolicy_e const crp,
|
||||
ZSTD_buffered_policy_e const zbuff)
|
||||
{
|
||||
@@ -1315,13 +1430,21 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
if (ZSTD_equivalentParams(zc->appliedParams, params,
|
||||
zc->inBuffSize,
|
||||
zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit,
|
||||
zbuff, pledgedSrcSize)) {
|
||||
DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)",
|
||||
zc->appliedParams.cParams.windowLog, zc->blockSize);
|
||||
zbuff, pledgedSrcSize) ) {
|
||||
DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> consider continue mode");
|
||||
zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
|
||||
if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION)
|
||||
if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION) {
|
||||
DEBUGLOG(4, "continue mode confirmed (wLog1=%u, blockSize1=%zu)",
|
||||
zc->appliedParams.cParams.windowLog, zc->blockSize);
|
||||
if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) {
|
||||
/* prefer a reset, faster than a rescale */
|
||||
ZSTD_reset_matchState(&zc->blockState.matchState,
|
||||
zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32,
|
||||
¶ms.cParams,
|
||||
crp, ZSTD_resetTarget_CCtx);
|
||||
}
|
||||
return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
|
||||
} }
|
||||
} } }
|
||||
DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
|
||||
|
||||
if (params.ldmParams.enableLdm) {
|
||||
@@ -1364,16 +1487,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
|
||||
|
||||
if (workSpaceTooSmall || workSpaceWasteful) {
|
||||
DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB",
|
||||
DEBUGLOG(4, "Resize workSpaceSize from %zuKB to %zuKB",
|
||||
zc->workSpaceSize >> 10,
|
||||
neededSpace >> 10);
|
||||
/* static cctx : no resize, error out */
|
||||
if (zc->staticSize) return ERROR(memory_allocation);
|
||||
|
||||
RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
|
||||
|
||||
zc->workSpaceSize = 0;
|
||||
ZSTD_free(zc->workSpace, zc->customMem);
|
||||
zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
|
||||
if (zc->workSpace == NULL) return ERROR(memory_allocation);
|
||||
RETURN_ERROR_IF(zc->workSpace == NULL, memory_allocation);
|
||||
zc->workSpaceSize = neededSpace;
|
||||
zc->workSpaceOversizedDuration = 0;
|
||||
|
||||
@@ -1406,7 +1529,10 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
|
||||
ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
|
||||
|
||||
ptr = zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32;
|
||||
ptr = ZSTD_reset_matchState(&zc->blockState.matchState,
|
||||
zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32,
|
||||
¶ms.cParams,
|
||||
crp, ZSTD_resetTarget_CCtx);
|
||||
|
||||
/* ldm hash table */
|
||||
/* initialize bucketOffsets table later for pointer alignment */
|
||||
@@ -1424,8 +1550,6 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
}
|
||||
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
||||
|
||||
ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, ¶ms.cParams, crp, /* forCCtx */ 1);
|
||||
|
||||
/* sequences storage */
|
||||
zc->seqStore.maxNbSeq = maxNbSeq;
|
||||
zc->seqStore.sequencesStart = (seqDef*)ptr;
|
||||
@@ -1502,15 +1626,14 @@ static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
|
||||
* handled in _enforceMaxDist */
|
||||
}
|
||||
|
||||
static size_t ZSTD_resetCCtx_byAttachingCDict(
|
||||
ZSTD_CCtx* cctx,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_CCtx_params params,
|
||||
U64 pledgedSrcSize,
|
||||
ZSTD_buffered_policy_e zbuff)
|
||||
static size_t
|
||||
ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_CCtx_params params,
|
||||
U64 pledgedSrcSize,
|
||||
ZSTD_buffered_policy_e zbuff)
|
||||
{
|
||||
{
|
||||
const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
|
||||
{ const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams;
|
||||
unsigned const windowLog = params.cParams.windowLog;
|
||||
assert(windowLog != 0);
|
||||
/* Resize working context table params for input only, since the dict
|
||||
@@ -1522,8 +1645,7 @@ static size_t ZSTD_resetCCtx_byAttachingCDict(
|
||||
assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
|
||||
}
|
||||
|
||||
{
|
||||
const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
|
||||
{ const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
|
||||
- cdict->matchState.window.base);
|
||||
const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
|
||||
if (cdictLen == 0) {
|
||||
@@ -1540,9 +1662,9 @@ static size_t ZSTD_resetCCtx_byAttachingCDict(
|
||||
cctx->blockState.matchState.window.base + cdictEnd;
|
||||
ZSTD_window_clear(&cctx->blockState.matchState.window);
|
||||
}
|
||||
/* loadedDictEnd is expressed within the referential of the active context */
|
||||
cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
cctx->dictID = cdict->dictID;
|
||||
|
||||
@@ -1596,7 +1718,6 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
||||
ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
|
||||
dstMatchState->window = srcMatchState->window;
|
||||
dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
|
||||
dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
|
||||
dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
|
||||
}
|
||||
|
||||
@@ -1644,7 +1765,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
||||
ZSTD_buffered_policy_e zbuff)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_copyCCtx_internal");
|
||||
if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
|
||||
RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong);
|
||||
|
||||
memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
|
||||
{ ZSTD_CCtx_params params = dstCCtx->requestedParams;
|
||||
@@ -1676,7 +1797,6 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
||||
ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
|
||||
dstMatchState->window = srcMatchState->window;
|
||||
dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
|
||||
dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
|
||||
dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
|
||||
}
|
||||
dstCCtx->dictID = srcCCtx->dictID;
|
||||
@@ -1746,16 +1866,15 @@ static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const
|
||||
|
||||
/*! ZSTD_reduceIndex() :
|
||||
* rescale all indexes to avoid future overflow (indexes are U32) */
|
||||
static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
|
||||
static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)
|
||||
{
|
||||
ZSTD_matchState_t* const ms = &zc->blockState.matchState;
|
||||
{ U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
|
||||
{ U32 const hSize = (U32)1 << params->cParams.hashLog;
|
||||
ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
|
||||
}
|
||||
|
||||
if (zc->appliedParams.cParams.strategy != ZSTD_fast) {
|
||||
U32 const chainSize = (U32)1 << zc->appliedParams.cParams.chainLog;
|
||||
if (zc->appliedParams.cParams.strategy == ZSTD_btlazy2)
|
||||
if (params->cParams.strategy != ZSTD_fast) {
|
||||
U32 const chainSize = (U32)1 << params->cParams.chainLog;
|
||||
if (params->cParams.strategy == ZSTD_btlazy2)
|
||||
ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
|
||||
else
|
||||
ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
|
||||
@@ -1777,7 +1896,8 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
|
||||
static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
|
||||
{
|
||||
U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
|
||||
if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
|
||||
dstSize_tooSmall);
|
||||
MEM_writeLE24(dst, cBlockHeader24);
|
||||
memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
|
||||
return ZSTD_blockHeaderSize + srcSize;
|
||||
@@ -1788,7 +1908,7 @@ static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void
|
||||
BYTE* const ostart = (BYTE* const)dst;
|
||||
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
||||
|
||||
if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall);
|
||||
|
||||
switch(flSize)
|
||||
{
|
||||
@@ -1878,7 +1998,7 @@ static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
||||
if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
|
||||
RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, "not enough space for compression");
|
||||
{ HUF_repeat repeat = prevHuf->repeatMode;
|
||||
int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
|
||||
if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
|
||||
@@ -1960,7 +2080,7 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
||||
* If x == 0: Return 0
|
||||
* Else: Return floor(-log2(x / 256) * 256)
|
||||
*/
|
||||
static unsigned const kInverseProbabiltyLog256[256] = {
|
||||
static unsigned const kInverseProbabilityLog256[256] = {
|
||||
0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
|
||||
1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
|
||||
874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
|
||||
@@ -1999,7 +2119,7 @@ static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t
|
||||
if (count[s] != 0 && norm == 0)
|
||||
norm = 1;
|
||||
assert(count[s] < total);
|
||||
cost += count[s] * kInverseProbabiltyLog256[norm];
|
||||
cost += count[s] * kInverseProbabilityLog256[norm];
|
||||
}
|
||||
return cost >> 8;
|
||||
}
|
||||
@@ -2022,7 +2142,7 @@ static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
|
||||
unsigned const norm256 = normAcc << shift;
|
||||
assert(norm256 > 0);
|
||||
assert(norm256 < 256);
|
||||
cost += count[s] * kInverseProbabiltyLog256[norm256];
|
||||
cost += count[s] * kInverseProbabilityLog256[norm256];
|
||||
}
|
||||
return cost >> 8;
|
||||
}
|
||||
@@ -2050,21 +2170,17 @@ static size_t ZSTD_fseBitCost(
|
||||
unsigned s;
|
||||
FSE_CState_t cstate;
|
||||
FSE_initCState(&cstate, ctable);
|
||||
if (ZSTD_getFSEMaxSymbolValue(ctable) < max) {
|
||||
DEBUGLOG(5, "Repeat FSE_CTable has maxSymbolValue %u < %u",
|
||||
RETURN_ERROR_IF(ZSTD_getFSEMaxSymbolValue(ctable) < max, GENERIC,
|
||||
"Repeat FSE_CTable has maxSymbolValue %u < %u",
|
||||
ZSTD_getFSEMaxSymbolValue(ctable), max);
|
||||
return ERROR(GENERIC);
|
||||
}
|
||||
for (s = 0; s <= max; ++s) {
|
||||
unsigned const tableLog = cstate.stateLog;
|
||||
unsigned const badCost = (tableLog + 1) << kAccuracyLog;
|
||||
unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
|
||||
if (count[s] == 0)
|
||||
continue;
|
||||
if (bitCost >= badCost) {
|
||||
DEBUGLOG(5, "Repeat FSE_CTable has Prob[%u] == 0", s);
|
||||
return ERROR(GENERIC);
|
||||
}
|
||||
RETURN_ERROR_IF(bitCost >= badCost, GENERIC,
|
||||
"Repeat FSE_CTable has Prob[%u] == 0", s);
|
||||
cost += count[s] * bitCost;
|
||||
}
|
||||
return cost >> kAccuracyLog;
|
||||
@@ -2080,7 +2196,7 @@ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
|
||||
BYTE wksp[FSE_NCOUNTBOUND];
|
||||
S16 norm[MaxSeq + 1];
|
||||
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
||||
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
|
||||
FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
|
||||
return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
|
||||
}
|
||||
|
||||
@@ -2186,15 +2302,15 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
||||
|
||||
switch (type) {
|
||||
case set_rle:
|
||||
CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max));
|
||||
if (dstCapacity==0) return ERROR(dstSize_tooSmall);
|
||||
FORWARD_IF_ERROR(FSE_buildCTable_rle(nextCTable, (BYTE)max));
|
||||
RETURN_ERROR_IF(dstCapacity==0, dstSize_tooSmall);
|
||||
*op = codeTable[0];
|
||||
return 1;
|
||||
case set_repeat:
|
||||
memcpy(nextCTable, prevCTable, prevCTableSize);
|
||||
return 0;
|
||||
case set_basic:
|
||||
CHECK_F(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
|
||||
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
|
||||
return 0;
|
||||
case set_compressed: {
|
||||
S16 norm[MaxSeq + 1];
|
||||
@@ -2205,14 +2321,14 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
||||
nbSeq_1--;
|
||||
}
|
||||
assert(nbSeq_1 > 1);
|
||||
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
|
||||
FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
|
||||
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
|
||||
if (FSE_isError(NCountSize)) return NCountSize;
|
||||
CHECK_F(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
|
||||
FORWARD_IF_ERROR(NCountSize);
|
||||
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
|
||||
return NCountSize;
|
||||
}
|
||||
}
|
||||
default: return assert(0), ERROR(GENERIC);
|
||||
default: assert(0); RETURN_ERROR(GENERIC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2229,7 +2345,9 @@ ZSTD_encodeSequences_body(
|
||||
FSE_CState_t stateOffsetBits;
|
||||
FSE_CState_t stateLitLength;
|
||||
|
||||
CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */
|
||||
RETURN_ERROR_IF(
|
||||
ERR_isError(BIT_initCStream(&blockStream, dst, dstCapacity)),
|
||||
dstSize_tooSmall, "not enough space remaining");
|
||||
DEBUGLOG(6, "available space for bitstream : %i (dstCapacity=%u)",
|
||||
(int)(blockStream.endPtr - blockStream.startPtr),
|
||||
(unsigned)dstCapacity);
|
||||
@@ -2303,7 +2421,7 @@ ZSTD_encodeSequences_body(
|
||||
FSE_flushCState(&blockStream, &stateLitLength);
|
||||
|
||||
{ size_t const streamSize = BIT_closeCStream(&blockStream);
|
||||
if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
|
||||
RETURN_ERROR_IF(streamSize==0, dstSize_tooSmall, "not enough space");
|
||||
return streamSize;
|
||||
}
|
||||
}
|
||||
@@ -2368,6 +2486,21 @@ static size_t ZSTD_encodeSequences(
|
||||
sequences, nbSeq, longOffsets);
|
||||
}
|
||||
|
||||
static int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
|
||||
{
|
||||
switch (cctxParams->literalCompressionMode) {
|
||||
case ZSTD_lcm_huffman:
|
||||
return 0;
|
||||
case ZSTD_lcm_uncompressed:
|
||||
return 1;
|
||||
default:
|
||||
assert(0 /* impossible: pre-validated */);
|
||||
/* fall-through */
|
||||
case ZSTD_lcm_auto:
|
||||
return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ZSTD_compressSequences_internal():
|
||||
* actually compresses both literals and sequences */
|
||||
MEM_STATIC size_t
|
||||
@@ -2403,28 +2536,29 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
||||
/* Compress literals */
|
||||
{ const BYTE* const literals = seqStorePtr->litStart;
|
||||
size_t const litSize = seqStorePtr->lit - literals;
|
||||
int const disableLiteralCompression = (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
|
||||
size_t const cSize = ZSTD_compressLiterals(
|
||||
&prevEntropy->huf, &nextEntropy->huf,
|
||||
cctxParams->cParams.strategy, disableLiteralCompression,
|
||||
cctxParams->cParams.strategy,
|
||||
ZSTD_disableLiteralsCompression(cctxParams),
|
||||
op, dstCapacity,
|
||||
literals, litSize,
|
||||
workspace, wkspSize,
|
||||
bmi2);
|
||||
if (ZSTD_isError(cSize))
|
||||
return cSize;
|
||||
FORWARD_IF_ERROR(cSize);
|
||||
assert(cSize <= dstCapacity);
|
||||
op += cSize;
|
||||
}
|
||||
|
||||
/* Sequences Header */
|
||||
if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
|
||||
dstSize_tooSmall);
|
||||
if (nbSeq < 0x7F)
|
||||
*op++ = (BYTE)nbSeq;
|
||||
else if (nbSeq < LONGNBSEQ)
|
||||
op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
|
||||
else
|
||||
op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
|
||||
assert(op <= oend);
|
||||
if (nbSeq==0) {
|
||||
/* Copy the old tables over as if we repeated them */
|
||||
memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
|
||||
@@ -2433,6 +2567,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
||||
|
||||
/* seqHead : flags for FSE encoding type */
|
||||
seqHead = op++;
|
||||
assert(op <= oend);
|
||||
|
||||
/* convert length/distances into codes */
|
||||
ZSTD_seqToCodes(seqStorePtr);
|
||||
@@ -2452,10 +2587,11 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
||||
count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
|
||||
prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable),
|
||||
workspace, wkspSize);
|
||||
if (ZSTD_isError(countSize)) return countSize;
|
||||
FORWARD_IF_ERROR(countSize);
|
||||
if (LLtype == set_compressed)
|
||||
lastNCount = op;
|
||||
op += countSize;
|
||||
assert(op <= oend);
|
||||
} }
|
||||
/* build CTable for Offsets */
|
||||
{ unsigned max = MaxOff;
|
||||
@@ -2474,10 +2610,11 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
||||
count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
|
||||
prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable),
|
||||
workspace, wkspSize);
|
||||
if (ZSTD_isError(countSize)) return countSize;
|
||||
FORWARD_IF_ERROR(countSize);
|
||||
if (Offtype == set_compressed)
|
||||
lastNCount = op;
|
||||
op += countSize;
|
||||
assert(op <= oend);
|
||||
} }
|
||||
/* build CTable for MatchLengths */
|
||||
{ unsigned max = MaxML;
|
||||
@@ -2494,10 +2631,11 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
||||
count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
|
||||
prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable),
|
||||
workspace, wkspSize);
|
||||
if (ZSTD_isError(countSize)) return countSize;
|
||||
FORWARD_IF_ERROR(countSize);
|
||||
if (MLtype == set_compressed)
|
||||
lastNCount = op;
|
||||
op += countSize;
|
||||
assert(op <= oend);
|
||||
} }
|
||||
|
||||
*seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
|
||||
@@ -2509,10 +2647,11 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
||||
CTable_LitLength, llCodeTable,
|
||||
sequences, nbSeq,
|
||||
longOffsets, bmi2);
|
||||
if (ZSTD_isError(bitstreamSize)) return bitstreamSize;
|
||||
FORWARD_IF_ERROR(bitstreamSize);
|
||||
op += bitstreamSize;
|
||||
assert(op <= oend);
|
||||
/* zstd versions <= 1.3.4 mistakenly report corruption when
|
||||
* FSE_readNCount() recieves a buffer < 4 bytes.
|
||||
* FSE_readNCount() receives a buffer < 4 bytes.
|
||||
* Fixed by https://github.com/facebook/zstd/pull/1146.
|
||||
* This can happen when the last set_compressed table present is 2
|
||||
* bytes and the bitstream is only one byte.
|
||||
@@ -2552,7 +2691,7 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
|
||||
*/
|
||||
if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
|
||||
return 0; /* block not compressed */
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
FORWARD_IF_ERROR(cSize);
|
||||
|
||||
/* Check compressibility */
|
||||
{ size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
|
||||
@@ -2622,27 +2761,24 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr)
|
||||
ssPtr->longLengthID = 0;
|
||||
}
|
||||
|
||||
static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e;
|
||||
|
||||
static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
{
|
||||
ZSTD_matchState_t* const ms = &zc->blockState.matchState;
|
||||
size_t cSize;
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
|
||||
(unsigned)dstCapacity, (unsigned)ms->window.dictLimit, (unsigned)ms->nextToUpdate);
|
||||
DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize);
|
||||
assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
|
||||
|
||||
/* Assert that we have correctly flushed the ctx params into the ms's copy */
|
||||
ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
|
||||
|
||||
if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
|
||||
ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
|
||||
cSize = 0;
|
||||
goto out; /* don't even attempt compression below a certain srcSize */
|
||||
return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */
|
||||
}
|
||||
ZSTD_resetSeqStore(&(zc->seqStore));
|
||||
ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; /* required for optimal parser to read stats from dictionary */
|
||||
|
||||
/* required for optimal parser to read stats from dictionary */
|
||||
ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
|
||||
/* tell the optimal parser how we expect to compress literals */
|
||||
ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
|
||||
/* a gap between an attached dict and the current window is not safe,
|
||||
* they must remain adjacent,
|
||||
* and when that stops being the case, the dict must be unset */
|
||||
@@ -2679,7 +2815,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
||||
ldmSeqStore.seq = zc->ldmSequences;
|
||||
ldmSeqStore.capacity = zc->maxNbLdmSequences;
|
||||
/* Updates ldmSeqStore.size */
|
||||
CHECK_F(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
|
||||
FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
|
||||
&zc->appliedParams.ldmParams,
|
||||
src, srcSize));
|
||||
/* Updates ldmSeqStore.pos */
|
||||
@@ -2696,6 +2832,21 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
||||
{ const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
|
||||
ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
|
||||
} }
|
||||
return ZSTDbss_compress;
|
||||
}
|
||||
|
||||
static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
size_t cSize;
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
|
||||
(unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate);
|
||||
|
||||
{ const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
|
||||
FORWARD_IF_ERROR(bss);
|
||||
if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; }
|
||||
}
|
||||
|
||||
/* encode sequences and literals */
|
||||
cSize = ZSTD_compressSequences(&zc->seqStore,
|
||||
@@ -2724,6 +2875,25 @@ out:
|
||||
}
|
||||
|
||||
|
||||
static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, void const* ip, void const* iend)
|
||||
{
|
||||
if (ZSTD_window_needOverflowCorrection(ms->window, iend)) {
|
||||
U32 const maxDist = (U32)1 << params->cParams.windowLog;
|
||||
U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);
|
||||
U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
||||
ZSTD_reduceIndex(ms, params, correction);
|
||||
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
|
||||
else ms->nextToUpdate -= correction;
|
||||
/* invalidate dictionaries on overflow correction */
|
||||
ms->loadedDictEnd = 0;
|
||||
ms->dictMatchState = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! ZSTD_compress_frameChunk() :
|
||||
* Compress a chunk of data into one or multiple blocks.
|
||||
* All blocks will be terminated, all input will be consumed.
|
||||
@@ -2742,7 +2912,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* op = ostart;
|
||||
U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
|
||||
assert(cctx->appliedParams.cParams.windowLog <= 31);
|
||||
assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
|
||||
if (cctx->appliedParams.fParams.checksumFlag && srcSize)
|
||||
@@ -2752,33 +2922,25 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
||||
ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
|
||||
U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
|
||||
|
||||
if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE)
|
||||
return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
|
||||
RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE,
|
||||
dstSize_tooSmall,
|
||||
"not enough space to store compressed block");
|
||||
if (remaining < blockSize) blockSize = remaining;
|
||||
|
||||
if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) {
|
||||
U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
|
||||
U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
||||
ZSTD_reduceIndex(cctx, correction);
|
||||
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
|
||||
else ms->nextToUpdate -= correction;
|
||||
ms->loadedDictEnd = 0;
|
||||
ms->dictMatchState = NULL;
|
||||
}
|
||||
ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
|
||||
ZSTD_overflowCorrectIfNeeded(ms, &cctx->appliedParams, ip, ip + blockSize);
|
||||
ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
|
||||
|
||||
/* Ensure hash/chain table insertion resumes no sooner than lowlimit */
|
||||
if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
|
||||
|
||||
{ size_t cSize = ZSTD_compressBlock_internal(cctx,
|
||||
op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
|
||||
ip, blockSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
FORWARD_IF_ERROR(cSize);
|
||||
|
||||
if (cSize == 0) { /* block is not compressible */
|
||||
cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
FORWARD_IF_ERROR(cSize);
|
||||
} else {
|
||||
U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
|
||||
MEM_writeLE24(op, cBlockHeader24);
|
||||
@@ -2796,7 +2958,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
||||
} }
|
||||
|
||||
if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
|
||||
return op-ostart;
|
||||
return (size_t)(op-ostart);
|
||||
}
|
||||
|
||||
|
||||
@@ -2811,11 +2973,11 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
||||
BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
|
||||
U32 const fcsCode = params.fParams.contentSizeFlag ?
|
||||
(pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
|
||||
BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
|
||||
BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
|
||||
size_t pos=0;
|
||||
|
||||
assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
|
||||
if (dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall);
|
||||
DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
|
||||
!params.fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
|
||||
|
||||
@@ -2823,7 +2985,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
||||
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
|
||||
pos = 4;
|
||||
}
|
||||
op[pos++] = frameHeaderDecriptionByte;
|
||||
op[pos++] = frameHeaderDescriptionByte;
|
||||
if (!singleSegment) op[pos++] = windowLogByte;
|
||||
switch(dictIDSizeCode)
|
||||
{
|
||||
@@ -2847,11 +3009,11 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
||||
/* ZSTD_writeLastEmptyBlock() :
|
||||
* output an empty Block with end-of-frame mark to complete a frame
|
||||
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
|
||||
* or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
|
||||
* or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
|
||||
*/
|
||||
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
|
||||
{
|
||||
if (dstCapacity < ZSTD_blockHeaderSize) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall);
|
||||
{ U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
|
||||
MEM_writeLE24(dst, cBlockHeader24);
|
||||
return ZSTD_blockHeaderSize;
|
||||
@@ -2860,10 +3022,9 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
|
||||
|
||||
size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
|
||||
{
|
||||
if (cctx->stage != ZSTDcs_init)
|
||||
return ERROR(stage_wrong);
|
||||
if (cctx->appliedParams.ldmParams.enableLdm)
|
||||
return ERROR(parameter_unsupported);
|
||||
RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong);
|
||||
RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
|
||||
parameter_unsupported);
|
||||
cctx->externSeqStore.seq = seq;
|
||||
cctx->externSeqStore.size = nbSeq;
|
||||
cctx->externSeqStore.capacity = nbSeq;
|
||||
@@ -2882,12 +3043,14 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
|
||||
cctx->stage, (unsigned)srcSize);
|
||||
if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */
|
||||
RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,
|
||||
"missing init (ZSTD_compressBegin)");
|
||||
|
||||
if (frame && (cctx->stage==ZSTDcs_init)) {
|
||||
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
|
||||
cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
|
||||
if (ZSTD_isError(fhSize)) return fhSize;
|
||||
FORWARD_IF_ERROR(fhSize);
|
||||
assert(fhSize <= dstCapacity);
|
||||
dstCapacity -= fhSize;
|
||||
dst = (char*)dst + fhSize;
|
||||
cctx->stage = ZSTDcs_ongoing;
|
||||
@@ -2904,35 +3067,25 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
||||
|
||||
if (!frame) {
|
||||
/* overflow check and correction for block mode */
|
||||
if (ZSTD_window_needOverflowCorrection(ms->window, (const char*)src + srcSize)) {
|
||||
U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
|
||||
U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, 1 << cctx->appliedParams.cParams.windowLog, src);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
||||
ZSTD_reduceIndex(cctx, correction);
|
||||
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
|
||||
else ms->nextToUpdate -= correction;
|
||||
ms->loadedDictEnd = 0;
|
||||
ms->dictMatchState = NULL;
|
||||
}
|
||||
ZSTD_overflowCorrectIfNeeded(ms, &cctx->appliedParams, src, (BYTE const*)src + srcSize);
|
||||
}
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize);
|
||||
{ size_t const cSize = frame ?
|
||||
ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
|
||||
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
FORWARD_IF_ERROR(cSize);
|
||||
cctx->consumedSrcSize += srcSize;
|
||||
cctx->producedCSize += (cSize + fhSize);
|
||||
assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
|
||||
if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
|
||||
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
|
||||
if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) {
|
||||
DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u",
|
||||
(unsigned)cctx->pledgedSrcSizePlusOne-1, (unsigned)cctx->consumedSrcSize);
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
RETURN_ERROR_IF(
|
||||
cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,
|
||||
srcSize_wrong,
|
||||
"error : pledgedSrcSize = %u, while realSrcSize >= %u",
|
||||
(unsigned)cctx->pledgedSrcSizePlusOne-1,
|
||||
(unsigned)cctx->consumedSrcSize);
|
||||
}
|
||||
return cSize + fhSize;
|
||||
}
|
||||
@@ -2957,7 +3110,7 @@ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
|
||||
size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
|
||||
if (srcSize > blockSizeMax) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong);
|
||||
|
||||
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
|
||||
}
|
||||
@@ -2970,7 +3123,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
|
||||
const void* src, size_t srcSize,
|
||||
ZSTD_dictTableLoadMethod_e dtlm)
|
||||
{
|
||||
const BYTE* const ip = (const BYTE*) src;
|
||||
const BYTE* ip = (const BYTE*) src;
|
||||
const BYTE* const iend = ip + srcSize;
|
||||
|
||||
ZSTD_window_update(&ms->window, src, srcSize);
|
||||
@@ -2981,32 +3134,42 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
|
||||
|
||||
if (srcSize <= HASH_READ_SIZE) return 0;
|
||||
|
||||
switch(params->cParams.strategy)
|
||||
{
|
||||
case ZSTD_fast:
|
||||
ZSTD_fillHashTable(ms, iend, dtlm);
|
||||
break;
|
||||
case ZSTD_dfast:
|
||||
ZSTD_fillDoubleHashTable(ms, iend, dtlm);
|
||||
break;
|
||||
while (iend - ip > HASH_READ_SIZE) {
|
||||
size_t const remaining = iend - ip;
|
||||
size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX);
|
||||
const BYTE* const ichunk = ip + chunk;
|
||||
|
||||
case ZSTD_greedy:
|
||||
case ZSTD_lazy:
|
||||
case ZSTD_lazy2:
|
||||
if (srcSize >= HASH_READ_SIZE)
|
||||
ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);
|
||||
break;
|
||||
ZSTD_overflowCorrectIfNeeded(ms, params, ip, ichunk);
|
||||
|
||||
case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
|
||||
case ZSTD_btopt:
|
||||
case ZSTD_btultra:
|
||||
case ZSTD_btultra2:
|
||||
if (srcSize >= HASH_READ_SIZE)
|
||||
ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
|
||||
break;
|
||||
switch(params->cParams.strategy)
|
||||
{
|
||||
case ZSTD_fast:
|
||||
ZSTD_fillHashTable(ms, ichunk, dtlm);
|
||||
break;
|
||||
case ZSTD_dfast:
|
||||
ZSTD_fillDoubleHashTable(ms, ichunk, dtlm);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0); /* not possible : not a valid strategy id */
|
||||
case ZSTD_greedy:
|
||||
case ZSTD_lazy:
|
||||
case ZSTD_lazy2:
|
||||
if (chunk >= HASH_READ_SIZE)
|
||||
ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE);
|
||||
break;
|
||||
|
||||
case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
|
||||
case ZSTD_btopt:
|
||||
case ZSTD_btultra:
|
||||
case ZSTD_btultra2:
|
||||
if (chunk >= HASH_READ_SIZE)
|
||||
ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0); /* not possible : not a valid strategy id */
|
||||
}
|
||||
|
||||
ip = ichunk;
|
||||
}
|
||||
|
||||
ms->nextToUpdate = (U32)(iend - ms->window.base);
|
||||
@@ -3020,9 +3183,9 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
|
||||
NOTE: This behavior is not standard and could be improved in the future. */
|
||||
static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) {
|
||||
U32 s;
|
||||
if (dictMaxSymbolValue < maxSymbolValue) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted);
|
||||
for (s = 0; s <= maxSymbolValue; ++s) {
|
||||
if (normalizedCounter[s] == 0) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3060,53 +3223,56 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
||||
|
||||
{ unsigned maxSymbolValue = 255;
|
||||
size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
|
||||
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
|
||||
if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted);
|
||||
RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted);
|
||||
dictPtr += hufHeaderSize;
|
||||
}
|
||||
|
||||
{ unsigned offcodeLog;
|
||||
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
||||
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
|
||||
if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
|
||||
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
|
||||
/* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
|
||||
/* fill all offset symbols to avoid garbage at end of table */
|
||||
CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.offcodeCTable,
|
||||
offcodeNCount, MaxOff, offcodeLog,
|
||||
workspace, HUF_WORKSPACE_SIZE),
|
||||
dictionary_corrupted);
|
||||
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
||||
bs->entropy.fse.offcodeCTable,
|
||||
offcodeNCount, MaxOff, offcodeLog,
|
||||
workspace, HUF_WORKSPACE_SIZE)),
|
||||
dictionary_corrupted);
|
||||
dictPtr += offcodeHeaderSize;
|
||||
}
|
||||
|
||||
{ short matchlengthNCount[MaxML+1];
|
||||
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
||||
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
||||
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
||||
if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
|
||||
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
|
||||
/* Every match length code must have non-zero probability */
|
||||
CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
|
||||
CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.matchlengthCTable,
|
||||
matchlengthNCount, matchlengthMaxValue, matchlengthLog,
|
||||
workspace, HUF_WORKSPACE_SIZE),
|
||||
dictionary_corrupted);
|
||||
FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
|
||||
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
||||
bs->entropy.fse.matchlengthCTable,
|
||||
matchlengthNCount, matchlengthMaxValue, matchlengthLog,
|
||||
workspace, HUF_WORKSPACE_SIZE)),
|
||||
dictionary_corrupted);
|
||||
dictPtr += matchlengthHeaderSize;
|
||||
}
|
||||
|
||||
{ short litlengthNCount[MaxLL+1];
|
||||
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
||||
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
||||
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
||||
if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
|
||||
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
|
||||
/* Every literal length code must have non-zero probability */
|
||||
CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
|
||||
CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.litlengthCTable,
|
||||
litlengthNCount, litlengthMaxValue, litlengthLog,
|
||||
workspace, HUF_WORKSPACE_SIZE),
|
||||
dictionary_corrupted);
|
||||
FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
|
||||
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
||||
bs->entropy.fse.litlengthCTable,
|
||||
litlengthNCount, litlengthMaxValue, litlengthLog,
|
||||
workspace, HUF_WORKSPACE_SIZE)),
|
||||
dictionary_corrupted);
|
||||
dictPtr += litlengthHeaderSize;
|
||||
}
|
||||
|
||||
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
|
||||
bs->rep[0] = MEM_readLE32(dictPtr+0);
|
||||
bs->rep[1] = MEM_readLE32(dictPtr+4);
|
||||
bs->rep[2] = MEM_readLE32(dictPtr+8);
|
||||
@@ -3119,19 +3285,19 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
||||
offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
|
||||
}
|
||||
/* All offset values <= dictContentSize + 128 KB must be representable */
|
||||
CHECK_F (ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
|
||||
FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
|
||||
/* All repCodes must be <= dictContentSize and != 0*/
|
||||
{ U32 u;
|
||||
for (u=0; u<3; u++) {
|
||||
if (bs->rep[u] == 0) return ERROR(dictionary_corrupted);
|
||||
if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted);
|
||||
RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted);
|
||||
} }
|
||||
|
||||
bs->entropy.huf.repeatMode = HUF_repeat_valid;
|
||||
bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
|
||||
bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
|
||||
bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
|
||||
CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm));
|
||||
FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm));
|
||||
return dictID;
|
||||
}
|
||||
}
|
||||
@@ -3161,8 +3327,7 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
|
||||
DEBUGLOG(4, "raw content dictionary detected");
|
||||
return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
|
||||
}
|
||||
if (dictContentType == ZSTD_dct_fullDict)
|
||||
return ERROR(dictionary_wrong);
|
||||
RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong);
|
||||
assert(0); /* impossible */
|
||||
}
|
||||
|
||||
@@ -3189,14 +3354,13 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
||||
return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
|
||||
}
|
||||
|
||||
CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
||||
FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
||||
ZSTDcrp_continue, zbuff) );
|
||||
{
|
||||
size_t const dictID = ZSTD_compress_insertDictionary(
|
||||
{ size_t const dictID = ZSTD_compress_insertDictionary(
|
||||
cctx->blockState.prevCBlock, &cctx->blockState.matchState,
|
||||
¶ms, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace);
|
||||
if (ZSTD_isError(dictID)) return dictID;
|
||||
assert(dictID <= (size_t)(U32)-1);
|
||||
FORWARD_IF_ERROR(dictID);
|
||||
assert(dictID <= UINT_MAX);
|
||||
cctx->dictID = (U32)dictID;
|
||||
}
|
||||
return 0;
|
||||
@@ -3212,7 +3376,7 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog);
|
||||
/* compression parameters verification and optimization */
|
||||
CHECK_F( ZSTD_checkCParams(params.cParams) );
|
||||
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
|
||||
return ZSTD_compressBegin_internal(cctx,
|
||||
dict, dictSize, dictContentType, dtlm,
|
||||
cdict,
|
||||
@@ -3260,12 +3424,12 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
||||
size_t fhSize = 0;
|
||||
|
||||
DEBUGLOG(4, "ZSTD_writeEpilogue");
|
||||
if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */
|
||||
RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing");
|
||||
|
||||
/* special case : empty frame */
|
||||
if (cctx->stage == ZSTDcs_init) {
|
||||
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
|
||||
if (ZSTD_isError(fhSize)) return fhSize;
|
||||
FORWARD_IF_ERROR(fhSize);
|
||||
dstCapacity -= fhSize;
|
||||
op += fhSize;
|
||||
cctx->stage = ZSTDcs_ongoing;
|
||||
@@ -3274,7 +3438,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
||||
if (cctx->stage != ZSTDcs_ending) {
|
||||
/* write one last empty block, make it the "last" block */
|
||||
U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
|
||||
if (dstCapacity<4) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
|
||||
MEM_writeLE32(op, cBlockHeader24);
|
||||
op += ZSTD_blockHeaderSize;
|
||||
dstCapacity -= ZSTD_blockHeaderSize;
|
||||
@@ -3282,7 +3446,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
||||
|
||||
if (cctx->appliedParams.fParams.checksumFlag) {
|
||||
U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
|
||||
if (dstCapacity<4) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
|
||||
DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
|
||||
MEM_writeLE32(op, checksum);
|
||||
op += 4;
|
||||
@@ -3300,18 +3464,20 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
|
||||
size_t const cSize = ZSTD_compressContinue_internal(cctx,
|
||||
dst, dstCapacity, src, srcSize,
|
||||
1 /* frame mode */, 1 /* last chunk */);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
FORWARD_IF_ERROR(cSize);
|
||||
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
|
||||
if (ZSTD_isError(endResult)) return endResult;
|
||||
FORWARD_IF_ERROR(endResult);
|
||||
assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
|
||||
if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
|
||||
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
|
||||
DEBUGLOG(4, "end of frame : controlling src size");
|
||||
if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
|
||||
DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u",
|
||||
(unsigned)cctx->pledgedSrcSizePlusOne-1, (unsigned)cctx->consumedSrcSize);
|
||||
return ERROR(srcSize_wrong);
|
||||
} }
|
||||
RETURN_ERROR_IF(
|
||||
cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,
|
||||
srcSize_wrong,
|
||||
"error : pledgedSrcSize = %u, while realSrcSize = %u",
|
||||
(unsigned)cctx->pledgedSrcSizePlusOne-1,
|
||||
(unsigned)cctx->consumedSrcSize);
|
||||
}
|
||||
return cSize + endResult;
|
||||
}
|
||||
|
||||
@@ -3339,7 +3505,7 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
|
||||
ZSTD_parameters params)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_compress_advanced");
|
||||
CHECK_F(ZSTD_checkCParams(params.cParams));
|
||||
FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams));
|
||||
return ZSTD_compress_internal(cctx,
|
||||
dst, dstCapacity,
|
||||
src, srcSize,
|
||||
@@ -3356,7 +3522,7 @@ size_t ZSTD_compress_advanced_internal(
|
||||
ZSTD_CCtx_params params)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
|
||||
CHECK_F( ZSTD_compressBegin_internal(cctx,
|
||||
FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
|
||||
dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
|
||||
params, srcSize, ZSTDb_not_buffered) );
|
||||
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
|
||||
@@ -3440,17 +3606,17 @@ static size_t ZSTD_initCDict_internal(
|
||||
void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem);
|
||||
cdict->dictBuffer = internalBuffer;
|
||||
cdict->dictContent = internalBuffer;
|
||||
if (!internalBuffer) return ERROR(memory_allocation);
|
||||
RETURN_ERROR_IF(!internalBuffer, memory_allocation);
|
||||
memcpy(internalBuffer, dictBuffer, dictSize);
|
||||
}
|
||||
cdict->dictContentSize = dictSize;
|
||||
|
||||
/* Reset the state to no dictionary */
|
||||
ZSTD_reset_compressedBlockState(&cdict->cBlockState);
|
||||
{ void* const end = ZSTD_reset_matchState(
|
||||
&cdict->matchState,
|
||||
(U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32,
|
||||
&cParams, ZSTDcrp_continue, /* forCCtx */ 0);
|
||||
{ void* const end = ZSTD_reset_matchState(&cdict->matchState,
|
||||
(U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32,
|
||||
&cParams,
|
||||
ZSTDcrp_continue, ZSTD_resetTarget_CDict);
|
||||
assert(end == (char*)cdict->workspace + cdict->workspaceSize);
|
||||
(void)end;
|
||||
}
|
||||
@@ -3466,7 +3632,7 @@ static size_t ZSTD_initCDict_internal(
|
||||
&cdict->cBlockState, &cdict->matchState, ¶ms,
|
||||
cdict->dictContent, cdict->dictContentSize,
|
||||
dictContentType, ZSTD_dtlm_full, cdict->workspace);
|
||||
if (ZSTD_isError(dictID)) return dictID;
|
||||
FORWARD_IF_ERROR(dictID);
|
||||
assert(dictID <= (size_t)(U32)-1);
|
||||
cdict->dictID = (U32)dictID;
|
||||
}
|
||||
@@ -3596,7 +3762,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
|
||||
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
|
||||
if (cdict==NULL) return ERROR(dictionary_wrong);
|
||||
RETURN_ERROR_IF(cdict==NULL, dictionary_wrong);
|
||||
{ ZSTD_CCtx_params params = cctx->requestedParams;
|
||||
params.cParams = ZSTD_getCParamsFromCDict(cdict);
|
||||
/* Increase window log to fit the entire dictionary and source if the
|
||||
@@ -3632,7 +3798,7 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
|
||||
{
|
||||
CHECK_F (ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */
|
||||
FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */
|
||||
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
@@ -3700,7 +3866,7 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
||||
|
||||
CHECK_F( ZSTD_compressBegin_internal(cctx,
|
||||
FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
|
||||
dict, dictSize, dictContentType, ZSTD_dtlm_fast,
|
||||
cdict,
|
||||
params, pledgedSrcSize,
|
||||
@@ -3718,13 +3884,17 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
|
||||
|
||||
/* ZSTD_resetCStream():
|
||||
* pledgedSrcSize == 0 means "unknown" */
|
||||
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
|
||||
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
|
||||
{
|
||||
ZSTD_CCtx_params params = zcs->requestedParams;
|
||||
/* temporary : 0 interpreted as "unknown" during transition period.
|
||||
* Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
* 0 will be interpreted as "empty" in the future.
|
||||
*/
|
||||
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
|
||||
DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
|
||||
if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
||||
params.fParams.contentSizeFlag = 1;
|
||||
return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! ZSTD_initCStream_internal() :
|
||||
@@ -3736,32 +3906,18 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
||||
ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_initCStream_internal");
|
||||
params.cParams = ZSTD_getCParamsFromCCtxParams(¶ms, pledgedSrcSize, dictSize);
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
zcs->requestedParams = params;
|
||||
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
||||
|
||||
if (dict && dictSize >= 8) {
|
||||
DEBUGLOG(4, "loading dictionary of size %u", (unsigned)dictSize);
|
||||
if (zcs->staticSize) { /* static CCtx : never uses malloc */
|
||||
/* incompatible with internal cdict creation */
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
ZSTD_freeCDict(zcs->cdictLocal);
|
||||
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
|
||||
ZSTD_dlm_byCopy, ZSTD_dct_auto,
|
||||
params.cParams, zcs->customMem);
|
||||
zcs->cdict = zcs->cdictLocal;
|
||||
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
||||
if (dict) {
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
|
||||
} else {
|
||||
if (cdict) {
|
||||
params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict; it includes windowLog */
|
||||
}
|
||||
ZSTD_freeCDict(zcs->cdictLocal);
|
||||
zcs->cdictLocal = NULL;
|
||||
zcs->cdict = cdict;
|
||||
/* Dictionary is cleared if !cdict */
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
|
||||
}
|
||||
|
||||
return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ZSTD_initCStream_usingCDict_advanced() :
|
||||
@@ -3772,22 +3928,20 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
||||
unsigned long long pledgedSrcSize)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
|
||||
if (!cdict) return ERROR(dictionary_wrong); /* cannot handle NULL cdict (does not know what to do) */
|
||||
{ ZSTD_CCtx_params params = zcs->requestedParams;
|
||||
params.cParams = ZSTD_getCParamsFromCDict(cdict);
|
||||
params.fParams = fParams;
|
||||
return ZSTD_initCStream_internal(zcs,
|
||||
NULL, 0, cdict,
|
||||
params, pledgedSrcSize);
|
||||
}
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
||||
zcs->requestedParams.fParams = fParams;
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* note : cdict must outlive compression session */
|
||||
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
|
||||
{
|
||||
ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksum */, 0 /* hideDictID */ };
|
||||
DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
|
||||
return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); /* note : will check that cdict != NULL */
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3797,33 +3951,53 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
|
||||
* dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */
|
||||
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
ZSTD_parameters params, unsigned long long pss)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u",
|
||||
(unsigned)pledgedSrcSize, params.fParams.contentSizeFlag);
|
||||
CHECK_F( ZSTD_checkCParams(params.cParams) );
|
||||
if ((pledgedSrcSize==0) && (params.fParams.contentSizeFlag==0)) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */
|
||||
/* for compatibility with older programs relying on this behavior.
|
||||
* Users should now specify ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
* This line will be removed in the future.
|
||||
*/
|
||||
U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
|
||||
DEBUGLOG(4, "ZSTD_initCStream_advanced");
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
||||
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
|
||||
zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
|
||||
return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, zcs->requestedParams, pledgedSrcSize);
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel);
|
||||
return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, zcs->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN);
|
||||
DEBUGLOG(4, "ZSTD_initCStream_usingDict");
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
|
||||
{
|
||||
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; /* temporary : 0 interpreted as "unknown" during transition period. Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. `0` will be interpreted as "empty" in the future */
|
||||
ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel);
|
||||
return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, zcs->requestedParams, pledgedSrcSize);
|
||||
/* temporary : 0 interpreted as "unknown" during transition period.
|
||||
* Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
* 0 will be interpreted as "empty" in the future.
|
||||
*/
|
||||
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
|
||||
DEBUGLOG(4, "ZSTD_initCStream_srcSize");
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_initCStream");
|
||||
return ZSTD_initCStream_srcSize(zcs, compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN);
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
|
||||
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*====== Compression ======*/
|
||||
@@ -3847,10 +4021,10 @@ static size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
|
||||
* internal function for all *compressStream*() variants
|
||||
* non-static, because can be called from zstdmt_compress.c
|
||||
* @return : hint size for next input */
|
||||
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective const flushMode)
|
||||
static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective const flushMode)
|
||||
{
|
||||
const char* const istart = (const char*)input->src;
|
||||
const char* const iend = istart + input->size;
|
||||
@@ -3873,8 +4047,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
switch(zcs->streamStage)
|
||||
{
|
||||
case zcss_init:
|
||||
/* call ZSTD_initCStream() first ! */
|
||||
return ERROR(init_missing);
|
||||
RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!");
|
||||
|
||||
case zcss_load:
|
||||
if ( (flushMode == ZSTD_e_end)
|
||||
@@ -3884,7 +4057,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
size_t const cSize = ZSTD_compressEnd(zcs,
|
||||
op, oend-op, ip, iend-ip);
|
||||
DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
FORWARD_IF_ERROR(cSize);
|
||||
ip = iend;
|
||||
op += cSize;
|
||||
zcs->frameEnded = 1;
|
||||
@@ -3925,7 +4098,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
zcs->inBuff + zcs->inToCompress, iSize) :
|
||||
ZSTD_compressContinue(zcs, cDst, oSize,
|
||||
zcs->inBuff + zcs->inToCompress, iSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
FORWARD_IF_ERROR(cSize);
|
||||
zcs->frameEnded = lastBlock;
|
||||
/* prepare next block */
|
||||
zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
|
||||
@@ -3953,7 +4126,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
case zcss_flush:
|
||||
DEBUGLOG(5, "flush stage");
|
||||
{ size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
|
||||
size_t const flushed = ZSTD_limitCopy(op, oend-op,
|
||||
size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
|
||||
zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
|
||||
DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
|
||||
(unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);
|
||||
@@ -4001,7 +4174,7 @@ static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)
|
||||
|
||||
size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
||||
{
|
||||
CHECK_F( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) );
|
||||
FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) );
|
||||
return ZSTD_nextInputSizeHint_MTorST(zcs);
|
||||
}
|
||||
|
||||
@@ -4013,14 +4186,15 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
|
||||
/* check conditions */
|
||||
if (output->pos > output->size) return ERROR(GENERIC);
|
||||
if (input->pos > input->size) return ERROR(GENERIC);
|
||||
RETURN_ERROR_IF(output->pos > output->size, GENERIC);
|
||||
RETURN_ERROR_IF(input->pos > input->size, GENERIC);
|
||||
assert(cctx!=NULL);
|
||||
|
||||
/* transparent initialization stage */
|
||||
if (cctx->streamStage == zcss_init) {
|
||||
ZSTD_CCtx_params params = cctx->requestedParams;
|
||||
ZSTD_prefixDict const prefixDict = cctx->prefixDict;
|
||||
FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) ); /* Init the local dict if present. */
|
||||
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
|
||||
assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
|
||||
DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
|
||||
@@ -4039,11 +4213,11 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||
DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
|
||||
params.nbWorkers);
|
||||
cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
|
||||
if (cctx->mtctx == NULL) return ERROR(memory_allocation);
|
||||
RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation);
|
||||
}
|
||||
/* mt compression */
|
||||
DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
|
||||
CHECK_F( ZSTDMT_initCStream_internal(
|
||||
FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
|
||||
cctx->mtctx,
|
||||
prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent,
|
||||
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
|
||||
@@ -4051,7 +4225,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||
cctx->appliedParams.nbWorkers = params.nbWorkers;
|
||||
} else
|
||||
#endif
|
||||
{ CHECK_F( ZSTD_resetCStream_internal(cctx,
|
||||
{ FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
|
||||
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
|
||||
cctx->cdict,
|
||||
params, cctx->pledgedSrcSizePlusOne-1) );
|
||||
@@ -4063,20 +4237,30 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||
/* compression stage */
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
if (cctx->appliedParams.nbWorkers > 0) {
|
||||
int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
|
||||
size_t flushMin;
|
||||
assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */);
|
||||
if (cctx->cParamsChanged) {
|
||||
ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
|
||||
cctx->cParamsChanged = 0;
|
||||
}
|
||||
{ size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
||||
do {
|
||||
flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
||||
if ( ZSTD_isError(flushMin)
|
||||
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
||||
}
|
||||
DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
|
||||
return flushMin;
|
||||
} }
|
||||
FORWARD_IF_ERROR(flushMin);
|
||||
} while (forceMaxProgress && flushMin != 0 && output->pos < output->size);
|
||||
DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
|
||||
/* Either we don't require maximum forward progress, we've finished the
|
||||
* flush, or we are out of output space.
|
||||
*/
|
||||
assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size);
|
||||
return flushMin;
|
||||
}
|
||||
#endif
|
||||
CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
|
||||
FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) );
|
||||
DEBUGLOG(5, "completed ZSTD_compressStream2");
|
||||
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
|
||||
}
|
||||
@@ -4107,10 +4291,10 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
||||
dst, dstCapacity, &oPos,
|
||||
src, srcSize, &iPos,
|
||||
ZSTD_e_end);
|
||||
if (ZSTD_isError(result)) return result;
|
||||
FORWARD_IF_ERROR(result);
|
||||
if (result != 0) { /* compression not completed, due to lack of output space */
|
||||
assert(oPos == dstCapacity);
|
||||
return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR(dstSize_tooSmall);
|
||||
}
|
||||
assert(iPos == srcSize); /* all input is expected consumed */
|
||||
return oPos;
|
||||
@@ -4132,11 +4316,11 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
|
||||
{
|
||||
ZSTD_inBuffer input = { NULL, 0, 0 };
|
||||
size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
|
||||
CHECK_F( remainingToFlush );
|
||||
FORWARD_IF_ERROR( remainingToFlush );
|
||||
if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */
|
||||
/* single thread mode : attempt to calculate remaining to flush more precisely */
|
||||
{ size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
|
||||
size_t const checksumSize = zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4;
|
||||
size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4);
|
||||
size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;
|
||||
DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush);
|
||||
return toFlush;
|
||||
@@ -4151,7 +4335,7 @@ int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
|
||||
int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
|
||||
|
||||
static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
|
||||
{ /* "default" - guarantees a monotonically increasing memory budget */
|
||||
{ /* "default" - for any srcSize > 256 KB */
|
||||
/* W, C, H, S, L, TL, strat */
|
||||
{ 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
|
||||
{ 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
|
||||
@@ -4258,13 +4442,13 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
||||
};
|
||||
|
||||
/*! ZSTD_getCParams() :
|
||||
* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
|
||||
* Size values are optional, provide 0 if not known or unused */
|
||||
* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
|
||||
* Size values are optional, provide 0 if not known or unused */
|
||||
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
|
||||
{
|
||||
size_t const addedSize = srcSizeHint ? 0 : 500;
|
||||
U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : (U64)-1;
|
||||
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
|
||||
U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : ZSTD_CONTENTSIZE_UNKNOWN; /* intentional overflow for srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN */
|
||||
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
|
||||
int row = compressionLevel;
|
||||
DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel);
|
||||
if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
|
||||
@@ -4272,13 +4456,14 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
|
||||
if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
|
||||
{ ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
|
||||
if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
|
||||
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize);
|
||||
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); /* refine parameters based on srcSize & dictSize */
|
||||
}
|
||||
}
|
||||
|
||||
/*! ZSTD_getParams() :
|
||||
* same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`).
|
||||
* All fields of `ZSTD_frameParameters` are set to default (0) */
|
||||
* same idea as ZSTD_getCParams()
|
||||
* @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
|
||||
* Fields of `ZSTD_frameParameters` are set to default values */
|
||||
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
|
||||
ZSTD_parameters params;
|
||||
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
|
||||
|
||||
@@ -33,13 +33,13 @@ extern "C" {
|
||||
***************************************/
|
||||
#define kSearchStrength 8
|
||||
#define HASH_READ_SIZE 8
|
||||
#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1 now means "unsorted".
|
||||
#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index ZSTD_DUBT_UNSORTED_MARK==1 means "unsorted".
|
||||
It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
|
||||
It's not a big deal though : candidate will just be sorted again.
|
||||
Additionnally, candidate position 1 will be lost.
|
||||
Additionally, candidate position 1 will be lost.
|
||||
But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
|
||||
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be misdhandled after table re-use with a different strategy
|
||||
Constant required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
|
||||
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy.
|
||||
This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -54,6 +54,14 @@ typedef struct ZSTD_prefixDict_s {
|
||||
ZSTD_dictContentType_e dictContentType;
|
||||
} ZSTD_prefixDict;
|
||||
|
||||
typedef struct {
|
||||
void* dictBuffer;
|
||||
void const* dict;
|
||||
size_t dictSize;
|
||||
ZSTD_dictContentType_e dictContentType;
|
||||
ZSTD_CDict* cdict;
|
||||
} ZSTD_localDict;
|
||||
|
||||
typedef struct {
|
||||
U32 CTable[HUF_CTABLE_SIZE_U32(255)];
|
||||
HUF_repeat repeatMode;
|
||||
@@ -107,6 +115,7 @@ typedef struct {
|
||||
U32 offCodeSumBasePrice; /* to compare to log2(offreq) */
|
||||
ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */
|
||||
const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */
|
||||
ZSTD_literalCompressionMode_e literalCompressionMode;
|
||||
} optState_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -119,21 +128,20 @@ typedef struct {
|
||||
BYTE const* base; /* All regular indexes relative to this position */
|
||||
BYTE const* dictBase; /* extDict indexes relative to this position */
|
||||
U32 dictLimit; /* below that point, need extDict */
|
||||
U32 lowLimit; /* below that point, no more data */
|
||||
U32 lowLimit; /* below that point, no more valid data */
|
||||
} ZSTD_window_t;
|
||||
|
||||
typedef struct ZSTD_matchState_t ZSTD_matchState_t;
|
||||
struct ZSTD_matchState_t {
|
||||
ZSTD_window_t window; /* State for window round buffer management */
|
||||
U32 loadedDictEnd; /* index of end of dictionary */
|
||||
U32 loadedDictEnd; /* index of end of dictionary, within context's referential. When dict referential is copied into active context (i.e. not attached), effectively same value as dictSize, since referential starts from zero */
|
||||
U32 nextToUpdate; /* index from which to continue table update */
|
||||
U32 nextToUpdate3; /* index from which to continue table update */
|
||||
U32 hashLog3; /* dispatch table : larger == faster, more memory */
|
||||
U32* hashTable;
|
||||
U32* hashTable3;
|
||||
U32* chainTable;
|
||||
optState_t opt; /* optimal parser state */
|
||||
const ZSTD_matchState_t * dictMatchState;
|
||||
const ZSTD_matchState_t* dictMatchState;
|
||||
ZSTD_compressionParameters cParams;
|
||||
};
|
||||
|
||||
@@ -186,8 +194,12 @@ struct ZSTD_CCtx_params_s {
|
||||
int compressionLevel;
|
||||
int forceWindow; /* force back-references to respect limit of
|
||||
* 1<<wLog, even for dictionary */
|
||||
size_t targetCBlockSize; /* Tries to fit compressed block size to be around targetCBlockSize.
|
||||
* No target when targetCBlockSize == 0.
|
||||
* There is no guarantee on compressed block size */
|
||||
|
||||
ZSTD_dictAttachPref_e attachDictPref;
|
||||
ZSTD_literalCompressionMode_e literalCompressionMode;
|
||||
|
||||
/* Multithreading: used to pass parameters to mtctx */
|
||||
int nbWorkers;
|
||||
@@ -243,7 +255,7 @@ struct ZSTD_CCtx_s {
|
||||
U32 frameEnded;
|
||||
|
||||
/* Dictionary */
|
||||
ZSTD_CDict* cdictLocal;
|
||||
ZSTD_localDict localDict;
|
||||
const ZSTD_CDict* cdict;
|
||||
ZSTD_prefixDict prefixDict; /* single-usage dictionary */
|
||||
|
||||
@@ -314,7 +326,7 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const v
|
||||
/* copy Literals */
|
||||
assert(seqStorePtr->maxNbLit <= 128 KB);
|
||||
assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit);
|
||||
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
|
||||
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength, ZSTD_no_overlap);
|
||||
seqStorePtr->lit += litLength;
|
||||
|
||||
/* literal Length */
|
||||
@@ -554,6 +566,9 @@ MEM_STATIC U64 ZSTD_rollingHash_rotate(U64 hash, BYTE toRemove, BYTE toAdd, U64
|
||||
/*-*************************************
|
||||
* Round buffer management
|
||||
***************************************/
|
||||
#if (ZSTD_WINDOWLOG_MAX_64 > 31)
|
||||
# error "ZSTD_WINDOWLOG_MAX is too large : would overflow ZSTD_CURRENT_MAX"
|
||||
#endif
|
||||
/* Max current allowed */
|
||||
#define ZSTD_CURRENT_MAX ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX))
|
||||
/* Maximum chunk size before overflow correction needs to be called again */
|
||||
@@ -665,31 +680,49 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
||||
* Updates lowLimit so that:
|
||||
* (srcEnd - base) - lowLimit == maxDist + loadedDictEnd
|
||||
*
|
||||
* This allows a simple check that index >= lowLimit to see if index is valid.
|
||||
* This must be called before a block compression call, with srcEnd as the block
|
||||
* source end.
|
||||
* It ensures index is valid as long as index >= lowLimit.
|
||||
* This must be called before a block compression call.
|
||||
*
|
||||
* If loadedDictEndPtr is not NULL, we set it to zero once we update lowLimit.
|
||||
* This is because dictionaries are allowed to be referenced as long as the last
|
||||
* byte of the dictionary is in the window, but once they are out of range,
|
||||
* they cannot be referenced. If loadedDictEndPtr is NULL, we use
|
||||
* loadedDictEnd == 0.
|
||||
* loadedDictEnd is only defined if a dictionary is in use for current compression.
|
||||
* As the name implies, loadedDictEnd represents the index at end of dictionary.
|
||||
* The value lies within context's referential, it can be directly compared to blockEndIdx.
|
||||
*
|
||||
* In normal dict mode, the dict is between lowLimit and dictLimit. In
|
||||
* dictMatchState mode, lowLimit and dictLimit are the same, and the dictionary
|
||||
* is below them. forceWindow and dictMatchState are therefore incompatible.
|
||||
* If loadedDictEndPtr is NULL, no dictionary is in use, and we use loadedDictEnd == 0.
|
||||
* If loadedDictEndPtr is not NULL, we set it to zero after updating lowLimit.
|
||||
* This is because dictionaries are allowed to be referenced fully
|
||||
* as long as the last byte of the dictionary is in the window.
|
||||
* Once input has progressed beyond window size, dictionary cannot be referenced anymore.
|
||||
*
|
||||
* In normal dict mode, the dictionary lies between lowLimit and dictLimit.
|
||||
* In dictMatchState mode, lowLimit and dictLimit are the same,
|
||||
* and the dictionary is below them.
|
||||
* forceWindow and dictMatchState are therefore incompatible.
|
||||
*/
|
||||
MEM_STATIC void
|
||||
ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
|
||||
void const* srcEnd,
|
||||
U32 maxDist,
|
||||
U32* loadedDictEndPtr,
|
||||
const void* blockEnd,
|
||||
U32 maxDist,
|
||||
U32* loadedDictEndPtr,
|
||||
const ZSTD_matchState_t** dictMatchStatePtr)
|
||||
{
|
||||
U32 const blockEndIdx = (U32)((BYTE const*)srcEnd - window->base);
|
||||
U32 loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;
|
||||
DEBUGLOG(5, "ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u",
|
||||
(unsigned)blockEndIdx, (unsigned)maxDist);
|
||||
U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);
|
||||
U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;
|
||||
DEBUGLOG(5, "ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u",
|
||||
(unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
|
||||
|
||||
/* - When there is no dictionary : loadedDictEnd == 0.
|
||||
In which case, the test (blockEndIdx > maxDist) is merely to avoid
|
||||
overflowing next operation `newLowLimit = blockEndIdx - maxDist`.
|
||||
- When there is a standard dictionary :
|
||||
Index referential is copied from the dictionary,
|
||||
which means it starts from 0.
|
||||
In which case, loadedDictEnd == dictSize,
|
||||
and it makes sense to compare `blockEndIdx > maxDist + dictSize`
|
||||
since `blockEndIdx` also starts from zero.
|
||||
- When there is an attached dictionary :
|
||||
loadedDictEnd is expressed within the referential of the context,
|
||||
so it can be directly compared against blockEndIdx.
|
||||
*/
|
||||
if (blockEndIdx > maxDist + loadedDictEnd) {
|
||||
U32 const newLowLimit = blockEndIdx - maxDist;
|
||||
if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;
|
||||
@@ -698,10 +731,31 @@ ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
|
||||
(unsigned)window->dictLimit, (unsigned)window->lowLimit);
|
||||
window->dictLimit = window->lowLimit;
|
||||
}
|
||||
if (loadedDictEndPtr)
|
||||
*loadedDictEndPtr = 0;
|
||||
if (dictMatchStatePtr)
|
||||
*dictMatchStatePtr = NULL;
|
||||
/* On reaching window size, dictionaries are invalidated */
|
||||
if (loadedDictEndPtr) *loadedDictEndPtr = 0;
|
||||
if (dictMatchStatePtr) *dictMatchStatePtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Similar to ZSTD_window_enforceMaxDist(),
|
||||
* but only invalidates dictionary
|
||||
* when input progresses beyond window size. */
|
||||
MEM_STATIC void
|
||||
ZSTD_checkDictValidity(ZSTD_window_t* window,
|
||||
const void* blockEnd,
|
||||
U32 maxDist,
|
||||
U32* loadedDictEndPtr,
|
||||
const ZSTD_matchState_t** dictMatchStatePtr)
|
||||
{
|
||||
U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);
|
||||
U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;
|
||||
DEBUGLOG(5, "ZSTD_checkDictValidity: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u",
|
||||
(unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
|
||||
|
||||
if (loadedDictEnd && (blockEndIdx > maxDist + loadedDictEnd)) {
|
||||
/* On reaching window size, dictionaries are invalidated */
|
||||
if (loadedDictEndPtr) *loadedDictEndPtr = 0;
|
||||
if (dictMatchStatePtr) *dictMatchStatePtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,13 +860,6 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
||||
|
||||
void ZSTD_resetSeqStore(seqStore_t* ssPtr);
|
||||
|
||||
/*! ZSTD_compressStream_generic() :
|
||||
* Private use only. To be called from zstdmt_compress.c in single-thread mode. */
|
||||
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective const flushMode);
|
||||
|
||||
/*! ZSTD_getCParamsFromCDict() :
|
||||
* as the name implies */
|
||||
ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
|
||||
@@ -839,7 +886,7 @@ size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
|
||||
/* ZSTD_writeLastEmptyBlock() :
|
||||
* output an empty Block with end-of-frame mark to complete a frame
|
||||
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
|
||||
* or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
|
||||
* or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
|
||||
*/
|
||||
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
|
||||
|
||||
|
||||
@@ -43,8 +43,7 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
|
||||
/* Only load extra positions for ZSTD_dtlm_full */
|
||||
if (dtlm == ZSTD_dtlm_fast)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +62,10 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
const BYTE* ip = istart;
|
||||
const BYTE* anchor = istart;
|
||||
const U32 prefixLowestIndex = ms->window.dictLimit;
|
||||
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
||||
const U32 lowestValid = ms->window.dictLimit;
|
||||
const U32 maxDistance = 1U << cParams->windowLog;
|
||||
const U32 prefixLowestIndex = (endIndex - lowestValid > maxDistance) ? endIndex - maxDistance : lowestValid;
|
||||
const BYTE* const prefixLowest = base + prefixLowestIndex;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* const ilimit = iend - HASH_READ_SIZE;
|
||||
@@ -95,8 +97,15 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
dictCParams->chainLog : hBitsS;
|
||||
const U32 dictAndPrefixLength = (U32)(ip - prefixLowest + dictEnd - dictStart);
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_generic");
|
||||
|
||||
assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
|
||||
|
||||
/* if a dictionary is attached, it must be within window range */
|
||||
if (dictMode == ZSTD_dictMatchState) {
|
||||
assert(lowestValid + maxDistance >= endIndex);
|
||||
}
|
||||
|
||||
/* init */
|
||||
ip += (dictAndPrefixLength == 0);
|
||||
if (dictMode == ZSTD_noDict) {
|
||||
@@ -138,7 +147,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
|
||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
||||
goto _match_stored;
|
||||
}
|
||||
|
||||
@@ -147,7 +156,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
&& ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
|
||||
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
||||
goto _match_stored;
|
||||
}
|
||||
|
||||
@@ -170,8 +179,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
offset = (U32)(current - dictMatchIndexL - dictIndexDelta);
|
||||
while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */
|
||||
goto _match_found;
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
if (matchIndexS > prefixLowestIndex) {
|
||||
/* check prefix short match */
|
||||
@@ -186,16 +194,14 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
|
||||
if (match > dictStart && MEM_read32(match) == MEM_read32(ip)) {
|
||||
goto _search_next_long;
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
ip += ((ip-anchor) >> kSearchStrength) + 1;
|
||||
continue;
|
||||
|
||||
_search_next_long:
|
||||
|
||||
{
|
||||
size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
||||
{ size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
||||
size_t const dictHLNext = ZSTD_hashPtr(ip+1, dictHBitsL, 8);
|
||||
U32 const matchIndexL3 = hashLong[hl3];
|
||||
const BYTE* matchL3 = base + matchIndexL3;
|
||||
@@ -221,9 +227,7 @@ _search_next_long:
|
||||
offset = (U32)(current + 1 - dictMatchIndexL3 - dictIndexDelta);
|
||||
while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */
|
||||
goto _match_found;
|
||||
}
|
||||
}
|
||||
}
|
||||
} } }
|
||||
|
||||
/* if no long +1 match, explore the short match we found */
|
||||
if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) {
|
||||
@@ -242,7 +246,7 @@ _match_found:
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
|
||||
_match_stored:
|
||||
/* match found */
|
||||
@@ -250,11 +254,14 @@ _match_stored:
|
||||
anchor = ip;
|
||||
|
||||
if (ip <= ilimit) {
|
||||
/* Fill Table */
|
||||
hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] =
|
||||
hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2; /* here because current+2 could be > iend-8 */
|
||||
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] =
|
||||
hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
|
||||
/* Complementary insertion */
|
||||
/* done after iLimit test, as candidates could be > iend-8 */
|
||||
{ U32 const indexToInsert = current+2;
|
||||
hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;
|
||||
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
|
||||
hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;
|
||||
hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);
|
||||
}
|
||||
|
||||
/* check immediate repcode */
|
||||
if (dictMode == ZSTD_dictMatchState) {
|
||||
@@ -278,8 +285,7 @@ _match_stored:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
if (dictMode == ZSTD_noDict) {
|
||||
while ( (ip <= ilimit)
|
||||
@@ -294,14 +300,15 @@ _match_stored:
|
||||
ip += rLength;
|
||||
anchor = ip;
|
||||
continue; /* faster when present ... (?) */
|
||||
} } } }
|
||||
} } }
|
||||
} /* while (ip < ilimit) */
|
||||
|
||||
/* save reps for next block */
|
||||
rep[0] = offset_1 ? offset_1 : offsetSaved;
|
||||
rep[1] = offset_2 ? offset_2 : offsetSaved;
|
||||
|
||||
/* Return the last literals size */
|
||||
return iend - anchor;
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
|
||||
@@ -360,10 +367,15 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
const BYTE* anchor = istart;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* const ilimit = iend - 8;
|
||||
const U32 prefixStartIndex = ms->window.dictLimit;
|
||||
const BYTE* const base = ms->window.base;
|
||||
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
||||
const U32 maxDistance = 1U << cParams->windowLog;
|
||||
const U32 lowestValid = ms->window.lowLimit;
|
||||
const U32 lowLimit = (endIndex - lowestValid > maxDistance) ? endIndex - maxDistance : lowestValid;
|
||||
const U32 dictStartIndex = lowLimit;
|
||||
const U32 dictLimit = ms->window.dictLimit;
|
||||
const U32 prefixStartIndex = (dictLimit > lowLimit) ? dictLimit : lowLimit;
|
||||
const BYTE* const prefixStart = base + prefixStartIndex;
|
||||
const U32 dictStartIndex = ms->window.lowLimit;
|
||||
const BYTE* const dictBase = ms->window.dictBase;
|
||||
const BYTE* const dictStart = dictBase + dictStartIndex;
|
||||
const BYTE* const dictEnd = dictBase + prefixStartIndex;
|
||||
@@ -371,6 +383,10 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_extDict_generic (srcSize=%zu)", srcSize);
|
||||
|
||||
/* if extDict is invalidated due to maxDistance, switch to "regular" variant */
|
||||
if (prefixStartIndex == dictStartIndex)
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, mls, ZSTD_noDict);
|
||||
|
||||
/* Search Loop */
|
||||
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
|
||||
const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);
|
||||
@@ -396,7 +412,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
||||
} else {
|
||||
if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
|
||||
const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;
|
||||
@@ -407,7 +423,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
|
||||
} else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {
|
||||
size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
||||
@@ -432,23 +448,27 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
}
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
|
||||
} else {
|
||||
ip += ((ip-anchor) >> kSearchStrength) + 1;
|
||||
continue;
|
||||
} }
|
||||
|
||||
/* found a match : store it */
|
||||
/* move to next sequence start */
|
||||
ip += mLength;
|
||||
anchor = ip;
|
||||
|
||||
if (ip <= ilimit) {
|
||||
/* Fill Table */
|
||||
hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2;
|
||||
hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = current+2;
|
||||
hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
|
||||
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
|
||||
/* Complementary insertion */
|
||||
/* done after iLimit test, as candidates could be > iend-8 */
|
||||
{ U32 const indexToInsert = current+2;
|
||||
hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;
|
||||
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
|
||||
hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;
|
||||
hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);
|
||||
}
|
||||
|
||||
/* check immediate repcode */
|
||||
while (ip <= ilimit) {
|
||||
U32 const current2 = (U32)(ip-base);
|
||||
@@ -475,7 +495,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
rep[1] = offset_2;
|
||||
|
||||
/* Return the last literals size */
|
||||
return iend - anchor;
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+235
-135
@@ -13,7 +13,8 @@
|
||||
|
||||
|
||||
void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
|
||||
void const* end, ZSTD_dictTableLoadMethod_e dtlm)
|
||||
const void* const end,
|
||||
ZSTD_dictTableLoadMethod_e dtlm)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32* const hashTable = ms->hashTable;
|
||||
@@ -41,11 +42,163 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
|
||||
} } } }
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
size_t ZSTD_compressBlock_fast_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize,
|
||||
U32 const mls, ZSTD_dictMode_e const dictMode)
|
||||
U32 const mls)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32* const hashTable = ms->hashTable;
|
||||
U32 const hlog = cParams->hashLog;
|
||||
/* support stepSize of 0 */
|
||||
size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1;
|
||||
const BYTE* const base = ms->window.base;
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
/* We check ip0 (ip + 0) and ip1 (ip + 1) each loop */
|
||||
const BYTE* ip0 = istart;
|
||||
const BYTE* ip1;
|
||||
const BYTE* anchor = istart;
|
||||
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
||||
const U32 maxDistance = 1U << cParams->windowLog;
|
||||
const U32 validStartIndex = ms->window.dictLimit;
|
||||
const U32 prefixStartIndex = (endIndex - validStartIndex > maxDistance) ? endIndex - maxDistance : validStartIndex;
|
||||
const BYTE* const prefixStart = base + prefixStartIndex;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* const ilimit = iend - HASH_READ_SIZE;
|
||||
U32 offset_1=rep[0], offset_2=rep[1];
|
||||
U32 offsetSaved = 0;
|
||||
|
||||
/* init */
|
||||
ip0 += (ip0 == prefixStart);
|
||||
ip1 = ip0 + 1;
|
||||
{
|
||||
U32 const maxRep = (U32)(ip0 - prefixStart);
|
||||
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
|
||||
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
|
||||
}
|
||||
|
||||
/* Main Search Loop */
|
||||
while (ip1 < ilimit) { /* < instead of <=, because check at ip0+2 */
|
||||
size_t mLength;
|
||||
BYTE const* ip2 = ip0 + 2;
|
||||
size_t const h0 = ZSTD_hashPtr(ip0, hlog, mls);
|
||||
U32 const val0 = MEM_read32(ip0);
|
||||
size_t const h1 = ZSTD_hashPtr(ip1, hlog, mls);
|
||||
U32 const val1 = MEM_read32(ip1);
|
||||
U32 const current0 = (U32)(ip0-base);
|
||||
U32 const current1 = (U32)(ip1-base);
|
||||
U32 const matchIndex0 = hashTable[h0];
|
||||
U32 const matchIndex1 = hashTable[h1];
|
||||
BYTE const* repMatch = ip2-offset_1;
|
||||
const BYTE* match0 = base + matchIndex0;
|
||||
const BYTE* match1 = base + matchIndex1;
|
||||
U32 offcode;
|
||||
hashTable[h0] = current0; /* update hash table */
|
||||
hashTable[h1] = current1; /* update hash table */
|
||||
|
||||
assert(ip0 + 1 == ip1);
|
||||
|
||||
if ((offset_1 > 0) & (MEM_read32(repMatch) == MEM_read32(ip2))) {
|
||||
mLength = ip2[-1] == repMatch[-1] ? 1 : 0;
|
||||
ip0 = ip2 - mLength;
|
||||
match0 = repMatch - mLength;
|
||||
offcode = 0;
|
||||
goto _match;
|
||||
}
|
||||
if ((matchIndex0 > prefixStartIndex) && MEM_read32(match0) == val0) {
|
||||
/* found a regular match */
|
||||
goto _offset;
|
||||
}
|
||||
if ((matchIndex1 > prefixStartIndex) && MEM_read32(match1) == val1) {
|
||||
/* found a regular match after one literal */
|
||||
ip0 = ip1;
|
||||
match0 = match1;
|
||||
goto _offset;
|
||||
}
|
||||
{
|
||||
size_t const step = ((ip0-anchor) >> (kSearchStrength - 1)) + stepSize;
|
||||
assert(step >= 2);
|
||||
ip0 += step;
|
||||
ip1 += step;
|
||||
continue;
|
||||
}
|
||||
_offset: /* Requires: ip0, match0 */
|
||||
/* Compute the offset code */
|
||||
offset_2 = offset_1;
|
||||
offset_1 = (U32)(ip0-match0);
|
||||
offcode = offset_1 + ZSTD_REP_MOVE;
|
||||
mLength = 0;
|
||||
/* Count the backwards match length */
|
||||
while (((ip0>anchor) & (match0>prefixStart))
|
||||
&& (ip0[-1] == match0[-1])) { ip0--; match0--; mLength++; } /* catch up */
|
||||
|
||||
_match: /* Requires: ip0, match0, offcode */
|
||||
/* Count the forward length */
|
||||
mLength += ZSTD_count(ip0+mLength+4, match0+mLength+4, iend) + 4;
|
||||
ZSTD_storeSeq(seqStore, ip0-anchor, anchor, offcode, mLength-MINMATCH);
|
||||
/* match found */
|
||||
ip0 += mLength;
|
||||
anchor = ip0;
|
||||
ip1 = ip0 + 1;
|
||||
|
||||
if (ip0 <= ilimit) {
|
||||
/* Fill Table */
|
||||
assert(base+current0+2 > istart); /* check base overflow */
|
||||
hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */
|
||||
hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);
|
||||
|
||||
while ( (ip0 <= ilimit)
|
||||
&& ( (offset_2>0)
|
||||
& (MEM_read32(ip0) == MEM_read32(ip0 - offset_2)) )) {
|
||||
/* store sequence */
|
||||
size_t const rLength = ZSTD_count(ip0+4, ip0+4-offset_2, iend) + 4;
|
||||
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
|
||||
hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);
|
||||
ip0 += rLength;
|
||||
ip1 = ip0 + 1;
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
|
||||
anchor = ip0;
|
||||
continue; /* faster when present (confirmed on gcc-8) ... (?) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* save reps for next block */
|
||||
rep[0] = offset_1 ? offset_1 : offsetSaved;
|
||||
rep[1] = offset_2 ? offset_2 : offsetSaved;
|
||||
|
||||
/* Return the last literals size */
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_compressBlock_fast(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize)
|
||||
{
|
||||
ZSTD_compressionParameters const* cParams = &ms->cParams;
|
||||
U32 const mls = cParams->minMatch;
|
||||
assert(ms->dictMatchState == NULL);
|
||||
switch(mls)
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7);
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize, U32 const mls)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32* const hashTable = ms->hashTable;
|
||||
@@ -64,46 +217,33 @@ size_t ZSTD_compressBlock_fast_generic(
|
||||
U32 offsetSaved = 0;
|
||||
|
||||
const ZSTD_matchState_t* const dms = ms->dictMatchState;
|
||||
const ZSTD_compressionParameters* const dictCParams =
|
||||
dictMode == ZSTD_dictMatchState ?
|
||||
&dms->cParams : NULL;
|
||||
const U32* const dictHashTable = dictMode == ZSTD_dictMatchState ?
|
||||
dms->hashTable : NULL;
|
||||
const U32 dictStartIndex = dictMode == ZSTD_dictMatchState ?
|
||||
dms->window.dictLimit : 0;
|
||||
const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
|
||||
dms->window.base : NULL;
|
||||
const BYTE* const dictStart = dictMode == ZSTD_dictMatchState ?
|
||||
dictBase + dictStartIndex : NULL;
|
||||
const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
|
||||
dms->window.nextSrc : NULL;
|
||||
const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
|
||||
prefixStartIndex - (U32)(dictEnd - dictBase) :
|
||||
0;
|
||||
const ZSTD_compressionParameters* const dictCParams = &dms->cParams ;
|
||||
const U32* const dictHashTable = dms->hashTable;
|
||||
const U32 dictStartIndex = dms->window.dictLimit;
|
||||
const BYTE* const dictBase = dms->window.base;
|
||||
const BYTE* const dictStart = dictBase + dictStartIndex;
|
||||
const BYTE* const dictEnd = dms->window.nextSrc;
|
||||
const U32 dictIndexDelta = prefixStartIndex - (U32)(dictEnd - dictBase);
|
||||
const U32 dictAndPrefixLength = (U32)(ip - prefixStart + dictEnd - dictStart);
|
||||
const U32 dictHLog = dictMode == ZSTD_dictMatchState ?
|
||||
dictCParams->hashLog : hlog;
|
||||
const U32 dictHLog = dictCParams->hashLog;
|
||||
|
||||
assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
|
||||
/* if a dictionary is still attached, it necessarily means that
|
||||
* it is within window size. So we just check it. */
|
||||
const U32 maxDistance = 1U << cParams->windowLog;
|
||||
const U32 endIndex = (U32)((size_t)(ip - base) + srcSize);
|
||||
assert(endIndex - prefixStartIndex <= maxDistance);
|
||||
(void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */
|
||||
|
||||
/* otherwise, we would get index underflow when translating a dict index
|
||||
* into a local index */
|
||||
assert(dictMode != ZSTD_dictMatchState
|
||||
|| prefixStartIndex >= (U32)(dictEnd - dictBase));
|
||||
/* ensure there will be no no underflow
|
||||
* when translating a dict index into a local index */
|
||||
assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
|
||||
|
||||
/* init */
|
||||
ip += (dictAndPrefixLength == 0);
|
||||
if (dictMode == ZSTD_noDict) {
|
||||
U32 const maxRep = (U32)(ip - prefixStart);
|
||||
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
|
||||
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
|
||||
}
|
||||
if (dictMode == ZSTD_dictMatchState) {
|
||||
/* dictMatchState repCode checks don't currently handle repCode == 0
|
||||
* disabling. */
|
||||
assert(offset_1 <= dictAndPrefixLength);
|
||||
assert(offset_2 <= dictAndPrefixLength);
|
||||
}
|
||||
/* dictMatchState repCode checks don't currently handle repCode == 0
|
||||
* disabling. */
|
||||
assert(offset_1 <= dictAndPrefixLength);
|
||||
assert(offset_2 <= dictAndPrefixLength);
|
||||
|
||||
/* Main Search Loop */
|
||||
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
|
||||
@@ -113,50 +253,37 @@ size_t ZSTD_compressBlock_fast_generic(
|
||||
U32 const matchIndex = hashTable[h];
|
||||
const BYTE* match = base + matchIndex;
|
||||
const U32 repIndex = current + 1 - offset_1;
|
||||
const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
|
||||
&& repIndex < prefixStartIndex) ?
|
||||
const BYTE* repMatch = (repIndex < prefixStartIndex) ?
|
||||
dictBase + (repIndex - dictIndexDelta) :
|
||||
base + repIndex;
|
||||
hashTable[h] = current; /* update hash table */
|
||||
|
||||
if ( (dictMode == ZSTD_dictMatchState)
|
||||
&& ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */
|
||||
if ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */
|
||||
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
||||
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
||||
} else if ( dictMode == ZSTD_noDict
|
||||
&& ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
|
||||
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
||||
} else if ( (matchIndex <= prefixStartIndex) ) {
|
||||
if (dictMode == ZSTD_dictMatchState) {
|
||||
size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls);
|
||||
U32 const dictMatchIndex = dictHashTable[dictHash];
|
||||
const BYTE* dictMatch = dictBase + dictMatchIndex;
|
||||
if (dictMatchIndex <= dictStartIndex ||
|
||||
MEM_read32(dictMatch) != MEM_read32(ip)) {
|
||||
assert(stepSize >= 1);
|
||||
ip += ((ip-anchor) >> kSearchStrength) + stepSize;
|
||||
continue;
|
||||
} else {
|
||||
/* found a dict match */
|
||||
U32 const offset = (U32)(current-dictMatchIndex-dictIndexDelta);
|
||||
mLength = ZSTD_count_2segments(ip+4, dictMatch+4, iend, dictEnd, prefixStart) + 4;
|
||||
while (((ip>anchor) & (dictMatch>dictStart))
|
||||
&& (ip[-1] == dictMatch[-1])) {
|
||||
ip--; dictMatch--; mLength++;
|
||||
} /* catch up */
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
}
|
||||
} else {
|
||||
size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls);
|
||||
U32 const dictMatchIndex = dictHashTable[dictHash];
|
||||
const BYTE* dictMatch = dictBase + dictMatchIndex;
|
||||
if (dictMatchIndex <= dictStartIndex ||
|
||||
MEM_read32(dictMatch) != MEM_read32(ip)) {
|
||||
assert(stepSize >= 1);
|
||||
ip += ((ip-anchor) >> kSearchStrength) + stepSize;
|
||||
continue;
|
||||
} else {
|
||||
/* found a dict match */
|
||||
U32 const offset = (U32)(current-dictMatchIndex-dictIndexDelta);
|
||||
mLength = ZSTD_count_2segments(ip+4, dictMatch+4, iend, dictEnd, prefixStart) + 4;
|
||||
while (((ip>anchor) & (dictMatch>dictStart))
|
||||
&& (ip[-1] == dictMatch[-1])) {
|
||||
ip--; dictMatch--; mLength++;
|
||||
} /* catch up */
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
}
|
||||
} else if (MEM_read32(match) != MEM_read32(ip)) {
|
||||
/* it's not a match, and we're not going to check the dictionary */
|
||||
@@ -171,7 +298,7 @@ size_t ZSTD_compressBlock_fast_generic(
|
||||
&& (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
}
|
||||
|
||||
/* match found */
|
||||
@@ -185,70 +312,34 @@ size_t ZSTD_compressBlock_fast_generic(
|
||||
hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base);
|
||||
|
||||
/* check immediate repcode */
|
||||
if (dictMode == ZSTD_dictMatchState) {
|
||||
while (ip <= ilimit) {
|
||||
U32 const current2 = (U32)(ip-base);
|
||||
U32 const repIndex2 = current2 - offset_2;
|
||||
const BYTE* repMatch2 = repIndex2 < prefixStartIndex ?
|
||||
dictBase - dictIndexDelta + repIndex2 :
|
||||
base + repIndex2;
|
||||
if ( ((U32)((prefixStartIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
|
||||
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
||||
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
||||
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
|
||||
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
|
||||
ip += repLength2;
|
||||
anchor = ip;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dictMode == ZSTD_noDict) {
|
||||
while ( (ip <= ilimit)
|
||||
&& ( (offset_2>0)
|
||||
& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
|
||||
/* store sequence */
|
||||
size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
||||
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
|
||||
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = (U32)(ip-base);
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
|
||||
ip += rLength;
|
||||
while (ip <= ilimit) {
|
||||
U32 const current2 = (U32)(ip-base);
|
||||
U32 const repIndex2 = current2 - offset_2;
|
||||
const BYTE* repMatch2 = repIndex2 < prefixStartIndex ?
|
||||
dictBase - dictIndexDelta + repIndex2 :
|
||||
base + repIndex2;
|
||||
if ( ((U32)((prefixStartIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
|
||||
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
||||
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
||||
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
|
||||
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
|
||||
ip += repLength2;
|
||||
anchor = ip;
|
||||
continue; /* faster when present ... (?) */
|
||||
} } } }
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* save reps for next block */
|
||||
rep[0] = offset_1 ? offset_1 : offsetSaved;
|
||||
rep[1] = offset_2 ? offset_2 : offsetSaved;
|
||||
|
||||
/* Return the last literals size */
|
||||
return iend - anchor;
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_compressBlock_fast(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize)
|
||||
{
|
||||
ZSTD_compressionParameters const* cParams = &ms->cParams;
|
||||
U32 const mls = cParams->minMatch;
|
||||
assert(ms->dictMatchState == NULL);
|
||||
switch(mls)
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_noDict);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_noDict);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_noDict);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_noDict);
|
||||
}
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock_fast_dictMatchState(
|
||||
@@ -262,13 +353,13 @@ size_t ZSTD_compressBlock_fast_dictMatchState(
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 4);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 5);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 6);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 7);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,15 +378,24 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
const BYTE* ip = istart;
|
||||
const BYTE* anchor = istart;
|
||||
const U32 dictStartIndex = ms->window.lowLimit;
|
||||
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
||||
const U32 maxDistance = 1U << cParams->windowLog;
|
||||
const U32 validLow = ms->window.lowLimit;
|
||||
const U32 lowLimit = (endIndex - validLow > maxDistance) ? endIndex - maxDistance : validLow;
|
||||
const U32 dictStartIndex = lowLimit;
|
||||
const BYTE* const dictStart = dictBase + dictStartIndex;
|
||||
const U32 prefixStartIndex = ms->window.dictLimit;
|
||||
const U32 dictLimit = ms->window.dictLimit;
|
||||
const U32 prefixStartIndex = dictLimit < lowLimit ? lowLimit : dictLimit;
|
||||
const BYTE* const prefixStart = base + prefixStartIndex;
|
||||
const BYTE* const dictEnd = dictBase + prefixStartIndex;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* const ilimit = iend - 8;
|
||||
U32 offset_1=rep[0], offset_2=rep[1];
|
||||
|
||||
/* switch to "regular" variant if extDict is invalidated due to maxDistance */
|
||||
if (prefixStartIndex == dictStartIndex)
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, mls);
|
||||
|
||||
/* Search Loop */
|
||||
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
|
||||
const size_t h = ZSTD_hashPtr(ip, hlog, mls);
|
||||
@@ -315,7 +415,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
||||
} else {
|
||||
if ( (matchIndex < dictStartIndex) ||
|
||||
(MEM_read32(match) != MEM_read32(ip)) ) {
|
||||
@@ -331,7 +431,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
offset = current - matchIndex;
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
} }
|
||||
|
||||
/* found a match : store it */
|
||||
@@ -366,7 +466,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
rep[1] = offset_2;
|
||||
|
||||
/* Return the last literals size */
|
||||
return iend - anchor;
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -83,7 +83,10 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms,
|
||||
U32* largerPtr = smallerPtr + 1;
|
||||
U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */
|
||||
U32 dummy32; /* to be nullified at the end */
|
||||
U32 const windowLow = ms->window.lowLimit;
|
||||
U32 const windowValid = ms->window.lowLimit;
|
||||
U32 const maxDistance = 1U << cParams->windowLog;
|
||||
U32 const windowLow = (current - windowValid > maxDistance) ? current - maxDistance : windowValid;
|
||||
|
||||
|
||||
DEBUGLOG(8, "ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)",
|
||||
current, dictLimit, windowLow);
|
||||
@@ -239,7 +242,9 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
|
||||
|
||||
const BYTE* const base = ms->window.base;
|
||||
U32 const current = (U32)(ip-base);
|
||||
U32 const windowLow = ms->window.lowLimit;
|
||||
U32 const maxDistance = 1U << cParams->windowLog;
|
||||
U32 const windowValid = ms->window.lowLimit;
|
||||
U32 const windowLow = (current - windowValid > maxDistance) ? current - maxDistance : windowValid;
|
||||
|
||||
U32* const bt = ms->chainTable;
|
||||
U32 const btLog = cParams->chainLog - 1;
|
||||
@@ -490,8 +495,10 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
const U32 dictLimit = ms->window.dictLimit;
|
||||
const BYTE* const prefixStart = base + dictLimit;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const U32 lowLimit = ms->window.lowLimit;
|
||||
const U32 current = (U32)(ip-base);
|
||||
const U32 maxDistance = 1U << cParams->windowLog;
|
||||
const U32 lowValid = ms->window.lowLimit;
|
||||
const U32 lowLimit = (current - lowValid > maxDistance) ? current - maxDistance : lowValid;
|
||||
const U32 minChain = current > chainSize ? current - chainSize : 0;
|
||||
U32 nbAttempts = 1U << cParams->searchLog;
|
||||
size_t ml=4-1;
|
||||
@@ -653,7 +660,6 @@ size_t ZSTD_compressBlock_lazy_generic(
|
||||
|
||||
/* init */
|
||||
ip += (dictAndPrefixLength == 0);
|
||||
ms->nextToUpdate3 = ms->nextToUpdate;
|
||||
if (dictMode == ZSTD_noDict) {
|
||||
U32 const maxRep = (U32)(ip - prefixLowest);
|
||||
if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
|
||||
@@ -933,7 +939,6 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
|
||||
U32 offset_1 = rep[0], offset_2 = rep[1];
|
||||
|
||||
/* init */
|
||||
ms->nextToUpdate3 = ms->nextToUpdate;
|
||||
ip += (ip == prefixStart);
|
||||
|
||||
/* Match Loop */
|
||||
|
||||
@@ -19,7 +19,7 @@ extern "C" {
|
||||
|
||||
U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
|
||||
|
||||
void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). pre-emptively increase value of ZSTD_DUBT_UNSORTED_MARK */
|
||||
void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */
|
||||
|
||||
size_t ZSTD_compressBlock_btlazy2(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
|
||||
@@ -429,7 +429,7 @@ size_t ZSTD_ldm_generateSequences(
|
||||
*/
|
||||
assert(ldmState->window.nextSrc >= (BYTE const*)src + srcSize);
|
||||
/* The input could be very large (in zstdmt), so it must be broken up into
|
||||
* chunks to enforce the maximmum distance and handle overflow correction.
|
||||
* chunks to enforce the maximum distance and handle overflow correction.
|
||||
*/
|
||||
assert(sequences->pos <= sequences->size);
|
||||
assert(sequences->size <= sequences->capacity);
|
||||
@@ -447,7 +447,7 @@ size_t ZSTD_ldm_generateSequences(
|
||||
if (ZSTD_window_needOverflowCorrection(ldmState->window, chunkEnd)) {
|
||||
U32 const ldmHSize = 1U << params->hashLog;
|
||||
U32 const correction = ZSTD_window_correctOverflow(
|
||||
&ldmState->window, /* cycleLog */ 0, maxDist, src);
|
||||
&ldmState->window, /* cycleLog */ 0, maxDist, chunkStart);
|
||||
ZSTD_ldm_reduceTable(ldmState->hashTable, ldmHSize, correction);
|
||||
}
|
||||
/* 2. We enforce the maximum offset allowed.
|
||||
|
||||
+72
-43
@@ -64,9 +64,15 @@ MEM_STATIC double ZSTD_fCost(U32 price)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ZSTD_compressedLiterals(optState_t const* const optPtr)
|
||||
{
|
||||
return optPtr->literalCompressionMode != ZSTD_lcm_uncompressed;
|
||||
}
|
||||
|
||||
static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
|
||||
{
|
||||
optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
|
||||
if (ZSTD_compressedLiterals(optPtr))
|
||||
optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
|
||||
optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);
|
||||
optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);
|
||||
optPtr->offCodeSumBasePrice = WEIGHT(optPtr->offCodeSum, optLevel);
|
||||
@@ -99,6 +105,7 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
||||
const BYTE* const src, size_t const srcSize,
|
||||
int const optLevel)
|
||||
{
|
||||
int const compressedLiterals = ZSTD_compressedLiterals(optPtr);
|
||||
DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize);
|
||||
optPtr->priceType = zop_dynamic;
|
||||
|
||||
@@ -113,9 +120,10 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
||||
/* huffman table presumed generated by dictionary */
|
||||
optPtr->priceType = zop_dynamic;
|
||||
|
||||
assert(optPtr->litFreq != NULL);
|
||||
optPtr->litSum = 0;
|
||||
{ unsigned lit;
|
||||
if (compressedLiterals) {
|
||||
unsigned lit;
|
||||
assert(optPtr->litFreq != NULL);
|
||||
optPtr->litSum = 0;
|
||||
for (lit=0; lit<=MaxLit; lit++) {
|
||||
U32 const scaleLog = 11; /* scale to 2K */
|
||||
U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit);
|
||||
@@ -163,10 +171,11 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
||||
} else { /* not a dictionary */
|
||||
|
||||
assert(optPtr->litFreq != NULL);
|
||||
{ unsigned lit = MaxLit;
|
||||
if (compressedLiterals) {
|
||||
unsigned lit = MaxLit;
|
||||
HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
|
||||
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
||||
}
|
||||
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
||||
|
||||
{ unsigned ll;
|
||||
for (ll=0; ll<=MaxLL; ll++)
|
||||
@@ -190,7 +199,8 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
||||
|
||||
} else { /* new block : re-use previous statistics, scaled down */
|
||||
|
||||
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
||||
if (compressedLiterals)
|
||||
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
||||
optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0);
|
||||
optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0);
|
||||
optPtr->offCodeSum = ZSTD_downscaleStat(optPtr->offCodeFreq, MaxOff, 0);
|
||||
@@ -207,6 +217,10 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
|
||||
int optLevel)
|
||||
{
|
||||
if (litLength == 0) return 0;
|
||||
|
||||
if (!ZSTD_compressedLiterals(optPtr))
|
||||
return (litLength << 3) * BITCOST_MULTIPLIER; /* Uncompressed - 8 bytes per literal. */
|
||||
|
||||
if (optPtr->priceType == zop_predef)
|
||||
return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */
|
||||
|
||||
@@ -241,13 +255,13 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
|
||||
* to provide a cost which is directly comparable to a match ending at same position */
|
||||
static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel)
|
||||
{
|
||||
if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel);
|
||||
if (optPtr->priceType >= zop_predef) return (int)WEIGHT(litLength, optLevel);
|
||||
|
||||
/* dynamic statistics */
|
||||
{ U32 const llCode = ZSTD_LLcode(litLength);
|
||||
int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER)
|
||||
+ WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
|
||||
- WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
|
||||
int const contribution = (int)(LL_bits[llCode] * BITCOST_MULTIPLIER)
|
||||
+ (int)WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
|
||||
- (int)WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
|
||||
#if 1
|
||||
return contribution;
|
||||
#else
|
||||
@@ -264,7 +278,7 @@ static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLe
|
||||
const optState_t* const optPtr,
|
||||
int optLevel)
|
||||
{
|
||||
int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
|
||||
int const contribution = (int)ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
|
||||
+ ZSTD_litLengthContribution(litLength, optPtr, optLevel);
|
||||
return contribution;
|
||||
}
|
||||
@@ -310,7 +324,8 @@ static void ZSTD_updateStats(optState_t* const optPtr,
|
||||
U32 offsetCode, U32 matchLength)
|
||||
{
|
||||
/* literals */
|
||||
{ U32 u;
|
||||
if (ZSTD_compressedLiterals(optPtr)) {
|
||||
U32 u;
|
||||
for (u=0; u < litLength; u++)
|
||||
optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
|
||||
optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
|
||||
@@ -357,13 +372,15 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
|
||||
|
||||
/* Update hashTable3 up to ip (excluded)
|
||||
Assumption : always within prefix (i.e. not within extDict) */
|
||||
static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE* const ip)
|
||||
static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
const BYTE* const ip)
|
||||
{
|
||||
U32* const hashTable3 = ms->hashTable3;
|
||||
U32 const hashLog3 = ms->hashLog3;
|
||||
const BYTE* const base = ms->window.base;
|
||||
U32 idx = ms->nextToUpdate3;
|
||||
U32 const target = ms->nextToUpdate3 = (U32)(ip - base);
|
||||
U32 idx = *nextToUpdate3;
|
||||
U32 const target = (U32)(ip - base);
|
||||
size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);
|
||||
assert(hashLog3 > 0);
|
||||
|
||||
@@ -372,6 +389,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
|
||||
idx++;
|
||||
}
|
||||
|
||||
*nextToUpdate3 = target;
|
||||
return hashTable3[hash3];
|
||||
}
|
||||
|
||||
@@ -488,9 +506,11 @@ static U32 ZSTD_insertBt1(
|
||||
} }
|
||||
|
||||
*smallerPtr = *largerPtr = 0;
|
||||
if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
|
||||
assert(matchEndIdx > current + 8);
|
||||
return matchEndIdx - (current + 8);
|
||||
{ U32 positions = 0;
|
||||
if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384)); /* speed optimization */
|
||||
assert(matchEndIdx > current + 8);
|
||||
return MAX(positions, matchEndIdx - (current + 8));
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
@@ -505,8 +525,13 @@ void ZSTD_updateTree_internal(
|
||||
DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
|
||||
idx, target, dictMode);
|
||||
|
||||
while(idx < target)
|
||||
idx += ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
|
||||
while(idx < target) {
|
||||
U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
|
||||
assert(idx < (U32)(idx + forward));
|
||||
idx += forward;
|
||||
}
|
||||
assert((size_t)(ip - base) <= (size_t)(U32)(-1));
|
||||
assert((size_t)(iend - base) <= (size_t)(U32)(-1));
|
||||
ms->nextToUpdate = target;
|
||||
}
|
||||
|
||||
@@ -516,16 +541,18 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
U32 ZSTD_insertBtAndGetAllMatches (
|
||||
ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
|
||||
ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
|
||||
U32 rep[ZSTD_REP_NUM],
|
||||
const U32 rep[ZSTD_REP_NUM],
|
||||
U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
|
||||
ZSTD_match_t* matches,
|
||||
const U32 lengthToBeat,
|
||||
U32 const mls /* template */)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
|
||||
U32 const maxDistance = 1U << cParams->windowLog;
|
||||
const BYTE* const base = ms->window.base;
|
||||
U32 const current = (U32)(ip-base);
|
||||
U32 const hashLog = cParams->hashLog;
|
||||
@@ -541,8 +568,9 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
U32 const dictLimit = ms->window.dictLimit;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const BYTE* const prefixStart = base + dictLimit;
|
||||
U32 const btLow = btMask >= current ? 0 : current - btMask;
|
||||
U32 const windowLow = ms->window.lowLimit;
|
||||
U32 const btLow = (btMask >= current) ? 0 : current - btMask;
|
||||
U32 const windowValid = ms->window.lowLimit;
|
||||
U32 const windowLow = ((current - windowValid) > maxDistance) ? current - maxDistance : windowValid;
|
||||
U32 const matchLow = windowLow ? windowLow : 1;
|
||||
U32* smallerPtr = bt + 2*(current&btMask);
|
||||
U32* largerPtr = bt + 2*(current&btMask) + 1;
|
||||
@@ -612,7 +640,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
|
||||
/* HC3 match finder */
|
||||
if ((mls == 3) /*static*/ && (bestLength < mls)) {
|
||||
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
|
||||
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);
|
||||
if ((matchIndex3 >= matchLow)
|
||||
& (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
|
||||
size_t mlen;
|
||||
@@ -638,9 +666,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
(ip+mlen == iLimit) ) { /* best possible length */
|
||||
ms->nextToUpdate = current+1; /* skip insertion */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} } }
|
||||
/* no dictMatchState lookup: dicts don't have a populated HC3 table */
|
||||
}
|
||||
|
||||
@@ -745,10 +771,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
||||
ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
|
||||
ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
|
||||
U32 rep[ZSTD_REP_NUM], U32 const ll0,
|
||||
ZSTD_match_t* matches, U32 const lengthToBeat)
|
||||
const U32 rep[ZSTD_REP_NUM],
|
||||
U32 const ll0,
|
||||
U32 const lengthToBeat)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32 const matchLengthSearch = cParams->minMatch;
|
||||
@@ -757,12 +786,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
||||
ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
|
||||
switch(matchLengthSearch)
|
||||
{
|
||||
case 3 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 3);
|
||||
case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3);
|
||||
default :
|
||||
case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4);
|
||||
case 5 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 5);
|
||||
case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4);
|
||||
case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 6);
|
||||
case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,6 +867,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
|
||||
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
|
||||
U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
|
||||
U32 nextToUpdate3 = ms->nextToUpdate;
|
||||
|
||||
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
|
||||
ZSTD_match_t* const matches = optStatePtr->matchTable;
|
||||
@@ -847,7 +877,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
|
||||
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
|
||||
assert(optLevel <= 2);
|
||||
ms->nextToUpdate3 = ms->nextToUpdate;
|
||||
ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
|
||||
ip += (ip==prefixStart);
|
||||
|
||||
@@ -858,7 +887,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
/* find first match */
|
||||
{ U32 const litlen = (U32)(ip - anchor);
|
||||
U32 const ll0 = !litlen;
|
||||
U32 const nbMatches = ZSTD_BtGetAllMatches(ms, ip, iend, dictMode, rep, ll0, matches, minMatch);
|
||||
U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
|
||||
if (!nbMatches) { ip++; continue; }
|
||||
|
||||
/* initialize opt[0] */
|
||||
@@ -870,7 +899,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
/* large match -> immediate encoding */
|
||||
{ U32 const maxML = matches[nbMatches-1].len;
|
||||
U32 const maxOffset = matches[nbMatches-1].off;
|
||||
DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new serie",
|
||||
DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
|
||||
nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
|
||||
|
||||
if (maxML > sufficient_len) {
|
||||
@@ -955,7 +984,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
|
||||
U32 const previousPrice = opt[cur].price;
|
||||
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
|
||||
U32 const nbMatches = ZSTD_BtGetAllMatches(ms, inr, iend, dictMode, opt[cur].rep, ll0, matches, minMatch);
|
||||
U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
|
||||
U32 matchNb;
|
||||
if (!nbMatches) {
|
||||
DEBUGLOG(7, "rPos:%u : no match found", cur);
|
||||
@@ -1079,7 +1108,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
||||
} /* while (ip < ilimit) */
|
||||
|
||||
/* Return the last literals size */
|
||||
return iend - anchor;
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
|
||||
@@ -1108,7 +1137,8 @@ static U32 ZSTD_upscaleStat(unsigned* table, U32 lastEltIndex, int bonus)
|
||||
/* used in 2-pass strategy */
|
||||
MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
|
||||
{
|
||||
optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
|
||||
if (ZSTD_compressedLiterals(optPtr))
|
||||
optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
|
||||
optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0);
|
||||
optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0);
|
||||
optPtr->offCodeSum = ZSTD_upscaleStat(optPtr->offCodeFreq, MaxOff, 0);
|
||||
@@ -1117,7 +1147,7 @@ MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
|
||||
/* ZSTD_initStats_ultra():
|
||||
* make a first compression pass, just to seed stats with more accurate starting values.
|
||||
* only works on first block, with no dictionary and no ldm.
|
||||
* this function cannot error, hence its constract must be respected.
|
||||
* this function cannot error, hence its contract must be respected.
|
||||
*/
|
||||
static void
|
||||
ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||
@@ -1142,7 +1172,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||
ms->window.dictLimit += (U32)srcSize;
|
||||
ms->window.lowLimit = ms->window.dictLimit;
|
||||
ms->nextToUpdate = ms->window.dictLimit;
|
||||
ms->nextToUpdate3 = ms->window.dictLimit;
|
||||
|
||||
/* re-inforce weight of collected statistics */
|
||||
ZSTD_upscaleStats(&ms->opt);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
/* ====== Dependencies ====== */
|
||||
#include <string.h> /* memcpy, memset */
|
||||
#include <limits.h> /* INT_MAX, UINT_MAX */
|
||||
#include "mem.h" /* MEM_STATIC */
|
||||
#include "pool.h" /* threadpool */
|
||||
#include "threading.h" /* mutex */
|
||||
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
||||
@@ -456,7 +457,7 @@ typedef struct {
|
||||
* Must be acquired after the main mutex when acquiring both.
|
||||
*/
|
||||
ZSTD_pthread_mutex_t ldmWindowMutex;
|
||||
ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is udpated */
|
||||
ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is updated */
|
||||
ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */
|
||||
} serialState_t;
|
||||
|
||||
@@ -647,7 +648,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
||||
buffer_t dstBuff = job->dstBuff;
|
||||
size_t lastCBlockSize = 0;
|
||||
|
||||
/* ressources */
|
||||
/* resources */
|
||||
if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation));
|
||||
if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */
|
||||
dstBuff = ZSTDMT_getBuffer(job->bufPool);
|
||||
@@ -672,7 +673,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
||||
if (ZSTD_isError(initError)) JOB_ERROR(initError);
|
||||
} else { /* srcStart points at reloaded section */
|
||||
U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
|
||||
{ size_t const forceWindowError = ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
|
||||
{ size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
|
||||
if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
|
||||
}
|
||||
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
|
||||
@@ -864,14 +865,10 @@ static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {
|
||||
* Internal use only */
|
||||
size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
|
||||
{
|
||||
if (nbWorkers > ZSTDMT_NBWORKERS_MAX) nbWorkers = ZSTDMT_NBWORKERS_MAX;
|
||||
params->nbWorkers = nbWorkers;
|
||||
params->overlapLog = ZSTDMT_OVERLAPLOG_DEFAULT;
|
||||
params->jobSize = 0;
|
||||
return nbWorkers;
|
||||
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);
|
||||
}
|
||||
|
||||
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
|
||||
MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem)
|
||||
{
|
||||
ZSTDMT_CCtx* mtctx;
|
||||
U32 nbJobs = nbWorkers + 2;
|
||||
@@ -906,6 +903,17 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
|
||||
return mtctx;
|
||||
}
|
||||
|
||||
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
|
||||
{
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem);
|
||||
#else
|
||||
(void)nbWorkers;
|
||||
(void)cMem;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
|
||||
{
|
||||
return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
|
||||
@@ -986,26 +994,13 @@ ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
|
||||
{
|
||||
case ZSTDMT_p_jobSize :
|
||||
DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value);
|
||||
if ( value != 0 /* default */
|
||||
&& value < ZSTDMT_JOBSIZE_MIN)
|
||||
value = ZSTDMT_JOBSIZE_MIN;
|
||||
assert(value >= 0);
|
||||
if (value > ZSTDMT_JOBSIZE_MAX) value = ZSTDMT_JOBSIZE_MAX;
|
||||
params->jobSize = value;
|
||||
return value;
|
||||
|
||||
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value);
|
||||
case ZSTDMT_p_overlapLog :
|
||||
DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value);
|
||||
if (value < ZSTD_OVERLAPLOG_MIN) value = ZSTD_OVERLAPLOG_MIN;
|
||||
if (value > ZSTD_OVERLAPLOG_MAX) value = ZSTD_OVERLAPLOG_MAX;
|
||||
params->overlapLog = value;
|
||||
return value;
|
||||
|
||||
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value);
|
||||
case ZSTDMT_p_rsyncable :
|
||||
value = (value != 0);
|
||||
params->rsyncable = value;
|
||||
return value;
|
||||
|
||||
DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value);
|
||||
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value);
|
||||
default :
|
||||
return ERROR(parameter_unsupported);
|
||||
}
|
||||
@@ -1021,32 +1016,29 @@ size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter,
|
||||
{
|
||||
switch (parameter) {
|
||||
case ZSTDMT_p_jobSize:
|
||||
assert(mtctx->params.jobSize <= INT_MAX);
|
||||
*value = (int)(mtctx->params.jobSize);
|
||||
break;
|
||||
return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value);
|
||||
case ZSTDMT_p_overlapLog:
|
||||
*value = mtctx->params.overlapLog;
|
||||
break;
|
||||
return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value);
|
||||
case ZSTDMT_p_rsyncable:
|
||||
*value = mtctx->params.rsyncable;
|
||||
break;
|
||||
return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value);
|
||||
default:
|
||||
return ERROR(parameter_unsupported);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets parameters relevant to the compression job,
|
||||
* initializing others to default values. */
|
||||
static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
|
||||
{
|
||||
ZSTD_CCtx_params jobParams;
|
||||
memset(&jobParams, 0, sizeof(jobParams));
|
||||
|
||||
jobParams.cParams = params.cParams;
|
||||
jobParams.fParams = params.fParams;
|
||||
jobParams.compressionLevel = params.compressionLevel;
|
||||
|
||||
ZSTD_CCtx_params jobParams = params;
|
||||
/* Clear parameters related to multithreading */
|
||||
jobParams.forceWindow = 0;
|
||||
jobParams.nbWorkers = 0;
|
||||
jobParams.jobSize = 0;
|
||||
jobParams.overlapLog = 0;
|
||||
jobParams.rsyncable = 0;
|
||||
memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t));
|
||||
memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem));
|
||||
return jobParams;
|
||||
}
|
||||
|
||||
@@ -1056,7 +1048,7 @@ static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
|
||||
static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
|
||||
{
|
||||
if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);
|
||||
CHECK_F( ZSTDMT_expandJobsTable(mtctx, nbWorkers) );
|
||||
FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) );
|
||||
mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers);
|
||||
if (mtctx->bufPool == NULL) return ERROR(memory_allocation);
|
||||
mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);
|
||||
@@ -1137,9 +1129,14 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
|
||||
size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;
|
||||
size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;
|
||||
assert(flushed <= produced);
|
||||
assert(jobPtr->consumed <= jobPtr->src.size);
|
||||
toFlush = produced - flushed;
|
||||
if (toFlush==0 && (jobPtr->consumed >= jobPtr->src.size)) {
|
||||
/* doneJobID is not-fully-flushed, but toFlush==0 : doneJobID should be compressing some more data */
|
||||
/* if toFlush==0, nothing is available to flush.
|
||||
* However, jobID is expected to still be active:
|
||||
* if jobID was already completed and fully flushed,
|
||||
* ZSTDMT_flushProduced() should have already moved onto next job.
|
||||
* Therefore, some input has not yet been consumed. */
|
||||
if (toFlush==0) {
|
||||
assert(jobPtr->consumed < jobPtr->src.size);
|
||||
}
|
||||
}
|
||||
@@ -1156,12 +1153,16 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
|
||||
|
||||
static unsigned ZSTDMT_computeTargetJobLog(ZSTD_CCtx_params const params)
|
||||
{
|
||||
if (params.ldmParams.enableLdm)
|
||||
unsigned jobLog;
|
||||
if (params.ldmParams.enableLdm) {
|
||||
/* In Long Range Mode, the windowLog is typically oversized.
|
||||
* In which case, it's preferable to determine the jobSize
|
||||
* based on chainLog instead. */
|
||||
return MAX(21, params.cParams.chainLog + 4);
|
||||
return MAX(20, params.cParams.windowLog + 2);
|
||||
jobLog = MAX(21, params.cParams.chainLog + 4);
|
||||
} else {
|
||||
jobLog = MAX(20, params.cParams.windowLog + 2);
|
||||
}
|
||||
return MIN(jobLog, (unsigned)ZSTDMT_JOBLOG_MAX);
|
||||
}
|
||||
|
||||
static int ZSTDMT_overlapLog_default(ZSTD_strategy strat)
|
||||
@@ -1205,7 +1206,7 @@ static size_t ZSTDMT_computeOverlapSize(ZSTD_CCtx_params const params)
|
||||
ovLog = MIN(params.cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2)
|
||||
- overlapRLog;
|
||||
}
|
||||
assert(0 <= ovLog && ovLog <= 30);
|
||||
assert(0 <= ovLog && ovLog <= ZSTD_WINDOWLOG_MAX);
|
||||
DEBUGLOG(4, "overlapLog : %i", params.overlapLog);
|
||||
DEBUGLOG(4, "overlap size : %i", 1 << ovLog);
|
||||
return (ovLog==0) ? 0 : (size_t)1 << ovLog;
|
||||
@@ -1263,7 +1264,7 @@ static size_t ZSTDMT_compress_advanced_internal(
|
||||
if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize))
|
||||
return ERROR(memory_allocation);
|
||||
|
||||
CHECK_F( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */
|
||||
FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */
|
||||
|
||||
{ unsigned u;
|
||||
for (u=0; u<nbJobs; u++) {
|
||||
@@ -1396,10 +1397,10 @@ size_t ZSTDMT_initCStream_internal(
|
||||
|
||||
/* init */
|
||||
if (params.nbWorkers != mtctx->params.nbWorkers)
|
||||
CHECK_F( ZSTDMT_resize(mtctx, params.nbWorkers) );
|
||||
FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) );
|
||||
|
||||
if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
|
||||
if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX;
|
||||
if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX;
|
||||
|
||||
mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */
|
||||
if (mtctx->singleBlockingThread) {
|
||||
@@ -1440,6 +1441,8 @@ size_t ZSTDMT_initCStream_internal(
|
||||
if (mtctx->targetSectionSize == 0) {
|
||||
mtctx->targetSectionSize = 1ULL << ZSTDMT_computeTargetJobLog(params);
|
||||
}
|
||||
assert(mtctx->targetSectionSize <= (size_t)ZSTDMT_JOBSIZE_MAX);
|
||||
|
||||
if (params.rsyncable) {
|
||||
/* Aim for the targetsectionSize as the average job size. */
|
||||
U32 const jobSizeMB = (U32)(mtctx->targetSectionSize >> 20);
|
||||
@@ -1547,7 +1550,7 @@ size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) {
|
||||
/* ZSTDMT_writeLastEmptyBlock()
|
||||
* Write a single empty block with an end-of-frame to finish a frame.
|
||||
* Job must be created from streaming variant.
|
||||
* This function is always successfull if expected conditions are fulfilled.
|
||||
* This function is always successful if expected conditions are fulfilled.
|
||||
*/
|
||||
static void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job)
|
||||
{
|
||||
@@ -1987,7 +1990,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
||||
assert(input->pos <= input->size);
|
||||
|
||||
if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
|
||||
return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp);
|
||||
return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp);
|
||||
}
|
||||
|
||||
if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
|
||||
@@ -2051,7 +2054,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
||||
|| ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */
|
||||
size_t const jobSize = mtctx->inBuff.filled;
|
||||
assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);
|
||||
CHECK_F( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
|
||||
FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
|
||||
}
|
||||
|
||||
/* check for potential compressed data ready to be flushed */
|
||||
@@ -2065,7 +2068,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
||||
|
||||
size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
||||
{
|
||||
CHECK_F( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
|
||||
FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
|
||||
|
||||
/* recommended next input size : fill current input buffer */
|
||||
return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
|
||||
@@ -2082,7 +2085,7 @@ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* ou
|
||||
|| ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
|
||||
DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
|
||||
(U32)srcSize, (U32)endFrame);
|
||||
CHECK_F( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
|
||||
FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
|
||||
}
|
||||
|
||||
/* check if there is any data available to flush */
|
||||
|
||||
@@ -17,10 +17,25 @@
|
||||
|
||||
|
||||
/* Note : This is an internal API.
|
||||
* Some methods are still exposed (ZSTDLIB_API),
|
||||
* These APIs used to be exposed with ZSTDLIB_API,
|
||||
* because it used to be the only way to invoke MT compression.
|
||||
* Now, it's recommended to use ZSTD_compress_generic() instead.
|
||||
* These methods will stop being exposed in a future version */
|
||||
* Now, it's recommended to use ZSTD_compress2 and ZSTD_compressStream2()
|
||||
* instead.
|
||||
*
|
||||
* If you depend on these APIs and can't switch, then define
|
||||
* ZSTD_LEGACY_MULTITHREADED_API when making the dynamic library.
|
||||
* However, we may completely remove these functions in a future
|
||||
* release, so please switch soon.
|
||||
*
|
||||
* This API requires ZSTD_MULTITHREAD to be defined during compilation,
|
||||
* otherwise ZSTDMT_createCCtx*() will fail.
|
||||
*/
|
||||
|
||||
#ifdef ZSTD_LEGACY_MULTITHREADED_API
|
||||
# define ZSTDMT_API ZSTDLIB_API
|
||||
#else
|
||||
# define ZSTDMT_API
|
||||
#endif
|
||||
|
||||
/* === Dependencies === */
|
||||
#include <stddef.h> /* size_t */
|
||||
@@ -35,22 +50,25 @@
|
||||
#ifndef ZSTDMT_JOBSIZE_MIN
|
||||
# define ZSTDMT_JOBSIZE_MIN (1 MB)
|
||||
#endif
|
||||
#define ZSTDMT_JOBLOG_MAX (MEM_32bits() ? 29 : 30)
|
||||
#define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB))
|
||||
|
||||
|
||||
/* === Memory management === */
|
||||
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
|
||||
ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
|
||||
ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
|
||||
/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
|
||||
ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
|
||||
/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
|
||||
ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
|
||||
ZSTD_customMem cMem);
|
||||
ZSTDLIB_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
|
||||
ZSTDMT_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
|
||||
ZSTDMT_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
|
||||
|
||||
|
||||
/* === Simple one-pass compression function === */
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
ZSTDMT_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
int compressionLevel);
|
||||
@@ -59,31 +77,31 @@ ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
|
||||
/* === Streaming functions === */
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
|
||||
ZSTDMT_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
|
||||
ZSTDMT_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
|
||||
ZSTDLIB_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
ZSTDMT_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
|
||||
ZSTDMT_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
||||
ZSTDLIB_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
||||
ZSTDMT_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
||||
ZSTDMT_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
||||
|
||||
|
||||
/* === Advanced functions and parameters === */
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_parameters params,
|
||||
int overlapLog);
|
||||
ZSTDMT_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_parameters params,
|
||||
int overlapLog);
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
|
||||
ZSTDMT_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
|
||||
const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */
|
||||
ZSTD_parameters params,
|
||||
unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
||||
ZSTDMT_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_frameParameters fparams,
|
||||
unsigned long long pledgedSrcSize); /* note : zero means empty */
|
||||
@@ -92,7 +110,7 @@ ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
||||
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
|
||||
typedef enum {
|
||||
ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
|
||||
ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compressionr ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
|
||||
ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compression ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
|
||||
ZSTDMT_p_rsyncable /* Enables rsyncable mode. */
|
||||
} ZSTDMT_parameter;
|
||||
|
||||
@@ -101,12 +119,12 @@ typedef enum {
|
||||
* The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__
|
||||
* Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
|
||||
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
||||
ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
|
||||
ZSTDMT_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
|
||||
|
||||
/* ZSTDMT_getMTCtxParameter() :
|
||||
* Query the ZSTDMT_CCtx for a parameter value.
|
||||
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
||||
ZSTDLIB_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
|
||||
ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
|
||||
|
||||
|
||||
/*! ZSTDMT_compressStream_generic() :
|
||||
@@ -116,7 +134,7 @@ ZSTDLIB_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter
|
||||
* 0 if fully flushed
|
||||
* or an error code
|
||||
* note : needs to be init using any ZSTD_initCStream*() variant */
|
||||
ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
||||
ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective endOp);
|
||||
|
||||
@@ -105,9 +105,9 @@ ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
|
||||
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
|
||||
|
||||
/* load entropy tables */
|
||||
CHECK_E( ZSTD_loadDEntropy(&ddict->entropy,
|
||||
ddict->dictContent, ddict->dictSize),
|
||||
dictionary_corrupted );
|
||||
RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
|
||||
&ddict->entropy, ddict->dictContent, ddict->dictSize)),
|
||||
dictionary_corrupted);
|
||||
ddict->entropyPresent = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -133,7 +133,7 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
|
||||
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
||||
|
||||
/* parse dictionary content */
|
||||
CHECK_F( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
|
||||
FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+293
-197
@@ -106,6 +106,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
||||
dctx->ddictLocal = NULL;
|
||||
dctx->dictEnd = NULL;
|
||||
dctx->ddictIsCold = 0;
|
||||
dctx->dictUses = ZSTD_dont_use;
|
||||
dctx->inBuff = NULL;
|
||||
dctx->inBuffSize = 0;
|
||||
dctx->outBuffSize = 0;
|
||||
@@ -147,13 +148,20 @@ ZSTD_DCtx* ZSTD_createDCtx(void)
|
||||
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
|
||||
}
|
||||
|
||||
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
|
||||
{
|
||||
ZSTD_freeDDict(dctx->ddictLocal);
|
||||
dctx->ddictLocal = NULL;
|
||||
dctx->ddict = NULL;
|
||||
dctx->dictUses = ZSTD_dont_use;
|
||||
}
|
||||
|
||||
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
||||
{
|
||||
if (dctx==NULL) return 0; /* support free on NULL */
|
||||
if (dctx->staticSize) return ERROR(memory_allocation); /* not compatible with static DCtx */
|
||||
RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
|
||||
{ ZSTD_customMem const cMem = dctx->customMem;
|
||||
ZSTD_freeDDict(dctx->ddictLocal);
|
||||
dctx->ddictLocal = NULL;
|
||||
ZSTD_clearDict(dctx);
|
||||
ZSTD_free(dctx->inBuff, cMem);
|
||||
dctx->inBuff = NULL;
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||
@@ -203,7 +211,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
||||
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
|
||||
{
|
||||
size_t const minInputSize = ZSTD_startingInputLength(format);
|
||||
if (srcSize < minInputSize) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
|
||||
|
||||
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
|
||||
U32 const dictID= fhd & 3;
|
||||
@@ -238,7 +246,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
||||
|
||||
memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
|
||||
if (srcSize < minInputSize) return minInputSize;
|
||||
if (src==NULL) return ERROR(GENERIC); /* invalid parameter */
|
||||
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
|
||||
|
||||
if ( (format != ZSTD_f_zstd1_magicless)
|
||||
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
||||
@@ -251,7 +259,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
||||
zfhPtr->frameType = ZSTD_skippableFrame;
|
||||
return 0;
|
||||
}
|
||||
return ERROR(prefix_unknown);
|
||||
RETURN_ERROR(prefix_unknown);
|
||||
}
|
||||
|
||||
/* ensure there is enough `srcSize` to fully read/decode frame header */
|
||||
@@ -269,14 +277,13 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
||||
U64 windowSize = 0;
|
||||
U32 dictID = 0;
|
||||
U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
||||
if ((fhdByte & 0x08) != 0)
|
||||
return ERROR(frameParameter_unsupported); /* reserved bits, must be zero */
|
||||
RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
|
||||
"reserved bits, must be zero");
|
||||
|
||||
if (!singleSegment) {
|
||||
BYTE const wlByte = ip[pos++];
|
||||
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
||||
if (windowLog > ZSTD_WINDOWLOG_MAX)
|
||||
return ERROR(frameParameter_windowTooLarge);
|
||||
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
|
||||
windowSize = (1ULL << windowLog);
|
||||
windowSize += (windowSize >> 3) * (wlByte&7);
|
||||
}
|
||||
@@ -348,14 +355,16 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
||||
size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
|
||||
U32 sizeU32;
|
||||
|
||||
if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
|
||||
return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
|
||||
|
||||
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
||||
if ((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32)
|
||||
return ERROR(frameParameter_unsupported);
|
||||
|
||||
return skippableHeaderSize + sizeU32;
|
||||
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
||||
frameParameter_unsupported);
|
||||
{
|
||||
size_t const skippableSize = skippableHeaderSize + sizeU32;
|
||||
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong);
|
||||
return skippableSize;
|
||||
}
|
||||
}
|
||||
|
||||
/** ZSTD_findDecompressedSize() :
|
||||
@@ -372,11 +381,10 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
||||
|
||||
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
||||
if (ZSTD_isError(skippableSize))
|
||||
return skippableSize;
|
||||
if (srcSize < skippableSize) {
|
||||
if (ZSTD_isError(skippableSize)) {
|
||||
return ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
assert(skippableSize <= srcSize);
|
||||
|
||||
src = (const BYTE *)src + skippableSize;
|
||||
srcSize -= skippableSize;
|
||||
@@ -428,13 +436,91 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
||||
{
|
||||
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
||||
if (ZSTD_isError(result)) return result; /* invalid header */
|
||||
if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */
|
||||
if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
|
||||
return ERROR(dictionary_wrong);
|
||||
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
||||
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
/* Skip the dictID check in fuzzing mode, because it makes the search
|
||||
* harder.
|
||||
*/
|
||||
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
||||
dictionary_wrong);
|
||||
#endif
|
||||
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
||||
{
|
||||
ZSTD_frameSizeInfo frameSizeInfo;
|
||||
frameSizeInfo.compressedSize = ret;
|
||||
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
return frameSizeInfo;
|
||||
}
|
||||
|
||||
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
||||
{
|
||||
ZSTD_frameSizeInfo frameSizeInfo;
|
||||
memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
||||
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||
if (ZSTD_isLegacy(src, srcSize))
|
||||
return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
|
||||
#endif
|
||||
|
||||
if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
||||
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||
frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
|
||||
assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
|
||||
frameSizeInfo.compressedSize <= srcSize);
|
||||
return frameSizeInfo;
|
||||
} else {
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
const BYTE* const ipstart = ip;
|
||||
size_t remainingSize = srcSize;
|
||||
size_t nbBlocks = 0;
|
||||
ZSTD_frameHeader zfh;
|
||||
|
||||
/* Extract Frame Header */
|
||||
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
||||
if (ZSTD_isError(ret))
|
||||
return ZSTD_errorFrameSizeInfo(ret);
|
||||
if (ret > 0)
|
||||
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
||||
}
|
||||
|
||||
ip += zfh.headerSize;
|
||||
remainingSize -= zfh.headerSize;
|
||||
|
||||
/* Iterate over each block */
|
||||
while (1) {
|
||||
blockProperties_t blockProperties;
|
||||
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||
if (ZSTD_isError(cBlockSize))
|
||||
return ZSTD_errorFrameSizeInfo(cBlockSize);
|
||||
|
||||
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
|
||||
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
||||
|
||||
ip += ZSTD_blockHeaderSize + cBlockSize;
|
||||
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
|
||||
nbBlocks++;
|
||||
|
||||
if (blockProperties.lastBlock) break;
|
||||
}
|
||||
|
||||
/* Final frame content checksum */
|
||||
if (zfh.checksumFlag) {
|
||||
if (remainingSize < 4)
|
||||
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
||||
ip += 4;
|
||||
}
|
||||
|
||||
frameSizeInfo.compressedSize = ip - ipstart;
|
||||
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
||||
? zfh.frameContentSize
|
||||
: nbBlocks * zfh.blockSizeMax;
|
||||
return frameSizeInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/** ZSTD_findFrameCompressedSize() :
|
||||
* compatible with legacy mode
|
||||
@@ -443,52 +529,33 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
||||
* @return : the compressed size of the frame starting at `src` */
|
||||
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
||||
{
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||
if (ZSTD_isLegacy(src, srcSize))
|
||||
return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
||||
#endif
|
||||
if ( (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
||||
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START ) {
|
||||
return readSkippableFrameSize(src, srcSize);
|
||||
} else {
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
const BYTE* const ipstart = ip;
|
||||
size_t remainingSize = srcSize;
|
||||
ZSTD_frameHeader zfh;
|
||||
|
||||
/* Extract Frame Header */
|
||||
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
||||
if (ZSTD_isError(ret)) return ret;
|
||||
if (ret > 0) return ERROR(srcSize_wrong);
|
||||
}
|
||||
|
||||
ip += zfh.headerSize;
|
||||
remainingSize -= zfh.headerSize;
|
||||
|
||||
/* Loop on each block */
|
||||
while (1) {
|
||||
blockProperties_t blockProperties;
|
||||
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
||||
|
||||
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
|
||||
return ERROR(srcSize_wrong);
|
||||
|
||||
ip += ZSTD_blockHeaderSize + cBlockSize;
|
||||
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
|
||||
|
||||
if (blockProperties.lastBlock) break;
|
||||
}
|
||||
|
||||
if (zfh.checksumFlag) { /* Final frame content checksum */
|
||||
if (remainingSize < 4) return ERROR(srcSize_wrong);
|
||||
ip += 4;
|
||||
}
|
||||
|
||||
return ip - ipstart;
|
||||
}
|
||||
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
||||
return frameSizeInfo.compressedSize;
|
||||
}
|
||||
|
||||
/** ZSTD_decompressBound() :
|
||||
* compatible with legacy mode
|
||||
* `src` must point to the start of a ZSTD frame or a skippeable frame
|
||||
* `srcSize` must be at least as large as the frame contained
|
||||
* @return : the maximum decompressed size of the compressed source
|
||||
*/
|
||||
unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
||||
{
|
||||
unsigned long long bound = 0;
|
||||
/* Iterate over each frame */
|
||||
while (srcSize > 0) {
|
||||
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
||||
size_t const compressedSize = frameSizeInfo.compressedSize;
|
||||
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
||||
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
||||
return ZSTD_CONTENTSIZE_ERROR;
|
||||
assert(srcSize >= compressedSize);
|
||||
src = (const BYTE*)src + compressedSize;
|
||||
srcSize -= compressedSize;
|
||||
bound += decompressedBound;
|
||||
}
|
||||
return bound;
|
||||
}
|
||||
|
||||
|
||||
/*-*************************************************************
|
||||
@@ -522,9 +589,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
||||
DEBUGLOG(5, "ZSTD_copyRawBlock");
|
||||
if (dst == NULL) {
|
||||
if (srcSize == 0) return 0;
|
||||
return ERROR(dstBuffer_null);
|
||||
RETURN_ERROR(dstBuffer_null);
|
||||
}
|
||||
if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall);
|
||||
memcpy(dst, src, srcSize);
|
||||
return srcSize;
|
||||
}
|
||||
@@ -535,9 +602,9 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
||||
{
|
||||
if (dst == NULL) {
|
||||
if (regenSize == 0) return 0;
|
||||
return ERROR(dstBuffer_null);
|
||||
RETURN_ERROR(dstBuffer_null);
|
||||
}
|
||||
if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall);
|
||||
memset(dst, b, regenSize);
|
||||
return regenSize;
|
||||
}
|
||||
@@ -560,15 +627,16 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
|
||||
|
||||
/* check */
|
||||
if (remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize)
|
||||
return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(
|
||||
remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize,
|
||||
srcSize_wrong);
|
||||
|
||||
/* Frame Header */
|
||||
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_FRAMEHEADERSIZE_PREFIX);
|
||||
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
||||
if (remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize)
|
||||
return ERROR(srcSize_wrong);
|
||||
CHECK_F( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
|
||||
RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
|
||||
srcSize_wrong);
|
||||
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
|
||||
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
|
||||
}
|
||||
|
||||
@@ -581,7 +649,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
|
||||
ip += ZSTD_blockHeaderSize;
|
||||
remainingSrcSize -= ZSTD_blockHeaderSize;
|
||||
if (cBlockSize > remainingSrcSize) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
|
||||
|
||||
switch(blockProperties.blockType)
|
||||
{
|
||||
@@ -596,7 +664,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
break;
|
||||
case bt_reserved :
|
||||
default:
|
||||
return ERROR(corruption_detected);
|
||||
RETURN_ERROR(corruption_detected);
|
||||
}
|
||||
|
||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||
@@ -609,15 +677,15 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
}
|
||||
|
||||
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
||||
if ((U64)(op-ostart) != dctx->fParams.frameContentSize) {
|
||||
return ERROR(corruption_detected);
|
||||
} }
|
||||
RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
|
||||
corruption_detected);
|
||||
}
|
||||
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
||||
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
||||
U32 checkRead;
|
||||
if (remainingSrcSize<4) return ERROR(checksum_wrong);
|
||||
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong);
|
||||
checkRead = MEM_readLE32(ip);
|
||||
if (checkRead != checkCalc) return ERROR(checksum_wrong);
|
||||
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong);
|
||||
ip += 4;
|
||||
remainingSrcSize -= 4;
|
||||
}
|
||||
@@ -652,8 +720,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
size_t decodedSize;
|
||||
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
||||
if (ZSTD_isError(frameSize)) return frameSize;
|
||||
/* legacy support is not compatible with static dctx */
|
||||
if (dctx->staticSize) return ERROR(memory_allocation);
|
||||
RETURN_ERROR_IF(dctx->staticSize, memory_allocation,
|
||||
"legacy support is not compatible with static dctx");
|
||||
|
||||
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||
@@ -674,9 +742,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
(unsigned)magicNumber, ZSTD_MAGICNUMBER);
|
||||
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
||||
if (ZSTD_isError(skippableSize))
|
||||
return skippableSize;
|
||||
if (srcSize < skippableSize) return ERROR(srcSize_wrong);
|
||||
FORWARD_IF_ERROR(skippableSize);
|
||||
assert(skippableSize <= srcSize);
|
||||
|
||||
src = (const BYTE *)src + skippableSize;
|
||||
srcSize -= skippableSize;
|
||||
@@ -685,29 +752,29 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
|
||||
if (ddict) {
|
||||
/* we were called from ZSTD_decompress_usingDDict */
|
||||
CHECK_F(ZSTD_decompressBegin_usingDDict(dctx, ddict));
|
||||
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
|
||||
} else {
|
||||
/* this will initialize correctly with no dict if dict == NULL, so
|
||||
* use this in all cases but ddict */
|
||||
CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
||||
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
||||
}
|
||||
ZSTD_checkContinuity(dctx, dst);
|
||||
|
||||
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
||||
&src, &srcSize);
|
||||
if ( (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
||||
&& (moreThan1Frame==1) ) {
|
||||
/* at least one frame successfully completed,
|
||||
* but following bytes are garbage :
|
||||
* it's more likely to be a srcSize error,
|
||||
* specifying more bytes than compressed size of frame(s).
|
||||
* This error message replaces ERROR(prefix_unknown),
|
||||
* which would be confusing, as the first header is actually correct.
|
||||
* Note that one could be unlucky, it might be a corruption error instead,
|
||||
* happening right at the place where we expect zstd magic bytes.
|
||||
* But this is _much_ less likely than a srcSize field error. */
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
RETURN_ERROR_IF(
|
||||
(ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
||||
&& (moreThan1Frame==1),
|
||||
srcSize_wrong,
|
||||
"at least one frame successfully completed, but following "
|
||||
"bytes are garbage: it's more likely to be a srcSize error, "
|
||||
"specifying more bytes than compressed size of frame(s). This "
|
||||
"error message replaces ERROR(prefix_unknown), which would be "
|
||||
"confusing, as the first header is actually correct. Note that "
|
||||
"one could be unlucky, it might be a corruption error instead, "
|
||||
"happening right at the place where we expect zstd magic "
|
||||
"bytes. But this is _much_ less likely than a srcSize field "
|
||||
"error.");
|
||||
if (ZSTD_isError(res)) return res;
|
||||
assert(res <= dstCapacity);
|
||||
dst = (BYTE*)dst + res;
|
||||
@@ -716,7 +783,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
moreThan1Frame = 1;
|
||||
} /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
|
||||
|
||||
if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */
|
||||
RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
|
||||
|
||||
return (BYTE*)dst - (BYTE*)dststart;
|
||||
}
|
||||
@@ -730,9 +797,26 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
||||
}
|
||||
|
||||
|
||||
static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
|
||||
{
|
||||
switch (dctx->dictUses) {
|
||||
default:
|
||||
assert(0 /* Impossible */);
|
||||
/* fall-through */
|
||||
case ZSTD_dont_use:
|
||||
ZSTD_clearDict(dctx);
|
||||
return NULL;
|
||||
case ZSTD_use_indefinitely:
|
||||
return dctx->ddict;
|
||||
case ZSTD_use_once:
|
||||
dctx->dictUses = ZSTD_dont_use;
|
||||
return dctx->ddict;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
|
||||
return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
|
||||
}
|
||||
|
||||
|
||||
@@ -741,7 +825,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
||||
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
||||
size_t regenSize;
|
||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||
if (dctx==NULL) return ERROR(memory_allocation);
|
||||
RETURN_ERROR_IF(dctx==NULL, memory_allocation);
|
||||
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
||||
ZSTD_freeDCtx(dctx);
|
||||
return regenSize;
|
||||
@@ -791,8 +875,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
||||
/* Sanity check */
|
||||
if (srcSize != dctx->expected)
|
||||
return ERROR(srcSize_wrong); /* not allowed */
|
||||
RETURN_ERROR_IF(srcSize != dctx->expected, srcSize_wrong, "not allowed");
|
||||
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
||||
|
||||
switch (dctx->stage)
|
||||
@@ -817,7 +900,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||
case ZSTDds_decodeFrameHeader:
|
||||
assert(src != NULL);
|
||||
memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
||||
CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
|
||||
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
|
||||
dctx->expected = ZSTD_blockHeaderSize;
|
||||
dctx->stage = ZSTDds_decodeBlockHeader;
|
||||
return 0;
|
||||
@@ -867,7 +950,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||
break;
|
||||
case bt_reserved : /* should never happen */
|
||||
default:
|
||||
return ERROR(corruption_detected);
|
||||
RETURN_ERROR(corruption_detected);
|
||||
}
|
||||
if (ZSTD_isError(rSize)) return rSize;
|
||||
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
||||
@@ -876,10 +959,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||
|
||||
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
||||
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
|
||||
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
||||
if (dctx->decodedSize != dctx->fParams.frameContentSize) {
|
||||
return ERROR(corruption_detected);
|
||||
} }
|
||||
RETURN_ERROR_IF(
|
||||
dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
||||
&& dctx->decodedSize != dctx->fParams.frameContentSize,
|
||||
corruption_detected);
|
||||
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
||||
dctx->expected = 4;
|
||||
dctx->stage = ZSTDds_checkChecksum;
|
||||
@@ -900,7 +983,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
||||
U32 const check32 = MEM_readLE32(src);
|
||||
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
||||
if (check32 != h32) return ERROR(checksum_wrong);
|
||||
RETURN_ERROR_IF(check32 != h32, checksum_wrong);
|
||||
dctx->expected = 0;
|
||||
dctx->stage = ZSTDds_getFrameHeaderSize;
|
||||
return 0;
|
||||
@@ -921,7 +1004,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||
|
||||
default:
|
||||
assert(0); /* impossible */
|
||||
return ERROR(GENERIC); /* some compiler require default to do something */
|
||||
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -945,7 +1028,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
||||
const BYTE* dictPtr = (const BYTE*)dict;
|
||||
const BYTE* const dictEnd = dictPtr + dictSize;
|
||||
|
||||
if (dictSize <= 8) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
|
||||
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
|
||||
dictPtr += 8; /* skip header = magic + dictID */
|
||||
|
||||
@@ -964,16 +1047,16 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
||||
dictPtr, dictEnd - dictPtr,
|
||||
workspace, workspaceSize);
|
||||
#endif
|
||||
if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
|
||||
dictPtr += hSize;
|
||||
}
|
||||
|
||||
{ short offcodeNCount[MaxOff+1];
|
||||
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
||||
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
||||
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
|
||||
if (offcodeMaxValue > MaxOff) return ERROR(dictionary_corrupted);
|
||||
if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
|
||||
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
|
||||
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
|
||||
ZSTD_buildFSETable( entropy->OFTable,
|
||||
offcodeNCount, offcodeMaxValue,
|
||||
OF_base, OF_bits,
|
||||
@@ -984,9 +1067,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
||||
{ short matchlengthNCount[MaxML+1];
|
||||
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
||||
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
||||
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
||||
if (matchlengthMaxValue > MaxML) return ERROR(dictionary_corrupted);
|
||||
if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
|
||||
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
|
||||
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
|
||||
ZSTD_buildFSETable( entropy->MLTable,
|
||||
matchlengthNCount, matchlengthMaxValue,
|
||||
ML_base, ML_bits,
|
||||
@@ -997,9 +1080,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
||||
{ short litlengthNCount[MaxLL+1];
|
||||
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
||||
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
||||
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
||||
if (litlengthMaxValue > MaxLL) return ERROR(dictionary_corrupted);
|
||||
if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
|
||||
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
|
||||
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
|
||||
ZSTD_buildFSETable( entropy->LLTable,
|
||||
litlengthNCount, litlengthMaxValue,
|
||||
LL_base, LL_bits,
|
||||
@@ -1007,12 +1090,13 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
||||
dictPtr += litlengthHeaderSize;
|
||||
}
|
||||
|
||||
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
|
||||
{ int i;
|
||||
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
||||
for (i=0; i<3; i++) {
|
||||
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
||||
if (rep==0 || rep >= dictContentSize) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(rep==0 || rep >= dictContentSize,
|
||||
dictionary_corrupted);
|
||||
entropy->rep[i] = rep;
|
||||
} }
|
||||
|
||||
@@ -1030,7 +1114,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
||||
|
||||
/* load entropy tables */
|
||||
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
|
||||
if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
|
||||
dict = (const char*)dict + eSize;
|
||||
dictSize -= eSize;
|
||||
}
|
||||
@@ -1064,9 +1148,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
||||
|
||||
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
||||
{
|
||||
CHECK_F( ZSTD_decompressBegin(dctx) );
|
||||
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
||||
if (dict && dictSize)
|
||||
CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
|
||||
RETURN_ERROR_IF(
|
||||
ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
|
||||
dictionary_corrupted);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1085,7 +1171,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
||||
DEBUGLOG(4, "DDict is %s",
|
||||
dctx->ddictIsCold ? "~cold~" : "hot!");
|
||||
}
|
||||
CHECK_F( ZSTD_decompressBegin(dctx) );
|
||||
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
||||
if (ddict) { /* NULL ddict is equivalent to no dictionary */
|
||||
ZSTD_copyDDictParameters(dctx, ddict);
|
||||
}
|
||||
@@ -1104,7 +1190,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
||||
}
|
||||
|
||||
/*! ZSTD_getDictID_fromFrame() :
|
||||
* Provides the dictID required to decompresse frame stored within `src`.
|
||||
* Provides the dictID required to decompress frame stored within `src`.
|
||||
* If @return == 0, the dictID could not be decoded.
|
||||
* This could for one of the following reasons :
|
||||
* - The frame does not require a dictionary (most common case).
|
||||
@@ -1176,15 +1262,14 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
|
||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||
ZSTD_dictContentType_e dictContentType)
|
||||
{
|
||||
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
|
||||
ZSTD_freeDDict(dctx->ddictLocal);
|
||||
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||
ZSTD_clearDict(dctx);
|
||||
if (dict && dictSize >= 8) {
|
||||
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
|
||||
if (dctx->ddictLocal == NULL) return ERROR(memory_allocation);
|
||||
} else {
|
||||
dctx->ddictLocal = NULL;
|
||||
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
|
||||
dctx->ddict = dctx->ddictLocal;
|
||||
dctx->dictUses = ZSTD_use_indefinitely;
|
||||
}
|
||||
dctx->ddict = dctx->ddictLocal;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1200,7 +1285,9 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
|
||||
|
||||
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
||||
{
|
||||
return ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType);
|
||||
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
|
||||
dctx->dictUses = ZSTD_use_once;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
|
||||
@@ -1215,9 +1302,8 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
|
||||
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
|
||||
zds->streamStage = zdss_init;
|
||||
zds->noForwardProgress = 0;
|
||||
CHECK_F( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
|
||||
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
|
||||
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
||||
}
|
||||
|
||||
@@ -1225,7 +1311,7 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
||||
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_initDStream");
|
||||
return ZSTD_initDStream_usingDict(zds, NULL, 0);
|
||||
return ZSTD_initDStream_usingDDict(zds, NULL);
|
||||
}
|
||||
|
||||
/* ZSTD_initDStream_usingDDict() :
|
||||
@@ -1233,9 +1319,9 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
||||
* this function cannot fail */
|
||||
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
||||
{
|
||||
size_t const initResult = ZSTD_initDStream(dctx);
|
||||
dctx->ddict = ddict;
|
||||
return initResult;
|
||||
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
|
||||
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
|
||||
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
||||
}
|
||||
|
||||
/* ZSTD_resetDStream() :
|
||||
@@ -1243,19 +1329,19 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
||||
* this function cannot fail */
|
||||
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_resetDStream");
|
||||
dctx->streamStage = zdss_loadHeader;
|
||||
dctx->lhSize = dctx->inPos = dctx->outStart = dctx->outEnd = 0;
|
||||
dctx->legacyVersion = 0;
|
||||
dctx->hostageByte = 0;
|
||||
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
|
||||
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
||||
{
|
||||
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
|
||||
dctx->ddict = ddict;
|
||||
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||
ZSTD_clearDict(dctx);
|
||||
if (ddict) {
|
||||
dctx->ddict = ddict;
|
||||
dctx->dictUses = ZSTD_use_indefinitely;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1267,9 +1353,9 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
||||
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
|
||||
size_t const min = (size_t)1 << bounds.lowerBound;
|
||||
size_t const max = (size_t)1 << bounds.upperBound;
|
||||
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
|
||||
if (maxWindowSize < min) return ERROR(parameter_outOfBound);
|
||||
if (maxWindowSize > max) return ERROR(parameter_outOfBound);
|
||||
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
|
||||
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
|
||||
dctx->maxWindowSize = maxWindowSize;
|
||||
return 0;
|
||||
}
|
||||
@@ -1311,15 +1397,15 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
|
||||
}
|
||||
|
||||
#define CHECK_DBOUNDS(p,v) { \
|
||||
if (!ZSTD_dParam_withinBounds(p, v)) \
|
||||
return ERROR(parameter_outOfBound); \
|
||||
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
|
||||
}
|
||||
|
||||
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
||||
{
|
||||
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
|
||||
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||
switch(dParam) {
|
||||
case ZSTD_d_windowLogMax:
|
||||
if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
|
||||
CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
|
||||
dctx->maxWindowSize = ((size_t)1) << value;
|
||||
return 0;
|
||||
@@ -1329,19 +1415,20 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
||||
return 0;
|
||||
default:;
|
||||
}
|
||||
return ERROR(parameter_unsupported);
|
||||
RETURN_ERROR(parameter_unsupported);
|
||||
}
|
||||
|
||||
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
||||
{
|
||||
if ( (reset == ZSTD_reset_session_only)
|
||||
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
||||
(void)ZSTD_initDStream(dctx);
|
||||
dctx->streamStage = zdss_init;
|
||||
dctx->noForwardProgress = 0;
|
||||
}
|
||||
if ( (reset == ZSTD_reset_parameters)
|
||||
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
||||
if (dctx->streamStage != zdss_init)
|
||||
return ERROR(stage_wrong);
|
||||
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||
ZSTD_clearDict(dctx);
|
||||
dctx->format = ZSTD_f_zstd1;
|
||||
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
||||
}
|
||||
@@ -1360,7 +1447,8 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
|
||||
unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
|
||||
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
||||
size_t const minRBSize = (size_t) neededSize;
|
||||
if ((unsigned long long)minRBSize != neededSize) return ERROR(frameParameter_windowTooLarge);
|
||||
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
||||
frameParameter_windowTooLarge);
|
||||
return minRBSize;
|
||||
}
|
||||
|
||||
@@ -1378,9 +1466,9 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
||||
ZSTD_frameHeader zfh;
|
||||
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
||||
if (ZSTD_isError(err)) return err;
|
||||
if (err>0) return ERROR(srcSize_wrong);
|
||||
if (zfh.windowSize > windowSizeMax)
|
||||
return ERROR(frameParameter_windowTooLarge);
|
||||
RETURN_ERROR_IF(err>0, srcSize_wrong);
|
||||
RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
|
||||
frameParameter_windowTooLarge);
|
||||
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
||||
}
|
||||
|
||||
@@ -1406,16 +1494,16 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
U32 someMoreWork = 1;
|
||||
|
||||
DEBUGLOG(5, "ZSTD_decompressStream");
|
||||
if (input->pos > input->size) { /* forbidden */
|
||||
DEBUGLOG(5, "in: pos: %u vs size: %u",
|
||||
(U32)input->pos, (U32)input->size);
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
if (output->pos > output->size) { /* forbidden */
|
||||
DEBUGLOG(5, "out: pos: %u vs size: %u",
|
||||
(U32)output->pos, (U32)output->size);
|
||||
return ERROR(dstSize_tooSmall);
|
||||
}
|
||||
RETURN_ERROR_IF(
|
||||
input->pos > input->size,
|
||||
srcSize_wrong,
|
||||
"forbidden. in: pos: %u vs size: %u",
|
||||
(U32)input->pos, (U32)input->size);
|
||||
RETURN_ERROR_IF(
|
||||
output->pos > output->size,
|
||||
dstSize_tooSmall,
|
||||
"forbidden. out: pos: %u vs size: %u",
|
||||
(U32)output->pos, (U32)output->size);
|
||||
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
||||
|
||||
while (someMoreWork) {
|
||||
@@ -1423,15 +1511,18 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
{
|
||||
case zdss_init :
|
||||
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
||||
ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
|
||||
zds->streamStage = zdss_loadHeader;
|
||||
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
||||
zds->legacyVersion = 0;
|
||||
zds->hostageByte = 0;
|
||||
/* fall-through */
|
||||
|
||||
case zdss_loadHeader :
|
||||
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
||||
if (zds->legacyVersion) {
|
||||
/* legacy support is incompatible with static dctx */
|
||||
if (zds->staticSize) return ERROR(memory_allocation);
|
||||
RETURN_ERROR_IF(zds->staticSize, memory_allocation,
|
||||
"legacy support is incompatible with static dctx");
|
||||
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
|
||||
if (hint==0) zds->streamStage = zdss_init;
|
||||
return hint;
|
||||
@@ -1443,12 +1534,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
||||
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
||||
if (legacyVersion) {
|
||||
const void* const dict = zds->ddict ? ZSTD_DDict_dictContent(zds->ddict) : NULL;
|
||||
size_t const dictSize = zds->ddict ? ZSTD_DDict_dictSize(zds->ddict) : 0;
|
||||
ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);
|
||||
const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;
|
||||
size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;
|
||||
DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
|
||||
/* legacy support is incompatible with static dctx */
|
||||
if (zds->staticSize) return ERROR(memory_allocation);
|
||||
CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext,
|
||||
RETURN_ERROR_IF(zds->staticSize, memory_allocation,
|
||||
"legacy support is incompatible with static dctx");
|
||||
FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
|
||||
zds->previousLegacyVersion, legacyVersion,
|
||||
dict, dictSize));
|
||||
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
||||
@@ -1482,7 +1574,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
||||
if (cSize <= (size_t)(iend-istart)) {
|
||||
/* shortcut : using single-pass mode */
|
||||
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds->ddict);
|
||||
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
|
||||
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
||||
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
||||
ip = istart + cSize;
|
||||
@@ -1495,13 +1587,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
|
||||
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
||||
DEBUGLOG(4, "Consume header");
|
||||
CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
|
||||
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
|
||||
|
||||
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
||||
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
||||
zds->stage = ZSTDds_skipFrame;
|
||||
} else {
|
||||
CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
||||
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
||||
zds->expected = ZSTD_blockHeaderSize;
|
||||
zds->stage = ZSTDds_decodeBlockHeader;
|
||||
}
|
||||
@@ -1511,7 +1603,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
(U32)(zds->fParams.windowSize >>10),
|
||||
(U32)(zds->maxWindowSize >> 10) );
|
||||
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
||||
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
|
||||
RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
|
||||
frameParameter_windowTooLarge);
|
||||
|
||||
/* Adapt buffer sizes to frame header instructions */
|
||||
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
||||
@@ -1525,14 +1618,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
if (zds->staticSize) { /* static DCtx */
|
||||
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
||||
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
||||
if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx))
|
||||
return ERROR(memory_allocation);
|
||||
RETURN_ERROR_IF(
|
||||
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
||||
memory_allocation);
|
||||
} else {
|
||||
ZSTD_free(zds->inBuff, zds->customMem);
|
||||
zds->inBuffSize = 0;
|
||||
zds->outBuffSize = 0;
|
||||
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
|
||||
if (zds->inBuff == NULL) return ERROR(memory_allocation);
|
||||
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
|
||||
}
|
||||
zds->inBuffSize = neededInBuffSize;
|
||||
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
||||
@@ -1574,7 +1668,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
if (isSkipFrame) {
|
||||
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
||||
} else {
|
||||
if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */
|
||||
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
|
||||
corruption_detected,
|
||||
"should never happen");
|
||||
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
||||
}
|
||||
ip += loadedSize;
|
||||
@@ -1615,7 +1711,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
|
||||
default:
|
||||
assert(0); /* impossible */
|
||||
return ERROR(GENERIC); /* some compiler require default to do something */
|
||||
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
||||
} }
|
||||
|
||||
/* result */
|
||||
@@ -1624,8 +1720,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
||||
zds->noForwardProgress ++;
|
||||
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
||||
if (op==oend) return ERROR(dstSize_tooSmall);
|
||||
if (ip==iend) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(ip==iend, srcSize_wrong);
|
||||
assert(0);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -56,14 +56,15 @@ static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
|
||||
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
|
||||
blockProperties_t* bpPtr)
|
||||
{
|
||||
if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong);
|
||||
|
||||
{ U32 const cBlockHeader = MEM_readLE24(src);
|
||||
U32 const cSize = cBlockHeader >> 3;
|
||||
bpPtr->lastBlock = cBlockHeader & 1;
|
||||
bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
|
||||
bpPtr->origSize = cSize; /* only useful for RLE */
|
||||
if (bpPtr->blockType == bt_rle) return 1;
|
||||
if (bpPtr->blockType == bt_reserved) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected);
|
||||
return cSize;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +79,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
|
||||
{
|
||||
if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected);
|
||||
|
||||
{ const BYTE* const istart = (const BYTE*) src;
|
||||
symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
|
||||
@@ -86,11 +87,11 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
switch(litEncType)
|
||||
{
|
||||
case set_repeat:
|
||||
if (dctx->litEntropy==0) return ERROR(dictionary_corrupted);
|
||||
RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted);
|
||||
/* fall-through */
|
||||
|
||||
case set_compressed:
|
||||
if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
|
||||
RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3");
|
||||
{ size_t lhSize, litSize, litCSize;
|
||||
U32 singleStream=0;
|
||||
U32 const lhlCode = (istart[0] >> 2) & 3;
|
||||
@@ -118,8 +119,8 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
litCSize = (lhc >> 22) + (istart[4] << 10);
|
||||
break;
|
||||
}
|
||||
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
||||
if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected);
|
||||
RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected);
|
||||
|
||||
/* prefetch huffman table if cold */
|
||||
if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {
|
||||
@@ -157,7 +158,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
}
|
||||
}
|
||||
|
||||
if (HUF_isError(hufSuccess)) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected);
|
||||
|
||||
dctx->litPtr = dctx->litBuffer;
|
||||
dctx->litSize = litSize;
|
||||
@@ -187,7 +188,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
}
|
||||
|
||||
if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
|
||||
if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected);
|
||||
memcpy(dctx->litBuffer, istart+lhSize, litSize);
|
||||
dctx->litPtr = dctx->litBuffer;
|
||||
dctx->litSize = litSize;
|
||||
@@ -216,17 +217,17 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
case 3:
|
||||
lhSize = 3;
|
||||
litSize = MEM_readLE24(istart) >> 4;
|
||||
if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
|
||||
RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4");
|
||||
break;
|
||||
}
|
||||
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected);
|
||||
memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
|
||||
dctx->litPtr = dctx->litBuffer;
|
||||
dctx->litSize = litSize;
|
||||
return lhSize+1;
|
||||
}
|
||||
default:
|
||||
return ERROR(corruption_detected); /* impossible */
|
||||
RETURN_ERROR(corruption_detected, "impossible");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -436,8 +437,8 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
|
||||
switch(type)
|
||||
{
|
||||
case set_rle :
|
||||
if (!srcSize) return ERROR(srcSize_wrong);
|
||||
if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(!srcSize, srcSize_wrong);
|
||||
RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected);
|
||||
{ U32 const symbol = *(const BYTE*)src;
|
||||
U32 const baseline = baseValue[symbol];
|
||||
U32 const nbBits = nbAdditionalBits[symbol];
|
||||
@@ -449,7 +450,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
|
||||
*DTablePtr = defaultTable;
|
||||
return 0;
|
||||
case set_repeat:
|
||||
if (!flagRepeatTable) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(!flagRepeatTable, corruption_detected);
|
||||
/* prefetch FSE table if used */
|
||||
if (ddictIsCold && (nbSeq > 24 /* heuristic */)) {
|
||||
const void* const pStart = *DTablePtr;
|
||||
@@ -461,15 +462,15 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
|
||||
{ unsigned tableLog;
|
||||
S16 norm[MaxSeq+1];
|
||||
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
|
||||
if (FSE_isError(headerSize)) return ERROR(corruption_detected);
|
||||
if (tableLog > maxLog) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected);
|
||||
RETURN_ERROR_IF(tableLog > maxLog, corruption_detected);
|
||||
ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog);
|
||||
*DTablePtr = DTableSpace;
|
||||
return headerSize;
|
||||
}
|
||||
default : /* impossible */
|
||||
default :
|
||||
assert(0);
|
||||
return ERROR(GENERIC);
|
||||
RETURN_ERROR(GENERIC, "impossible");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,28 +484,28 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
||||
DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
|
||||
|
||||
/* check */
|
||||
if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong);
|
||||
|
||||
/* SeqHead */
|
||||
nbSeq = *ip++;
|
||||
if (!nbSeq) {
|
||||
*nbSeqPtr=0;
|
||||
if (srcSize != 1) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(srcSize != 1, srcSize_wrong);
|
||||
return 1;
|
||||
}
|
||||
if (nbSeq > 0x7F) {
|
||||
if (nbSeq == 0xFF) {
|
||||
if (ip+2 > iend) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong);
|
||||
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
||||
} else {
|
||||
if (ip >= iend) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(ip >= iend, srcSize_wrong);
|
||||
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
||||
}
|
||||
}
|
||||
*nbSeqPtr = nbSeq;
|
||||
|
||||
/* FSE table descriptors */
|
||||
if (ip+4 > iend) return ERROR(srcSize_wrong); /* minimum possible size */
|
||||
RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong); /* minimum possible size: 1 byte for symbol encoding types */
|
||||
{ symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
|
||||
symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
|
||||
symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
|
||||
@@ -517,7 +518,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
||||
LL_base, LL_bits,
|
||||
LL_defaultDTable, dctx->fseEntropy,
|
||||
dctx->ddictIsCold, nbSeq);
|
||||
if (ZSTD_isError(llhSize)) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected);
|
||||
ip += llhSize;
|
||||
}
|
||||
|
||||
@@ -527,7 +528,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
||||
OF_base, OF_bits,
|
||||
OF_defaultDTable, dctx->fseEntropy,
|
||||
dctx->ddictIsCold, nbSeq);
|
||||
if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected);
|
||||
ip += ofhSize;
|
||||
}
|
||||
|
||||
@@ -537,7 +538,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
||||
ML_base, ML_bits,
|
||||
ML_defaultDTable, dctx->fseEntropy,
|
||||
dctx->ddictIsCold, nbSeq);
|
||||
if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected);
|
||||
ip += mlhSize;
|
||||
}
|
||||
}
|
||||
@@ -590,8 +591,8 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
|
||||
const BYTE* match = oLitEnd - sequence.offset;
|
||||
|
||||
/* check */
|
||||
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must fit within dstBuffer */
|
||||
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* try to read beyond literal buffer */
|
||||
RETURN_ERROR_IF(oMatchEnd>oend, dstSize_tooSmall, "last match must fit within dstBuffer");
|
||||
RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "try to read beyond literal buffer");
|
||||
|
||||
/* copy literals */
|
||||
while (op < oLitEnd) *op++ = *(*litPtr)++;
|
||||
@@ -599,7 +600,7 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
|
||||
/* copy Match */
|
||||
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
||||
/* offset beyond prefix */
|
||||
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - vBase),corruption_detected);
|
||||
match = dictEnd - (base-match);
|
||||
if (match + sequence.matchLength <= dictEnd) {
|
||||
memmove(oLitEnd, match, sequence.matchLength);
|
||||
@@ -631,22 +632,22 @@ size_t ZSTD_execSequence(BYTE* op,
|
||||
const BYTE* match = oLitEnd - sequence.offset;
|
||||
|
||||
/* check */
|
||||
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
||||
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
||||
RETURN_ERROR_IF(oMatchEnd>oend, dstSize_tooSmall, "last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend");
|
||||
RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "over-read beyond lit buffer");
|
||||
if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
|
||||
|
||||
/* copy Literals */
|
||||
ZSTD_copy8(op, *litPtr);
|
||||
if (sequence.litLength > 8)
|
||||
ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
||||
ZSTD_wildcopy_16min(op, (*litPtr), sequence.litLength, ZSTD_no_overlap); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
||||
else
|
||||
ZSTD_copy8(op, *litPtr);
|
||||
op = oLitEnd;
|
||||
*litPtr = iLitEnd; /* update for next sequence */
|
||||
|
||||
/* copy Match */
|
||||
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
|
||||
/* offset beyond prefix -> go into extDict */
|
||||
if (sequence.offset > (size_t)(oLitEnd - virtualStart))
|
||||
return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected);
|
||||
match = dictEnd + (match - prefixStart);
|
||||
if (match + sequence.matchLength <= dictEnd) {
|
||||
memmove(oLitEnd, match, sequence.matchLength);
|
||||
@@ -686,13 +687,13 @@ size_t ZSTD_execSequence(BYTE* op,
|
||||
|
||||
if (oMatchEnd > oend-(16-MINMATCH)) {
|
||||
if (op < oend_w) {
|
||||
ZSTD_wildcopy(op, match, oend_w - op);
|
||||
ZSTD_wildcopy(op, match, oend_w - op, ZSTD_overlap_src_before_dst);
|
||||
match += oend_w - op;
|
||||
op = oend_w;
|
||||
}
|
||||
while (op < oMatchEnd) *op++ = *match++;
|
||||
} else {
|
||||
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
|
||||
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst); /* works even if matchLength < 8 */
|
||||
}
|
||||
return sequenceLength;
|
||||
}
|
||||
@@ -712,21 +713,23 @@ size_t ZSTD_execSequenceLong(BYTE* op,
|
||||
const BYTE* match = sequence.match;
|
||||
|
||||
/* check */
|
||||
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
||||
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
||||
RETURN_ERROR_IF(oMatchEnd > oend, dstSize_tooSmall, "last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend");
|
||||
RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "over-read beyond lit buffer");
|
||||
if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
|
||||
|
||||
/* copy Literals */
|
||||
ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
|
||||
if (sequence.litLength > 8)
|
||||
ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
||||
ZSTD_wildcopy_16min(op, *litPtr, sequence.litLength, ZSTD_no_overlap); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
||||
else
|
||||
ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
|
||||
|
||||
op = oLitEnd;
|
||||
*litPtr = iLitEnd; /* update for next sequence */
|
||||
|
||||
/* copy Match */
|
||||
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
|
||||
/* offset beyond prefix */
|
||||
if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - dictStart), corruption_detected);
|
||||
if (match + sequence.matchLength <= dictEnd) {
|
||||
memmove(oLitEnd, match, sequence.matchLength);
|
||||
return sequenceLength;
|
||||
@@ -766,13 +769,13 @@ size_t ZSTD_execSequenceLong(BYTE* op,
|
||||
|
||||
if (oMatchEnd > oend-(16-MINMATCH)) {
|
||||
if (op < oend_w) {
|
||||
ZSTD_wildcopy(op, match, oend_w - op);
|
||||
ZSTD_wildcopy(op, match, oend_w - op, ZSTD_overlap_src_before_dst);
|
||||
match += oend_w - op;
|
||||
op = oend_w;
|
||||
}
|
||||
while (op < oMatchEnd) *op++ = *match++;
|
||||
} else {
|
||||
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
|
||||
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst); /* works even if matchLength < 8 */
|
||||
}
|
||||
return sequenceLength;
|
||||
}
|
||||
@@ -801,7 +804,7 @@ ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD)
|
||||
/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
|
||||
* offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
|
||||
* bits before reloading. This value is the maximum number of bytes we read
|
||||
* after reloading when we are decoding long offets.
|
||||
* after reloading when we are decoding long offsets.
|
||||
*/
|
||||
#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
|
||||
(ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
|
||||
@@ -889,6 +892,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
DONT_VECTORIZE
|
||||
ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
||||
void* dst, size_t maxDstSize,
|
||||
const void* seqStart, size_t seqSize, int nbSeq,
|
||||
@@ -911,11 +915,18 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
||||
seqState_t seqState;
|
||||
dctx->fseEntropy = 1;
|
||||
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
||||
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
||||
RETURN_ERROR_IF(
|
||||
ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
|
||||
corruption_detected);
|
||||
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
||||
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
||||
ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
||||
|
||||
ZSTD_STATIC_ASSERT(
|
||||
BIT_DStream_unfinished < BIT_DStream_completed &&
|
||||
BIT_DStream_endOfBuffer < BIT_DStream_completed &&
|
||||
BIT_DStream_completed < BIT_DStream_overflow);
|
||||
|
||||
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
|
||||
nbSeq--;
|
||||
{ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
|
||||
@@ -927,14 +938,15 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
||||
|
||||
/* check if reached exact end */
|
||||
DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
|
||||
if (nbSeq) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(nbSeq, corruption_detected);
|
||||
RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected);
|
||||
/* save reps for next block */
|
||||
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
||||
}
|
||||
|
||||
/* last literal segment */
|
||||
{ size_t const lastLLSize = litEnd - litPtr;
|
||||
if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall);
|
||||
memcpy(op, litPtr, lastLLSize);
|
||||
op += lastLLSize;
|
||||
}
|
||||
@@ -1066,7 +1078,9 @@ ZSTD_decompressSequencesLong_body(
|
||||
seqState.pos = (size_t)(op-prefixStart);
|
||||
seqState.dictEnd = dictEnd;
|
||||
assert(iend >= ip);
|
||||
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
||||
RETURN_ERROR_IF(
|
||||
ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
|
||||
corruption_detected);
|
||||
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
||||
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
||||
ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
||||
@@ -1076,7 +1090,7 @@ ZSTD_decompressSequencesLong_body(
|
||||
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
|
||||
PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
||||
}
|
||||
if (seqNb<seqAdvance) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected);
|
||||
|
||||
/* decode and decompress */
|
||||
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
|
||||
@@ -1087,7 +1101,7 @@ ZSTD_decompressSequencesLong_body(
|
||||
sequences[seqNb & STORED_SEQS_MASK] = sequence;
|
||||
op += oneSeqSize;
|
||||
}
|
||||
if (seqNb<nbSeq) return ERROR(corruption_detected);
|
||||
RETURN_ERROR_IF(seqNb<nbSeq, corruption_detected);
|
||||
|
||||
/* finish queue */
|
||||
seqNb -= seqAdvance;
|
||||
@@ -1103,7 +1117,7 @@ ZSTD_decompressSequencesLong_body(
|
||||
|
||||
/* last literal segment */
|
||||
{ size_t const lastLLSize = litEnd - litPtr;
|
||||
if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);
|
||||
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall);
|
||||
memcpy(op, litPtr, lastLLSize);
|
||||
op += lastLLSize;
|
||||
}
|
||||
@@ -1127,6 +1141,7 @@ ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,
|
||||
|
||||
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
|
||||
static TARGET_ATTRIBUTE("bmi2") size_t
|
||||
DONT_VECTORIZE
|
||||
ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t maxDstSize,
|
||||
const void* seqStart, size_t seqSize, int nbSeq,
|
||||
@@ -1176,7 +1191,7 @@ ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
|
||||
/* ZSTD_decompressSequencesLong() :
|
||||
* decompression function triggered when a minimum share of offsets is considered "long",
|
||||
* aka out of cache.
|
||||
* note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes mearning "farther than memory cache distance".
|
||||
* note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes meaning "farther than memory cache distance".
|
||||
* This function will try to mitigate main memory latency through the use of prefetching */
|
||||
static size_t
|
||||
ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
|
||||
@@ -1240,7 +1255,7 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN))));
|
||||
DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
|
||||
|
||||
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
|
||||
RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong);
|
||||
|
||||
/* Decode literals section */
|
||||
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
||||
|
||||
@@ -89,6 +89,12 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
|
||||
typedef enum { zdss_init=0, zdss_loadHeader,
|
||||
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
|
||||
|
||||
typedef enum {
|
||||
ZSTD_use_indefinitely = -1, /* Use the dictionary indefinitely */
|
||||
ZSTD_dont_use = 0, /* Do not use the dictionary (if one exists free it) */
|
||||
ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
|
||||
} ZSTD_dictUses_e;
|
||||
|
||||
struct ZSTD_DCtx_s
|
||||
{
|
||||
const ZSTD_seqSymbol* LLTptr;
|
||||
@@ -123,6 +129,7 @@ struct ZSTD_DCtx_s
|
||||
const ZSTD_DDict* ddict; /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */
|
||||
U32 dictID;
|
||||
int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
|
||||
ZSTD_dictUses_e dictUses;
|
||||
|
||||
/* streaming */
|
||||
ZSTD_dStreamStage streamStage;
|
||||
|
||||
+212
-56
@@ -391,7 +391,7 @@ static void COVER_group(COVER_ctx_t *ctx, const void *group,
|
||||
*
|
||||
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
|
||||
*
|
||||
* Once the dmer d is in the dictionay we set F(d) = 0.
|
||||
* Once the dmer d is in the dictionary we set F(d) = 0.
|
||||
*/
|
||||
static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs,
|
||||
COVER_map_t *activeDmers, U32 begin,
|
||||
@@ -435,7 +435,7 @@ static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs,
|
||||
U32 *delDmerOcc = COVER_map_at(activeDmers, delDmer);
|
||||
activeSegment.begin += 1;
|
||||
*delDmerOcc -= 1;
|
||||
/* If this is the last occurence of the dmer, subtract its score */
|
||||
/* If this is the last occurrence of the dmer, subtract its score */
|
||||
if (*delDmerOcc == 0) {
|
||||
COVER_map_remove(activeDmers, delDmer);
|
||||
activeSegment.score -= freqs[delDmer];
|
||||
@@ -526,10 +526,10 @@ static void COVER_ctx_destroy(COVER_ctx_t *ctx) {
|
||||
* Prepare a context for dictionary building.
|
||||
* The context is only dependent on the parameter `d` and can used multiple
|
||||
* times.
|
||||
* Returns 1 on success or zero on error.
|
||||
* Returns 0 on success or error code on error.
|
||||
* The context must be destroyed with `COVER_ctx_destroy()`.
|
||||
*/
|
||||
static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
static size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
const size_t *samplesSizes, unsigned nbSamples,
|
||||
unsigned d, double splitPoint) {
|
||||
const BYTE *const samples = (const BYTE *)samplesBuffer;
|
||||
@@ -544,17 +544,17 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
totalSamplesSize >= (size_t)COVER_MAX_SAMPLES_SIZE) {
|
||||
DISPLAYLEVEL(1, "Total samples size is too large (%u MB), maximum size is %u MB\n",
|
||||
(unsigned)(totalSamplesSize>>20), (COVER_MAX_SAMPLES_SIZE >> 20));
|
||||
return 0;
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
/* Check if there are at least 5 training samples */
|
||||
if (nbTrainSamples < 5) {
|
||||
DISPLAYLEVEL(1, "Total number of training samples is %u and is invalid.", nbTrainSamples);
|
||||
return 0;
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
/* Check if there's testing sample */
|
||||
if (nbTestSamples < 1) {
|
||||
DISPLAYLEVEL(1, "Total number of testing samples is %u and is invalid.", nbTestSamples);
|
||||
return 0;
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
/* Zero the context */
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
@@ -577,7 +577,7 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
if (!ctx->suffix || !ctx->dmerAt || !ctx->offsets) {
|
||||
DISPLAYLEVEL(1, "Failed to allocate scratch buffers\n");
|
||||
COVER_ctx_destroy(ctx);
|
||||
return 0;
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
ctx->freqs = NULL;
|
||||
ctx->d = d;
|
||||
@@ -624,7 +624,40 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
(ctx->d <= 8 ? &COVER_cmp8 : &COVER_cmp), &COVER_group);
|
||||
ctx->freqs = ctx->suffix;
|
||||
ctx->suffix = NULL;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel)
|
||||
{
|
||||
const double ratio = (double)nbDmers / maxDictSize;
|
||||
if (ratio >= 10) {
|
||||
return;
|
||||
}
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1,
|
||||
"WARNING: The maximum dictionary size %u is too large "
|
||||
"compared to the source size %u! "
|
||||
"size(source)/size(dictionary) = %f, but it should be >= "
|
||||
"10! This may lead to a subpar dictionary! We recommend "
|
||||
"training on sources at least 10x, and up to 100x the "
|
||||
"size of the dictionary!\n", (U32)maxDictSize,
|
||||
(U32)nbDmers, ratio);
|
||||
}
|
||||
|
||||
COVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize,
|
||||
U32 nbDmers, U32 k, U32 passes)
|
||||
{
|
||||
const U32 minEpochSize = k * 10;
|
||||
COVER_epoch_info_t epochs;
|
||||
epochs.num = MAX(1, maxDictSize / k / passes);
|
||||
epochs.size = nbDmers / epochs.num;
|
||||
if (epochs.size >= minEpochSize) {
|
||||
assert(epochs.size * epochs.num <= nbDmers);
|
||||
return epochs;
|
||||
}
|
||||
epochs.size = MIN(minEpochSize, nbDmers);
|
||||
epochs.num = nbDmers / epochs.size;
|
||||
assert(epochs.size * epochs.num <= nbDmers);
|
||||
return epochs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -636,28 +669,34 @@ static size_t COVER_buildDictionary(const COVER_ctx_t *ctx, U32 *freqs,
|
||||
ZDICT_cover_params_t parameters) {
|
||||
BYTE *const dict = (BYTE *)dictBuffer;
|
||||
size_t tail = dictBufferCapacity;
|
||||
/* Divide the data up into epochs of equal size.
|
||||
* We will select at least one segment from each epoch.
|
||||
*/
|
||||
const unsigned epochs = MAX(1, (U32)(dictBufferCapacity / parameters.k / 4));
|
||||
const unsigned epochSize = (U32)(ctx->suffixSize / epochs);
|
||||
/* Divide the data into epochs. We will select one segment from each epoch. */
|
||||
const COVER_epoch_info_t epochs = COVER_computeEpochs(
|
||||
(U32)dictBufferCapacity, (U32)ctx->suffixSize, parameters.k, 4);
|
||||
const size_t maxZeroScoreRun = MAX(10, MIN(100, epochs.num >> 3));
|
||||
size_t zeroScoreRun = 0;
|
||||
size_t epoch;
|
||||
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
|
||||
epochs, epochSize);
|
||||
(U32)epochs.num, (U32)epochs.size);
|
||||
/* Loop through the epochs until there are no more segments or the dictionary
|
||||
* is full.
|
||||
*/
|
||||
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs) {
|
||||
const U32 epochBegin = (U32)(epoch * epochSize);
|
||||
const U32 epochEnd = epochBegin + epochSize;
|
||||
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) {
|
||||
const U32 epochBegin = (U32)(epoch * epochs.size);
|
||||
const U32 epochEnd = epochBegin + epochs.size;
|
||||
size_t segmentSize;
|
||||
/* Select a segment */
|
||||
COVER_segment_t segment = COVER_selectSegment(
|
||||
ctx, freqs, activeDmers, epochBegin, epochEnd, parameters);
|
||||
/* If the segment covers no dmers, then we are out of content */
|
||||
/* If the segment covers no dmers, then we are out of content.
|
||||
* There may be new content in other epochs, for continue for some time.
|
||||
*/
|
||||
if (segment.score == 0) {
|
||||
break;
|
||||
if (++zeroScoreRun >= maxZeroScoreRun) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
zeroScoreRun = 0;
|
||||
/* Trim the segment if necessary and if it is too small then we are done */
|
||||
segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);
|
||||
if (segmentSize < parameters.d) {
|
||||
@@ -690,11 +729,11 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_cover(
|
||||
/* Checks */
|
||||
if (!COVER_checkParameters(parameters, dictBufferCapacity)) {
|
||||
DISPLAYLEVEL(1, "Cover parameters incorrect\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(parameter_outOfBound);
|
||||
}
|
||||
if (nbSamples == 0) {
|
||||
DISPLAYLEVEL(1, "Cover must have at least one input file\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {
|
||||
DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n",
|
||||
@@ -702,14 +741,18 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_cover(
|
||||
return ERROR(dstSize_tooSmall);
|
||||
}
|
||||
/* Initialize context and activeDmers */
|
||||
if (!COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples,
|
||||
parameters.d, parameters.splitPoint)) {
|
||||
return ERROR(GENERIC);
|
||||
{
|
||||
size_t const initVal = COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples,
|
||||
parameters.d, parameters.splitPoint);
|
||||
if (ZSTD_isError(initVal)) {
|
||||
return initVal;
|
||||
}
|
||||
}
|
||||
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, g_displayLevel);
|
||||
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
|
||||
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
|
||||
COVER_ctx_destroy(&ctx);
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(2, "Building dictionary\n");
|
||||
@@ -770,7 +813,7 @@ size_t COVER_checkTotalCompressedSize(const ZDICT_cover_params_t parameters,
|
||||
cctx, dst, dstCapacity, samples + offsets[i],
|
||||
samplesSizes[i], cdict);
|
||||
if (ZSTD_isError(size)) {
|
||||
totalCompressedSize = ERROR(GENERIC);
|
||||
totalCompressedSize = size;
|
||||
goto _compressCleanup;
|
||||
}
|
||||
totalCompressedSize += size;
|
||||
@@ -846,9 +889,11 @@ void COVER_best_start(COVER_best_t *best) {
|
||||
* Decrements liveJobs and signals any waiting threads if liveJobs == 0.
|
||||
* If this dictionary is the best so far save it and its parameters.
|
||||
*/
|
||||
void COVER_best_finish(COVER_best_t *best, size_t compressedSize,
|
||||
ZDICT_cover_params_t parameters, void *dict,
|
||||
size_t dictSize) {
|
||||
void COVER_best_finish(COVER_best_t *best, ZDICT_cover_params_t parameters,
|
||||
COVER_dictSelection_t selection) {
|
||||
void* dict = selection.dictContent;
|
||||
size_t compressedSize = selection.totalCompressedSize;
|
||||
size_t dictSize = selection.dictSize;
|
||||
if (!best) {
|
||||
return;
|
||||
}
|
||||
@@ -874,6 +919,9 @@ void COVER_best_finish(COVER_best_t *best, size_t compressedSize,
|
||||
}
|
||||
}
|
||||
/* Save the dictionary, parameters, and size */
|
||||
if (!dict) {
|
||||
return;
|
||||
}
|
||||
memcpy(best->dict, dict, dictSize);
|
||||
best->dictSize = dictSize;
|
||||
best->parameters = parameters;
|
||||
@@ -886,6 +934,111 @@ void COVER_best_finish(COVER_best_t *best, size_t compressedSize,
|
||||
}
|
||||
}
|
||||
|
||||
COVER_dictSelection_t COVER_dictSelectionError(size_t error) {
|
||||
COVER_dictSelection_t selection = { NULL, 0, error };
|
||||
return selection;
|
||||
}
|
||||
|
||||
unsigned COVER_dictSelectionIsError(COVER_dictSelection_t selection) {
|
||||
return (ZSTD_isError(selection.totalCompressedSize) || !selection.dictContent);
|
||||
}
|
||||
|
||||
void COVER_dictSelectionFree(COVER_dictSelection_t selection){
|
||||
free(selection.dictContent);
|
||||
}
|
||||
|
||||
COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent,
|
||||
size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples,
|
||||
size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize) {
|
||||
|
||||
size_t largestDict = 0;
|
||||
size_t largestCompressed = 0;
|
||||
BYTE* customDictContentEnd = customDictContent + dictContentSize;
|
||||
|
||||
BYTE * largestDictbuffer = (BYTE *)malloc(dictContentSize);
|
||||
BYTE * candidateDictBuffer = (BYTE *)malloc(dictContentSize);
|
||||
double regressionTolerance = ((double)params.shrinkDictMaxRegression / 100.0) + 1.00;
|
||||
|
||||
if (!largestDictbuffer || !candidateDictBuffer) {
|
||||
free(largestDictbuffer);
|
||||
free(candidateDictBuffer);
|
||||
return COVER_dictSelectionError(dictContentSize);
|
||||
}
|
||||
|
||||
/* Initial dictionary size and compressed size */
|
||||
memcpy(largestDictbuffer, customDictContent, dictContentSize);
|
||||
dictContentSize = ZDICT_finalizeDictionary(
|
||||
largestDictbuffer, dictContentSize, customDictContent, dictContentSize,
|
||||
samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams);
|
||||
|
||||
if (ZDICT_isError(dictContentSize)) {
|
||||
free(largestDictbuffer);
|
||||
free(candidateDictBuffer);
|
||||
return COVER_dictSelectionError(dictContentSize);
|
||||
}
|
||||
|
||||
totalCompressedSize = COVER_checkTotalCompressedSize(params, samplesSizes,
|
||||
samplesBuffer, offsets,
|
||||
nbCheckSamples, nbSamples,
|
||||
largestDictbuffer, dictContentSize);
|
||||
|
||||
if (ZSTD_isError(totalCompressedSize)) {
|
||||
free(largestDictbuffer);
|
||||
free(candidateDictBuffer);
|
||||
return COVER_dictSelectionError(totalCompressedSize);
|
||||
}
|
||||
|
||||
if (params.shrinkDict == 0) {
|
||||
COVER_dictSelection_t selection = { largestDictbuffer, dictContentSize, totalCompressedSize };
|
||||
free(candidateDictBuffer);
|
||||
return selection;
|
||||
}
|
||||
|
||||
largestDict = dictContentSize;
|
||||
largestCompressed = totalCompressedSize;
|
||||
dictContentSize = ZDICT_DICTSIZE_MIN;
|
||||
|
||||
/* Largest dict is initially at least ZDICT_DICTSIZE_MIN */
|
||||
while (dictContentSize < largestDict) {
|
||||
memcpy(candidateDictBuffer, largestDictbuffer, largestDict);
|
||||
dictContentSize = ZDICT_finalizeDictionary(
|
||||
candidateDictBuffer, dictContentSize, customDictContentEnd - dictContentSize, dictContentSize,
|
||||
samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams);
|
||||
|
||||
if (ZDICT_isError(dictContentSize)) {
|
||||
free(largestDictbuffer);
|
||||
free(candidateDictBuffer);
|
||||
return COVER_dictSelectionError(dictContentSize);
|
||||
|
||||
}
|
||||
|
||||
totalCompressedSize = COVER_checkTotalCompressedSize(params, samplesSizes,
|
||||
samplesBuffer, offsets,
|
||||
nbCheckSamples, nbSamples,
|
||||
candidateDictBuffer, dictContentSize);
|
||||
|
||||
if (ZSTD_isError(totalCompressedSize)) {
|
||||
free(largestDictbuffer);
|
||||
free(candidateDictBuffer);
|
||||
return COVER_dictSelectionError(totalCompressedSize);
|
||||
}
|
||||
|
||||
if (totalCompressedSize <= largestCompressed * regressionTolerance) {
|
||||
COVER_dictSelection_t selection = { candidateDictBuffer, dictContentSize, totalCompressedSize };
|
||||
free(largestDictbuffer);
|
||||
return selection;
|
||||
}
|
||||
dictContentSize *= 2;
|
||||
}
|
||||
dictContentSize = largestDict;
|
||||
totalCompressedSize = largestCompressed;
|
||||
{
|
||||
COVER_dictSelection_t selection = { largestDictbuffer, dictContentSize, totalCompressedSize };
|
||||
free(candidateDictBuffer);
|
||||
return selection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for COVER_tryParameters().
|
||||
*/
|
||||
@@ -911,6 +1064,7 @@ static void COVER_tryParameters(void *opaque) {
|
||||
/* Allocate space for hash table, dict, and freqs */
|
||||
COVER_map_t activeDmers;
|
||||
BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity);
|
||||
COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC));
|
||||
U32 *freqs = (U32 *)malloc(ctx->suffixSize * sizeof(U32));
|
||||
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
|
||||
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
|
||||
@@ -926,29 +1080,21 @@ static void COVER_tryParameters(void *opaque) {
|
||||
{
|
||||
const size_t tail = COVER_buildDictionary(ctx, freqs, &activeDmers, dict,
|
||||
dictBufferCapacity, parameters);
|
||||
dictBufferCapacity = ZDICT_finalizeDictionary(
|
||||
dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail,
|
||||
ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbTrainSamples,
|
||||
parameters.zParams);
|
||||
if (ZDICT_isError(dictBufferCapacity)) {
|
||||
DISPLAYLEVEL(1, "Failed to finalize dictionary\n");
|
||||
selection = COVER_selectDict(dict + tail, dictBufferCapacity - tail,
|
||||
ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbTrainSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets,
|
||||
totalCompressedSize);
|
||||
|
||||
if (COVER_dictSelectionIsError(selection)) {
|
||||
DISPLAYLEVEL(1, "Failed to select dictionary\n");
|
||||
goto _cleanup;
|
||||
}
|
||||
}
|
||||
/* Check total compressed size */
|
||||
totalCompressedSize = COVER_checkTotalCompressedSize(parameters, ctx->samplesSizes,
|
||||
ctx->samples, ctx->offsets,
|
||||
ctx->nbTrainSamples, ctx->nbSamples,
|
||||
dict, dictBufferCapacity);
|
||||
|
||||
_cleanup:
|
||||
COVER_best_finish(data->best, totalCompressedSize, parameters, dict,
|
||||
dictBufferCapacity);
|
||||
free(dict);
|
||||
COVER_best_finish(data->best, parameters, selection);
|
||||
free(data);
|
||||
COVER_map_destroy(&activeDmers);
|
||||
if (dict) {
|
||||
free(dict);
|
||||
}
|
||||
COVER_dictSelectionFree(selection);
|
||||
if (freqs) {
|
||||
free(freqs);
|
||||
}
|
||||
@@ -970,6 +1116,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1);
|
||||
const unsigned kIterations =
|
||||
(1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize);
|
||||
const unsigned shrinkDict = 0;
|
||||
/* Local variables */
|
||||
const int displayLevel = parameters->zParams.notificationLevel;
|
||||
unsigned iteration = 1;
|
||||
@@ -977,19 +1124,20 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
unsigned k;
|
||||
COVER_best_t best;
|
||||
POOL_ctx *pool = NULL;
|
||||
int warned = 0;
|
||||
|
||||
/* Checks */
|
||||
if (splitPoint <= 0 || splitPoint > 1) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect parameters\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(parameter_outOfBound);
|
||||
}
|
||||
if (kMinK < kMaxD || kMaxK < kMinK) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect parameters\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(parameter_outOfBound);
|
||||
}
|
||||
if (nbSamples == 0) {
|
||||
DISPLAYLEVEL(1, "Cover must have at least one input file\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {
|
||||
DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n",
|
||||
@@ -1013,11 +1161,18 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
/* Initialize the context for this value of d */
|
||||
COVER_ctx_t ctx;
|
||||
LOCALDISPLAYLEVEL(displayLevel, 3, "d=%u\n", d);
|
||||
if (!COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint)) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n");
|
||||
COVER_best_destroy(&best);
|
||||
POOL_free(pool);
|
||||
return ERROR(GENERIC);
|
||||
{
|
||||
const size_t initVal = COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint);
|
||||
if (ZSTD_isError(initVal)) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n");
|
||||
COVER_best_destroy(&best);
|
||||
POOL_free(pool);
|
||||
return initVal;
|
||||
}
|
||||
}
|
||||
if (!warned) {
|
||||
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, displayLevel);
|
||||
warned = 1;
|
||||
}
|
||||
/* Loop through k reusing the same context */
|
||||
for (k = kMinK; k <= kMaxK; k += kStepSize) {
|
||||
@@ -1030,7 +1185,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
COVER_best_destroy(&best);
|
||||
COVER_ctx_destroy(&ctx);
|
||||
POOL_free(pool);
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
data->ctx = &ctx;
|
||||
data->best = &best;
|
||||
@@ -1040,6 +1195,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
data->parameters.d = d;
|
||||
data->parameters.splitPoint = splitPoint;
|
||||
data->parameters.steps = kSteps;
|
||||
data->parameters.shrinkDict = shrinkDict;
|
||||
data->parameters.zParams.notificationLevel = g_displayLevel;
|
||||
/* Check the parameters */
|
||||
if (!COVER_checkParameters(data->parameters, dictBufferCapacity)) {
|
||||
|
||||
+67
-3
@@ -38,6 +38,44 @@ typedef struct {
|
||||
U32 score;
|
||||
} COVER_segment_t;
|
||||
|
||||
/**
|
||||
*Number of epochs and size of each epoch.
|
||||
*/
|
||||
typedef struct {
|
||||
U32 num;
|
||||
U32 size;
|
||||
} COVER_epoch_info_t;
|
||||
|
||||
/**
|
||||
* Struct used for the dictionary selection function.
|
||||
*/
|
||||
typedef struct COVER_dictSelection {
|
||||
BYTE* dictContent;
|
||||
size_t dictSize;
|
||||
size_t totalCompressedSize;
|
||||
} COVER_dictSelection_t;
|
||||
|
||||
/**
|
||||
* Computes the number of epochs and the size of each epoch.
|
||||
* We will make sure that each epoch gets at least 10 * k bytes.
|
||||
*
|
||||
* The COVER algorithms divide the data up into epochs of equal size and
|
||||
* select one segment from each epoch.
|
||||
*
|
||||
* @param maxDictSize The maximum allowed dictionary size.
|
||||
* @param nbDmers The number of dmers we are training on.
|
||||
* @param k The parameter k (segment size).
|
||||
* @param passes The target number of passes over the dmer corpus.
|
||||
* More passes means a better dictionary.
|
||||
*/
|
||||
COVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize, U32 nbDmers,
|
||||
U32 k, U32 passes);
|
||||
|
||||
/**
|
||||
* Warns the user when their corpus is too small.
|
||||
*/
|
||||
void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel);
|
||||
|
||||
/**
|
||||
* Checks total compressed size of a dictionary
|
||||
*/
|
||||
@@ -78,6 +116,32 @@ void COVER_best_start(COVER_best_t *best);
|
||||
* Decrements liveJobs and signals any waiting threads if liveJobs == 0.
|
||||
* If this dictionary is the best so far save it and its parameters.
|
||||
*/
|
||||
void COVER_best_finish(COVER_best_t *best, size_t compressedSize,
|
||||
ZDICT_cover_params_t parameters, void *dict,
|
||||
size_t dictSize);
|
||||
void COVER_best_finish(COVER_best_t *best, ZDICT_cover_params_t parameters,
|
||||
COVER_dictSelection_t selection);
|
||||
/**
|
||||
* Error function for COVER_selectDict function. Checks if the return
|
||||
* value is an error.
|
||||
*/
|
||||
unsigned COVER_dictSelectionIsError(COVER_dictSelection_t selection);
|
||||
|
||||
/**
|
||||
* Error function for COVER_selectDict function. Returns a struct where
|
||||
* return.totalCompressedSize is a ZSTD error.
|
||||
*/
|
||||
COVER_dictSelection_t COVER_dictSelectionError(size_t error);
|
||||
|
||||
/**
|
||||
* Always call after selectDict is called to free up used memory from
|
||||
* newly created dictionary.
|
||||
*/
|
||||
void COVER_dictSelectionFree(COVER_dictSelection_t selection);
|
||||
|
||||
/**
|
||||
* Called to finalize the dictionary and select one based on whether or not
|
||||
* the shrink-dict flag was enabled. If enabled the dictionary used is the
|
||||
* smallest dictionary within a specified regression of the compressed size
|
||||
* from the largest dictionary.
|
||||
*/
|
||||
COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent,
|
||||
size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples,
|
||||
size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize);
|
||||
|
||||
+71
-52
@@ -132,7 +132,7 @@ typedef struct {
|
||||
*
|
||||
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
|
||||
*
|
||||
* Once the dmer with hash value d is in the dictionay we set F(d) = 0.
|
||||
* Once the dmer with hash value d is in the dictionary we set F(d) = 0.
|
||||
*/
|
||||
static COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
||||
U32 *freqs, U32 begin, U32 end,
|
||||
@@ -161,7 +161,7 @@ static COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
||||
/* Get hash value of current dmer */
|
||||
const size_t idx = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, f, d);
|
||||
|
||||
/* Add frequency of this index to score if this is the first occurence of index in active segment */
|
||||
/* Add frequency of this index to score if this is the first occurrence of index in active segment */
|
||||
if (segmentFreqs[idx] == 0) {
|
||||
activeSegment.score += freqs[idx];
|
||||
}
|
||||
@@ -287,10 +287,10 @@ FASTCOVER_computeFrequency(U32* freqs, const FASTCOVER_ctx_t* ctx)
|
||||
* Prepare a context for dictionary building.
|
||||
* The context is only dependent on the parameter `d` and can used multiple
|
||||
* times.
|
||||
* Returns 1 on success or zero on error.
|
||||
* Returns 0 on success or error code on error.
|
||||
* The context must be destroyed with `FASTCOVER_ctx_destroy()`.
|
||||
*/
|
||||
static int
|
||||
static size_t
|
||||
FASTCOVER_ctx_init(FASTCOVER_ctx_t* ctx,
|
||||
const void* samplesBuffer,
|
||||
const size_t* samplesSizes, unsigned nbSamples,
|
||||
@@ -310,19 +310,19 @@ FASTCOVER_ctx_init(FASTCOVER_ctx_t* ctx,
|
||||
totalSamplesSize >= (size_t)FASTCOVER_MAX_SAMPLES_SIZE) {
|
||||
DISPLAYLEVEL(1, "Total samples size is too large (%u MB), maximum size is %u MB\n",
|
||||
(unsigned)(totalSamplesSize >> 20), (FASTCOVER_MAX_SAMPLES_SIZE >> 20));
|
||||
return 0;
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
|
||||
/* Check if there are at least 5 training samples */
|
||||
if (nbTrainSamples < 5) {
|
||||
DISPLAYLEVEL(1, "Total number of training samples is %u and is invalid\n", nbTrainSamples);
|
||||
return 0;
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
|
||||
/* Check if there's testing sample */
|
||||
if (nbTestSamples < 1) {
|
||||
DISPLAYLEVEL(1, "Total number of testing samples is %u and is invalid.\n", nbTestSamples);
|
||||
return 0;
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
|
||||
/* Zero the context */
|
||||
@@ -347,7 +347,7 @@ FASTCOVER_ctx_init(FASTCOVER_ctx_t* ctx,
|
||||
if (ctx->offsets == NULL) {
|
||||
DISPLAYLEVEL(1, "Failed to allocate scratch buffers \n");
|
||||
FASTCOVER_ctx_destroy(ctx);
|
||||
return 0;
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
|
||||
/* Fill offsets from the samplesSizes */
|
||||
@@ -364,13 +364,13 @@ FASTCOVER_ctx_init(FASTCOVER_ctx_t* ctx,
|
||||
if (ctx->freqs == NULL) {
|
||||
DISPLAYLEVEL(1, "Failed to allocate frequency table \n");
|
||||
FASTCOVER_ctx_destroy(ctx);
|
||||
return 0;
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(2, "Computing frequencies\n");
|
||||
FASTCOVER_computeFrequency(ctx->freqs, ctx);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -386,29 +386,35 @@ FASTCOVER_buildDictionary(const FASTCOVER_ctx_t* ctx,
|
||||
{
|
||||
BYTE *const dict = (BYTE *)dictBuffer;
|
||||
size_t tail = dictBufferCapacity;
|
||||
/* Divide the data up into epochs of equal size.
|
||||
* We will select at least one segment from each epoch.
|
||||
*/
|
||||
const unsigned epochs = MAX(1, (U32)(dictBufferCapacity / parameters.k));
|
||||
const unsigned epochSize = (U32)(ctx->nbDmers / epochs);
|
||||
/* Divide the data into epochs. We will select one segment from each epoch. */
|
||||
const COVER_epoch_info_t epochs = COVER_computeEpochs(
|
||||
(U32)dictBufferCapacity, (U32)ctx->nbDmers, parameters.k, 1);
|
||||
const size_t maxZeroScoreRun = 10;
|
||||
size_t zeroScoreRun = 0;
|
||||
size_t epoch;
|
||||
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
|
||||
epochs, epochSize);
|
||||
(U32)epochs.num, (U32)epochs.size);
|
||||
/* Loop through the epochs until there are no more segments or the dictionary
|
||||
* is full.
|
||||
*/
|
||||
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs) {
|
||||
const U32 epochBegin = (U32)(epoch * epochSize);
|
||||
const U32 epochEnd = epochBegin + epochSize;
|
||||
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) {
|
||||
const U32 epochBegin = (U32)(epoch * epochs.size);
|
||||
const U32 epochEnd = epochBegin + epochs.size;
|
||||
size_t segmentSize;
|
||||
/* Select a segment */
|
||||
COVER_segment_t segment = FASTCOVER_selectSegment(
|
||||
ctx, freqs, epochBegin, epochEnd, parameters, segmentFreqs);
|
||||
|
||||
/* If the segment covers no dmers, then we are out of content */
|
||||
/* If the segment covers no dmers, then we are out of content.
|
||||
* There may be new content in other epochs, for continue for some time.
|
||||
*/
|
||||
if (segment.score == 0) {
|
||||
break;
|
||||
if (++zeroScoreRun >= maxZeroScoreRun) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
zeroScoreRun = 0;
|
||||
|
||||
/* Trim the segment if necessary and if it is too small then we are done */
|
||||
segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);
|
||||
@@ -429,7 +435,6 @@ FASTCOVER_buildDictionary(const FASTCOVER_ctx_t* ctx,
|
||||
return tail;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parameters for FASTCOVER_tryParameters().
|
||||
*/
|
||||
@@ -458,6 +463,7 @@ static void FASTCOVER_tryParameters(void *opaque)
|
||||
U16* segmentFreqs = (U16 *)calloc(((U64)1 << ctx->f), sizeof(U16));
|
||||
/* Allocate space for hash table, dict, and freqs */
|
||||
BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity);
|
||||
COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC));
|
||||
U32 *freqs = (U32*) malloc(((U64)1 << ctx->f) * sizeof(U32));
|
||||
if (!segmentFreqs || !dict || !freqs) {
|
||||
DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n");
|
||||
@@ -467,27 +473,24 @@ static void FASTCOVER_tryParameters(void *opaque)
|
||||
memcpy(freqs, ctx->freqs, ((U64)1 << ctx->f) * sizeof(U32));
|
||||
/* Build the dictionary */
|
||||
{ const size_t tail = FASTCOVER_buildDictionary(ctx, freqs, dict, dictBufferCapacity,
|
||||
parameters, segmentFreqs);
|
||||
parameters, segmentFreqs);
|
||||
|
||||
const unsigned nbFinalizeSamples = (unsigned)(ctx->nbTrainSamples * ctx->accelParams.finalize / 100);
|
||||
dictBufferCapacity = ZDICT_finalizeDictionary(
|
||||
dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail,
|
||||
ctx->samples, ctx->samplesSizes, nbFinalizeSamples, parameters.zParams);
|
||||
if (ZDICT_isError(dictBufferCapacity)) {
|
||||
DISPLAYLEVEL(1, "Failed to finalize dictionary\n");
|
||||
selection = COVER_selectDict(dict + tail, dictBufferCapacity - tail,
|
||||
ctx->samples, ctx->samplesSizes, nbFinalizeSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets,
|
||||
totalCompressedSize);
|
||||
|
||||
if (COVER_dictSelectionIsError(selection)) {
|
||||
DISPLAYLEVEL(1, "Failed to select dictionary\n");
|
||||
goto _cleanup;
|
||||
}
|
||||
}
|
||||
/* Check total compressed size */
|
||||
totalCompressedSize = COVER_checkTotalCompressedSize(parameters, ctx->samplesSizes,
|
||||
ctx->samples, ctx->offsets,
|
||||
ctx->nbTrainSamples, ctx->nbSamples,
|
||||
dict, dictBufferCapacity);
|
||||
_cleanup:
|
||||
COVER_best_finish(data->best, totalCompressedSize, parameters, dict,
|
||||
dictBufferCapacity);
|
||||
free(dict);
|
||||
COVER_best_finish(data->best, parameters, selection);
|
||||
free(data);
|
||||
free(segmentFreqs);
|
||||
free(dict);
|
||||
COVER_dictSelectionFree(selection);
|
||||
free(freqs);
|
||||
}
|
||||
|
||||
@@ -502,6 +505,7 @@ FASTCOVER_convertToCoverParams(ZDICT_fastCover_params_t fastCoverParams,
|
||||
coverParams->nbThreads = fastCoverParams.nbThreads;
|
||||
coverParams->splitPoint = fastCoverParams.splitPoint;
|
||||
coverParams->zParams = fastCoverParams.zParams;
|
||||
coverParams->shrinkDict = fastCoverParams.shrinkDict;
|
||||
}
|
||||
|
||||
|
||||
@@ -518,6 +522,7 @@ FASTCOVER_convertToFastCoverParams(ZDICT_cover_params_t coverParams,
|
||||
fastCoverParams->f = f;
|
||||
fastCoverParams->accel = accel;
|
||||
fastCoverParams->zParams = coverParams.zParams;
|
||||
fastCoverParams->shrinkDict = coverParams.shrinkDict;
|
||||
}
|
||||
|
||||
|
||||
@@ -544,11 +549,11 @@ ZDICT_trainFromBuffer_fastCover(void* dictBuffer, size_t dictBufferCapacity,
|
||||
if (!FASTCOVER_checkParameters(coverParams, dictBufferCapacity, parameters.f,
|
||||
parameters.accel)) {
|
||||
DISPLAYLEVEL(1, "FASTCOVER parameters incorrect\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(parameter_outOfBound);
|
||||
}
|
||||
if (nbSamples == 0) {
|
||||
DISPLAYLEVEL(1, "FASTCOVER must have at least one input file\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {
|
||||
DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n",
|
||||
@@ -558,12 +563,16 @@ ZDICT_trainFromBuffer_fastCover(void* dictBuffer, size_t dictBufferCapacity,
|
||||
/* Assign corresponding FASTCOVER_accel_t to accelParams*/
|
||||
accelParams = FASTCOVER_defaultAccelParameters[parameters.accel];
|
||||
/* Initialize context */
|
||||
if (!FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples,
|
||||
{
|
||||
size_t const initVal = FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples,
|
||||
coverParams.d, parameters.splitPoint, parameters.f,
|
||||
accelParams)) {
|
||||
DISPLAYLEVEL(1, "Failed to initialize context\n");
|
||||
return ERROR(GENERIC);
|
||||
accelParams);
|
||||
if (ZSTD_isError(initVal)) {
|
||||
DISPLAYLEVEL(1, "Failed to initialize context\n");
|
||||
return initVal;
|
||||
}
|
||||
}
|
||||
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, g_displayLevel);
|
||||
/* Build the dictionary */
|
||||
DISPLAYLEVEL(2, "Building dictionary\n");
|
||||
{
|
||||
@@ -609,6 +618,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
|
||||
(1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize);
|
||||
const unsigned f = parameters->f == 0 ? DEFAULT_F : parameters->f;
|
||||
const unsigned accel = parameters->accel == 0 ? DEFAULT_ACCEL : parameters->accel;
|
||||
const unsigned shrinkDict = 0;
|
||||
/* Local variables */
|
||||
const int displayLevel = parameters->zParams.notificationLevel;
|
||||
unsigned iteration = 1;
|
||||
@@ -616,22 +626,23 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
|
||||
unsigned k;
|
||||
COVER_best_t best;
|
||||
POOL_ctx *pool = NULL;
|
||||
int warned = 0;
|
||||
/* Checks */
|
||||
if (splitPoint <= 0 || splitPoint > 1) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect splitPoint\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(parameter_outOfBound);
|
||||
}
|
||||
if (accel == 0 || accel > FASTCOVER_MAX_ACCEL) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect accel\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(parameter_outOfBound);
|
||||
}
|
||||
if (kMinK < kMaxD || kMaxK < kMinK) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect k\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(parameter_outOfBound);
|
||||
}
|
||||
if (nbSamples == 0) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "FASTCOVER must have at least one input file\n");
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "dictBufferCapacity must be at least %u\n",
|
||||
@@ -658,11 +669,18 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
|
||||
/* Initialize the context for this value of d */
|
||||
FASTCOVER_ctx_t ctx;
|
||||
LOCALDISPLAYLEVEL(displayLevel, 3, "d=%u\n", d);
|
||||
if (!FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint, f, accelParams)) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n");
|
||||
COVER_best_destroy(&best);
|
||||
POOL_free(pool);
|
||||
return ERROR(GENERIC);
|
||||
{
|
||||
size_t const initVal = FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint, f, accelParams);
|
||||
if (ZSTD_isError(initVal)) {
|
||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n");
|
||||
COVER_best_destroy(&best);
|
||||
POOL_free(pool);
|
||||
return initVal;
|
||||
}
|
||||
}
|
||||
if (!warned) {
|
||||
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, displayLevel);
|
||||
warned = 1;
|
||||
}
|
||||
/* Loop through k reusing the same context */
|
||||
for (k = kMinK; k <= kMaxK; k += kStepSize) {
|
||||
@@ -675,7 +693,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
|
||||
COVER_best_destroy(&best);
|
||||
FASTCOVER_ctx_destroy(&ctx);
|
||||
POOL_free(pool);
|
||||
return ERROR(GENERIC);
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
data->ctx = &ctx;
|
||||
data->best = &best;
|
||||
@@ -685,6 +703,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
|
||||
data->parameters.d = d;
|
||||
data->parameters.splitPoint = splitPoint;
|
||||
data->parameters.steps = kSteps;
|
||||
data->parameters.shrinkDict = shrinkDict;
|
||||
data->parameters.zParams.notificationLevel = g_displayLevel;
|
||||
/* Check the parameters */
|
||||
if (!FASTCOVER_checkParameters(data->parameters, dictBufferCapacity,
|
||||
|
||||
@@ -741,7 +741,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
/* analyze, build stats, starting with literals */
|
||||
{ size_t maxNbBits = HUF_buildCTable (hufTable, countLit, 255, huffLog);
|
||||
if (HUF_isError(maxNbBits)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
eSize = maxNbBits;
|
||||
DISPLAYLEVEL(1, " HUF_buildCTable error \n");
|
||||
goto _cleanup;
|
||||
}
|
||||
@@ -764,7 +764,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
total=0; for (u=0; u<=offcodeMax; u++) total+=offcodeCount[u];
|
||||
errorCode = FSE_normalizeCount(offcodeNCount, Offlog, offcodeCount, total, offcodeMax);
|
||||
if (FSE_isError(errorCode)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
eSize = errorCode;
|
||||
DISPLAYLEVEL(1, "FSE_normalizeCount error with offcodeCount \n");
|
||||
goto _cleanup;
|
||||
}
|
||||
@@ -773,7 +773,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
total=0; for (u=0; u<=MaxML; u++) total+=matchLengthCount[u];
|
||||
errorCode = FSE_normalizeCount(matchLengthNCount, mlLog, matchLengthCount, total, MaxML);
|
||||
if (FSE_isError(errorCode)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
eSize = errorCode;
|
||||
DISPLAYLEVEL(1, "FSE_normalizeCount error with matchLengthCount \n");
|
||||
goto _cleanup;
|
||||
}
|
||||
@@ -782,7 +782,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
total=0; for (u=0; u<=MaxLL; u++) total+=litLengthCount[u];
|
||||
errorCode = FSE_normalizeCount(litLengthNCount, llLog, litLengthCount, total, MaxLL);
|
||||
if (FSE_isError(errorCode)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
eSize = errorCode;
|
||||
DISPLAYLEVEL(1, "FSE_normalizeCount error with litLengthCount \n");
|
||||
goto _cleanup;
|
||||
}
|
||||
@@ -791,7 +791,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
/* write result to buffer */
|
||||
{ size_t const hhSize = HUF_writeCTable(dstPtr, maxDstSize, hufTable, 255, huffLog);
|
||||
if (HUF_isError(hhSize)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
eSize = hhSize;
|
||||
DISPLAYLEVEL(1, "HUF_writeCTable error \n");
|
||||
goto _cleanup;
|
||||
}
|
||||
@@ -802,7 +802,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
|
||||
{ size_t const ohSize = FSE_writeNCount(dstPtr, maxDstSize, offcodeNCount, OFFCODE_MAX, Offlog);
|
||||
if (FSE_isError(ohSize)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
eSize = ohSize;
|
||||
DISPLAYLEVEL(1, "FSE_writeNCount error with offcodeNCount \n");
|
||||
goto _cleanup;
|
||||
}
|
||||
@@ -813,7 +813,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
|
||||
{ size_t const mhSize = FSE_writeNCount(dstPtr, maxDstSize, matchLengthNCount, MaxML, mlLog);
|
||||
if (FSE_isError(mhSize)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
eSize = mhSize;
|
||||
DISPLAYLEVEL(1, "FSE_writeNCount error with matchLengthNCount \n");
|
||||
goto _cleanup;
|
||||
}
|
||||
@@ -824,7 +824,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
|
||||
{ size_t const lhSize = FSE_writeNCount(dstPtr, maxDstSize, litLengthNCount, MaxLL, llLog);
|
||||
if (FSE_isError(lhSize)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
eSize = lhSize;
|
||||
DISPLAYLEVEL(1, "FSE_writeNCount error with litlengthNCount \n");
|
||||
goto _cleanup;
|
||||
}
|
||||
@@ -834,7 +834,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
}
|
||||
|
||||
if (maxDstSize<12) {
|
||||
eSize = ERROR(GENERIC);
|
||||
eSize = ERROR(dstSize_tooSmall);
|
||||
DISPLAYLEVEL(1, "not enough space to write RepOffsets \n");
|
||||
goto _cleanup;
|
||||
}
|
||||
|
||||
+23
-8
@@ -46,7 +46,12 @@ extern "C" {
|
||||
* The resulting dictionary will be saved into `dictBuffer`.
|
||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||
* or an error code, which can be tested with ZDICT_isError().
|
||||
* Note: ZDICT_trainFromBuffer() requires about 9 bytes of memory for each input byte.
|
||||
* Note: Dictionary training will fail if there are not enough samples to construct a
|
||||
* dictionary, or if most of the samples are too small (< 8 bytes being the lower limit).
|
||||
* If dictionary training fails, you should use zstd without a dictionary, as the dictionary
|
||||
* would've been ineffective anyways. If you believe your samples would benefit from a dictionary
|
||||
* please open an issue with details, and we can look into it.
|
||||
* Note: ZDICT_trainFromBuffer()'s memory usage is about 6 MB.
|
||||
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
||||
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
||||
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
||||
@@ -89,6 +94,8 @@ typedef struct {
|
||||
unsigned steps; /* Number of steps : Only used for optimization : 0 means default (40) : Higher means more parameters checked */
|
||||
unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */
|
||||
double splitPoint; /* Percentage of samples used for training: Only used for optimization : the first nbSamples * splitPoint samples will be used to training, the last nbSamples * (1 - splitPoint) samples will be used for testing, 0 means default (1.0), 1.0 when all samples are used for both training and testing */
|
||||
unsigned shrinkDict; /* Train dictionaries to shrink in size starting from the minimum size and selects the smallest dictionary that is shrinkDictMaxRegression% worse than the largest dictionary. 0 means no shrinking and 1 means shrinking */
|
||||
unsigned shrinkDictMaxRegression; /* Sets shrinkDictMaxRegression so that a smaller dictionary can be at worse shrinkDictMaxRegression% worse than the max dict size dictionary. */
|
||||
ZDICT_params_t zParams;
|
||||
} ZDICT_cover_params_t;
|
||||
|
||||
@@ -100,6 +107,9 @@ typedef struct {
|
||||
unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */
|
||||
double splitPoint; /* Percentage of samples used for training: Only used for optimization : the first nbSamples * splitPoint samples will be used to training, the last nbSamples * (1 - splitPoint) samples will be used for testing, 0 means default (0.75), 1.0 when all samples are used for both training and testing */
|
||||
unsigned accel; /* Acceleration level: constraint: 0 < accel <= 10, higher means faster and less accurate, 0 means default(1) */
|
||||
unsigned shrinkDict; /* Train dictionaries to shrink in size starting from the minimum size and selects the smallest dictionary that is shrinkDictMaxRegression% worse than the largest dictionary. 0 means no shrinking and 1 means shrinking */
|
||||
unsigned shrinkDictMaxRegression; /* Sets shrinkDictMaxRegression so that a smaller dictionary can be at worse shrinkDictMaxRegression% worse than the max dict size dictionary. */
|
||||
|
||||
ZDICT_params_t zParams;
|
||||
} ZDICT_fastCover_params_t;
|
||||
|
||||
@@ -110,6 +120,7 @@ typedef struct {
|
||||
* The resulting dictionary will be saved into `dictBuffer`.
|
||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||
* or an error code, which can be tested with ZDICT_isError().
|
||||
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||
* Note: ZDICT_trainFromBuffer_cover() requires about 9 bytes of memory for each input byte.
|
||||
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
||||
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
||||
@@ -133,8 +144,9 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_cover(
|
||||
* If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [50, 2000].
|
||||
*
|
||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||
* or an error code, which can be tested with ZDICT_isError().
|
||||
* On success `*parameters` contains the parameters selected.
|
||||
* or an error code, which can be tested with ZDICT_isError().
|
||||
* On success `*parameters` contains the parameters selected.
|
||||
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||
* Note: ZDICT_optimizeTrainFromBuffer_cover() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread.
|
||||
*/
|
||||
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
@@ -151,7 +163,8 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
* The resulting dictionary will be saved into `dictBuffer`.
|
||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||
* or an error code, which can be tested with ZDICT_isError().
|
||||
* Note: ZDICT_trainFromBuffer_fastCover() requires about 1 bytes of memory for each input byte and additionally another 6 * 2^f bytes of memory .
|
||||
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||
* Note: ZDICT_trainFromBuffer_fastCover() requires 6 * 2^f bytes of memory.
|
||||
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
||||
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
||||
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
||||
@@ -175,9 +188,10 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_fastCover(void *dictBuffer,
|
||||
* If accel is zero, default value of 1 is used.
|
||||
*
|
||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||
* or an error code, which can be tested with ZDICT_isError().
|
||||
* On success `*parameters` contains the parameters selected.
|
||||
* Note: ZDICT_optimizeTrainFromBuffer_fastCover() requires about 1 byte of memory for each input byte and additionally another 6 * 2^f bytes of memory for each thread.
|
||||
* or an error code, which can be tested with ZDICT_isError().
|
||||
* On success `*parameters` contains the parameters selected.
|
||||
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||
* Note: ZDICT_optimizeTrainFromBuffer_fastCover() requires about 6 * 2^f bytes of memory for each thread.
|
||||
*/
|
||||
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer,
|
||||
size_t dictBufferCapacity, const void* samplesBuffer,
|
||||
@@ -195,7 +209,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer,
|
||||
* maxDictSize must be >= dictContentSize, and must be >= ZDICT_DICTSIZE_MIN bytes.
|
||||
*
|
||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`),
|
||||
* or an error code, which can be tested by ZDICT_isError().
|
||||
* or an error code, which can be tested by ZDICT_isError().
|
||||
* Note: ZDICT_finalizeDictionary() will push notifications into stderr if instructed to, using notificationLevel>0.
|
||||
* Note 2: dictBuffer and dictContent can overlap
|
||||
*/
|
||||
@@ -219,6 +233,7 @@ typedef struct {
|
||||
* `parameters` is optional and can be provided with values set to 0 to mean "default".
|
||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||
* or an error code, which can be tested with ZDICT_isError().
|
||||
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
||||
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
||||
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
||||
|
||||
@@ -6,14 +6,15 @@ COPY programs\datagen.h bin\example\
|
||||
COPY programs\util.h bin\example\
|
||||
COPY programs\platform.h bin\example\
|
||||
COPY lib\common\mem.h bin\example\
|
||||
COPY lib\common\zstd_errors.h bin\example\
|
||||
COPY lib\common\zstd_internal.h bin\example\
|
||||
COPY lib\common\error_private.h bin\example\
|
||||
COPY lib\common\xxhash.h bin\example\
|
||||
COPY lib\zstd.h bin\include\
|
||||
COPY lib\libzstd.a bin\static\libzstd_static.lib
|
||||
COPY lib\dll\libzstd.* 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 lib\zstd.h bin\include\
|
||||
COPY lib\common\zstd_errors.h bin\include\
|
||||
COPY lib\dictBuilder\zdict.h bin\include\
|
||||
COPY programs\zstd.exe bin\zstd.exe
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
LIBRARY libzstd.dll
|
||||
EXPORTS
|
||||
ZDICT_getDictID
|
||||
ZDICT_getErrorName
|
||||
ZDICT_isError
|
||||
ZDICT_trainFromBuffer
|
||||
ZSTD_CStreamInSize
|
||||
ZSTD_CStreamOutSize
|
||||
ZSTD_DStreamInSize
|
||||
ZSTD_DStreamOutSize
|
||||
ZSTD_adjustCParams
|
||||
ZSTD_checkCParams
|
||||
ZSTD_compress
|
||||
ZSTD_compressBegin
|
||||
ZSTD_compressBegin_advanced
|
||||
ZSTD_compressBegin_usingDict
|
||||
ZSTD_compressBlock
|
||||
ZSTD_compressBound
|
||||
ZSTD_compressCCtx
|
||||
ZSTD_compressContinue
|
||||
ZSTD_compressEnd
|
||||
ZSTD_compressStream
|
||||
ZSTD_compress_advanced
|
||||
ZSTD_compress_usingCDict
|
||||
ZSTD_compress_usingDict
|
||||
ZSTD_copyCCtx
|
||||
ZSTD_copyDCtx
|
||||
ZSTD_createCCtx
|
||||
ZSTD_createCCtx_advanced
|
||||
ZSTD_createCDict
|
||||
ZSTD_createCDict_advanced
|
||||
ZSTD_createCStream
|
||||
ZSTD_createCStream_advanced
|
||||
ZSTD_createDCtx
|
||||
ZSTD_createDCtx_advanced
|
||||
ZSTD_createDDict
|
||||
ZSTD_createDStream
|
||||
ZSTD_createDStream_advanced
|
||||
ZSTD_decompress
|
||||
ZSTD_decompressBegin
|
||||
ZSTD_decompressBegin_usingDict
|
||||
ZSTD_decompressBlock
|
||||
ZSTD_decompressContinue
|
||||
ZSTD_decompressDCtx
|
||||
ZSTD_decompressStream
|
||||
ZSTD_decompress_usingDDict
|
||||
ZSTD_decompress_usingDict
|
||||
ZSTD_endStream
|
||||
ZSTD_estimateCCtxSize
|
||||
ZSTD_estimateDCtxSize
|
||||
ZSTD_flushStream
|
||||
ZSTD_freeCCtx
|
||||
ZSTD_freeCDict
|
||||
ZSTD_freeCStream
|
||||
ZSTD_freeDCtx
|
||||
ZSTD_freeDDict
|
||||
ZSTD_freeDStream
|
||||
ZSTD_getBlockSizeMax
|
||||
ZSTD_getCParams
|
||||
ZSTD_getDecompressedSize
|
||||
ZSTD_findDecompressedSize
|
||||
ZSTD_getFrameContentSize
|
||||
ZSTD_getErrorName
|
||||
ZSTD_getFrameParams
|
||||
ZSTD_getParams
|
||||
ZSTD_initCStream
|
||||
ZSTD_initCStream_advanced
|
||||
ZSTD_initCStream_usingCDict
|
||||
ZSTD_initCStream_usingDict
|
||||
ZSTD_initDStream
|
||||
ZSTD_initDStream_usingDDict
|
||||
ZSTD_initDStream_usingDict
|
||||
ZSTD_insertBlock
|
||||
ZSTD_isError
|
||||
ZSTD_isFrame
|
||||
ZSTD_maxCLevel
|
||||
ZSTD_nextInputType
|
||||
ZSTD_nextSrcSizeToDecompress
|
||||
ZSTD_resetCStream
|
||||
ZSTD_resetDStream
|
||||
ZSTD_sizeof_CCtx
|
||||
ZSTD_sizeof_CDict
|
||||
ZSTD_sizeof_CStream
|
||||
ZSTD_sizeof_DCtx
|
||||
ZSTD_sizeof_DDict
|
||||
ZSTD_sizeof_DStream
|
||||
ZSTD_versionNumber
|
||||
+46
-12
@@ -20,7 +20,7 @@ extern "C" {
|
||||
***************************************/
|
||||
#include "mem.h" /* MEM_STATIC */
|
||||
#include "error_private.h" /* ERROR */
|
||||
#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer */
|
||||
#include "zstd_internal.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */
|
||||
|
||||
#if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0)
|
||||
# undef ZSTD_LEGACY_SUPPORT
|
||||
@@ -178,43 +178,77 @@ MEM_STATIC size_t ZSTD_decompressLegacy(
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src,
|
||||
size_t compressedSize)
|
||||
MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize)
|
||||
{
|
||||
U32 const version = ZSTD_isLegacy(src, compressedSize);
|
||||
ZSTD_frameSizeInfo frameSizeInfo;
|
||||
U32 const version = ZSTD_isLegacy(src, srcSize);
|
||||
switch(version)
|
||||
{
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 1)
|
||||
case 1 :
|
||||
return ZSTDv01_findFrameCompressedSize(src, compressedSize);
|
||||
ZSTDv01_findFrameSizeInfoLegacy(src, srcSize,
|
||||
&frameSizeInfo.compressedSize,
|
||||
&frameSizeInfo.decompressedBound);
|
||||
break;
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 2)
|
||||
case 2 :
|
||||
return ZSTDv02_findFrameCompressedSize(src, compressedSize);
|
||||
ZSTDv02_findFrameSizeInfoLegacy(src, srcSize,
|
||||
&frameSizeInfo.compressedSize,
|
||||
&frameSizeInfo.decompressedBound);
|
||||
break;
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 3)
|
||||
case 3 :
|
||||
return ZSTDv03_findFrameCompressedSize(src, compressedSize);
|
||||
ZSTDv03_findFrameSizeInfoLegacy(src, srcSize,
|
||||
&frameSizeInfo.compressedSize,
|
||||
&frameSizeInfo.decompressedBound);
|
||||
break;
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 4)
|
||||
case 4 :
|
||||
return ZSTDv04_findFrameCompressedSize(src, compressedSize);
|
||||
ZSTDv04_findFrameSizeInfoLegacy(src, srcSize,
|
||||
&frameSizeInfo.compressedSize,
|
||||
&frameSizeInfo.decompressedBound);
|
||||
break;
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 5)
|
||||
case 5 :
|
||||
return ZSTDv05_findFrameCompressedSize(src, compressedSize);
|
||||
ZSTDv05_findFrameSizeInfoLegacy(src, srcSize,
|
||||
&frameSizeInfo.compressedSize,
|
||||
&frameSizeInfo.decompressedBound);
|
||||
break;
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 6)
|
||||
case 6 :
|
||||
return ZSTDv06_findFrameCompressedSize(src, compressedSize);
|
||||
ZSTDv06_findFrameSizeInfoLegacy(src, srcSize,
|
||||
&frameSizeInfo.compressedSize,
|
||||
&frameSizeInfo.decompressedBound);
|
||||
break;
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 7)
|
||||
case 7 :
|
||||
return ZSTDv07_findFrameCompressedSize(src, compressedSize);
|
||||
ZSTDv07_findFrameSizeInfoLegacy(src, srcSize,
|
||||
&frameSizeInfo.compressedSize,
|
||||
&frameSizeInfo.decompressedBound);
|
||||
break;
|
||||
#endif
|
||||
default :
|
||||
return ERROR(prefix_unknown);
|
||||
frameSizeInfo.compressedSize = ERROR(prefix_unknown);
|
||||
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
break;
|
||||
}
|
||||
if (!ZSTD_isError(frameSizeInfo.compressedSize) && frameSizeInfo.compressedSize > srcSize) {
|
||||
frameSizeInfo.compressedSize = ERROR(srcSize_wrong);
|
||||
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
return frameSizeInfo;
|
||||
}
|
||||
|
||||
MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize)
|
||||
{
|
||||
ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize);
|
||||
return frameSizeInfo.compressedSize;
|
||||
}
|
||||
|
||||
MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)
|
||||
|
||||
+124
-105
@@ -1073,99 +1073,102 @@ static size_t HUF_decompress_usingDTable( /* -3% slower when non static */
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const U16* DTable)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const omax = op + maxDstSize;
|
||||
BYTE* const olimit = omax-15;
|
||||
|
||||
const void* ptr = DTable;
|
||||
const HUF_DElt* const dt = (const HUF_DElt*)(ptr)+1;
|
||||
const U32 dtLog = DTable[0];
|
||||
size_t errorCode;
|
||||
U32 reloadStatus;
|
||||
|
||||
/* Init */
|
||||
|
||||
const U16* jumpTable = (const U16*)cSrc;
|
||||
const size_t length1 = FSE_readLE16(jumpTable);
|
||||
const size_t length2 = FSE_readLE16(jumpTable+1);
|
||||
const size_t length3 = FSE_readLE16(jumpTable+2);
|
||||
const size_t length4 = cSrcSize - 6 - length1 - length2 - length3; // check coherency !!
|
||||
const char* const start1 = (const char*)(cSrc) + 6;
|
||||
const char* const start2 = start1 + length1;
|
||||
const char* const start3 = start2 + length2;
|
||||
const char* const start4 = start3 + length3;
|
||||
FSE_DStream_t bitD1, bitD2, bitD3, bitD4;
|
||||
|
||||
if (length1+length2+length3+6 >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;
|
||||
|
||||
errorCode = FSE_initDStream(&bitD1, start1, length1);
|
||||
if (FSE_isError(errorCode)) return errorCode;
|
||||
errorCode = FSE_initDStream(&bitD2, start2, length2);
|
||||
if (FSE_isError(errorCode)) return errorCode;
|
||||
errorCode = FSE_initDStream(&bitD3, start3, length3);
|
||||
if (FSE_isError(errorCode)) return errorCode;
|
||||
errorCode = FSE_initDStream(&bitD4, start4, length4);
|
||||
if (FSE_isError(errorCode)) return errorCode;
|
||||
|
||||
reloadStatus=FSE_reloadDStream(&bitD2);
|
||||
|
||||
/* 16 symbols per loop */
|
||||
for ( ; (reloadStatus<FSE_DStream_completed) && (op<olimit); /* D2-3-4 are supposed to be synchronized and finish together */
|
||||
op+=16, reloadStatus = FSE_reloadDStream(&bitD2) | FSE_reloadDStream(&bitD3) | FSE_reloadDStream(&bitD4), FSE_reloadDStream(&bitD1))
|
||||
if (cSrcSize < 6) return (size_t)-FSE_ERROR_srcSize_wrong;
|
||||
{
|
||||
#define HUF_DECODE_SYMBOL_0(n, Dstream) \
|
||||
op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog);
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const omax = op + maxDstSize;
|
||||
BYTE* const olimit = omax-15;
|
||||
|
||||
#define HUF_DECODE_SYMBOL_1(n, Dstream) \
|
||||
op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \
|
||||
if (FSE_32bits() && (HUF_MAX_TABLELOG>12)) FSE_reloadDStream(&Dstream)
|
||||
const void* ptr = DTable;
|
||||
const HUF_DElt* const dt = (const HUF_DElt*)(ptr)+1;
|
||||
const U32 dtLog = DTable[0];
|
||||
size_t errorCode;
|
||||
U32 reloadStatus;
|
||||
|
||||
#define HUF_DECODE_SYMBOL_2(n, Dstream) \
|
||||
op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \
|
||||
if (FSE_32bits()) FSE_reloadDStream(&Dstream)
|
||||
/* Init */
|
||||
|
||||
HUF_DECODE_SYMBOL_1( 0, bitD1);
|
||||
HUF_DECODE_SYMBOL_1( 1, bitD2);
|
||||
HUF_DECODE_SYMBOL_1( 2, bitD3);
|
||||
HUF_DECODE_SYMBOL_1( 3, bitD4);
|
||||
HUF_DECODE_SYMBOL_2( 4, bitD1);
|
||||
HUF_DECODE_SYMBOL_2( 5, bitD2);
|
||||
HUF_DECODE_SYMBOL_2( 6, bitD3);
|
||||
HUF_DECODE_SYMBOL_2( 7, bitD4);
|
||||
HUF_DECODE_SYMBOL_1( 8, bitD1);
|
||||
HUF_DECODE_SYMBOL_1( 9, bitD2);
|
||||
HUF_DECODE_SYMBOL_1(10, bitD3);
|
||||
HUF_DECODE_SYMBOL_1(11, bitD4);
|
||||
HUF_DECODE_SYMBOL_0(12, bitD1);
|
||||
HUF_DECODE_SYMBOL_0(13, bitD2);
|
||||
HUF_DECODE_SYMBOL_0(14, bitD3);
|
||||
HUF_DECODE_SYMBOL_0(15, bitD4);
|
||||
}
|
||||
const U16* jumpTable = (const U16*)cSrc;
|
||||
const size_t length1 = FSE_readLE16(jumpTable);
|
||||
const size_t length2 = FSE_readLE16(jumpTable+1);
|
||||
const size_t length3 = FSE_readLE16(jumpTable+2);
|
||||
const size_t length4 = cSrcSize - 6 - length1 - length2 - length3; // check coherency !!
|
||||
const char* const start1 = (const char*)(cSrc) + 6;
|
||||
const char* const start2 = start1 + length1;
|
||||
const char* const start3 = start2 + length2;
|
||||
const char* const start4 = start3 + length3;
|
||||
FSE_DStream_t bitD1, bitD2, bitD3, bitD4;
|
||||
|
||||
if (reloadStatus!=FSE_DStream_completed) /* not complete : some bitStream might be FSE_DStream_unfinished */
|
||||
return (size_t)-FSE_ERROR_corruptionDetected;
|
||||
if (length1+length2+length3+6 >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;
|
||||
|
||||
/* tail */
|
||||
{
|
||||
// bitTail = bitD1; // *much* slower : -20% !??!
|
||||
FSE_DStream_t bitTail;
|
||||
bitTail.ptr = bitD1.ptr;
|
||||
bitTail.bitsConsumed = bitD1.bitsConsumed;
|
||||
bitTail.bitContainer = bitD1.bitContainer; // required in case of FSE_DStream_endOfBuffer
|
||||
bitTail.start = start1;
|
||||
for ( ; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op<omax) ; op++)
|
||||
errorCode = FSE_initDStream(&bitD1, start1, length1);
|
||||
if (FSE_isError(errorCode)) return errorCode;
|
||||
errorCode = FSE_initDStream(&bitD2, start2, length2);
|
||||
if (FSE_isError(errorCode)) return errorCode;
|
||||
errorCode = FSE_initDStream(&bitD3, start3, length3);
|
||||
if (FSE_isError(errorCode)) return errorCode;
|
||||
errorCode = FSE_initDStream(&bitD4, start4, length4);
|
||||
if (FSE_isError(errorCode)) return errorCode;
|
||||
|
||||
reloadStatus=FSE_reloadDStream(&bitD2);
|
||||
|
||||
/* 16 symbols per loop */
|
||||
for ( ; (reloadStatus<FSE_DStream_completed) && (op<olimit); /* D2-3-4 are supposed to be synchronized and finish together */
|
||||
op+=16, reloadStatus = FSE_reloadDStream(&bitD2) | FSE_reloadDStream(&bitD3) | FSE_reloadDStream(&bitD4), FSE_reloadDStream(&bitD1))
|
||||
{
|
||||
HUF_DECODE_SYMBOL_0(0, bitTail);
|
||||
#define HUF_DECODE_SYMBOL_0(n, Dstream) \
|
||||
op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog);
|
||||
|
||||
#define HUF_DECODE_SYMBOL_1(n, Dstream) \
|
||||
op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \
|
||||
if (FSE_32bits() && (HUF_MAX_TABLELOG>12)) FSE_reloadDStream(&Dstream)
|
||||
|
||||
#define HUF_DECODE_SYMBOL_2(n, Dstream) \
|
||||
op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \
|
||||
if (FSE_32bits()) FSE_reloadDStream(&Dstream)
|
||||
|
||||
HUF_DECODE_SYMBOL_1( 0, bitD1);
|
||||
HUF_DECODE_SYMBOL_1( 1, bitD2);
|
||||
HUF_DECODE_SYMBOL_1( 2, bitD3);
|
||||
HUF_DECODE_SYMBOL_1( 3, bitD4);
|
||||
HUF_DECODE_SYMBOL_2( 4, bitD1);
|
||||
HUF_DECODE_SYMBOL_2( 5, bitD2);
|
||||
HUF_DECODE_SYMBOL_2( 6, bitD3);
|
||||
HUF_DECODE_SYMBOL_2( 7, bitD4);
|
||||
HUF_DECODE_SYMBOL_1( 8, bitD1);
|
||||
HUF_DECODE_SYMBOL_1( 9, bitD2);
|
||||
HUF_DECODE_SYMBOL_1(10, bitD3);
|
||||
HUF_DECODE_SYMBOL_1(11, bitD4);
|
||||
HUF_DECODE_SYMBOL_0(12, bitD1);
|
||||
HUF_DECODE_SYMBOL_0(13, bitD2);
|
||||
HUF_DECODE_SYMBOL_0(14, bitD3);
|
||||
HUF_DECODE_SYMBOL_0(15, bitD4);
|
||||
}
|
||||
|
||||
if (FSE_endOfDStream(&bitTail))
|
||||
return op-ostart;
|
||||
if (reloadStatus!=FSE_DStream_completed) /* not complete : some bitStream might be FSE_DStream_unfinished */
|
||||
return (size_t)-FSE_ERROR_corruptionDetected;
|
||||
|
||||
/* tail */
|
||||
{
|
||||
// bitTail = bitD1; // *much* slower : -20% !??!
|
||||
FSE_DStream_t bitTail;
|
||||
bitTail.ptr = bitD1.ptr;
|
||||
bitTail.bitsConsumed = bitD1.bitsConsumed;
|
||||
bitTail.bitContainer = bitD1.bitContainer; // required in case of FSE_DStream_endOfBuffer
|
||||
bitTail.start = start1;
|
||||
for ( ; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op<omax) ; op++)
|
||||
{
|
||||
HUF_DECODE_SYMBOL_0(0, bitTail);
|
||||
}
|
||||
|
||||
if (FSE_endOfDStream(&bitTail))
|
||||
return op-ostart;
|
||||
}
|
||||
|
||||
if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall; /* dst buffer is full, but cSrc unfinished */
|
||||
|
||||
return (size_t)-FSE_ERROR_corruptionDetected;
|
||||
}
|
||||
|
||||
if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall; /* dst buffer is full, but cSrc unfinished */
|
||||
|
||||
return (size_t)-FSE_ERROR_corruptionDetected;
|
||||
}
|
||||
|
||||
|
||||
@@ -1336,6 +1339,8 @@ static const U32 ZSTD_magicNumber = 0xFD2FB51E; /* 3rd version : seqNb header
|
||||
#define LITERAL_NOENTROPY 63
|
||||
#define COMMAND_NOENTROPY 7 /* to remove */
|
||||
|
||||
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||
|
||||
static const size_t ZSTD_blockHeaderSize = 3;
|
||||
static const size_t ZSTD_frameHeaderSize = 4;
|
||||
|
||||
@@ -1353,8 +1358,6 @@ static unsigned ZSTD_isLittleEndian(void)
|
||||
|
||||
static U16 ZSTD_read16(const void* p) { U16 r; memcpy(&r, p, sizeof(r)); return r; }
|
||||
|
||||
static U32 ZSTD_read32(const void* p) { U32 r; memcpy(&r, p, sizeof(r)); return r; }
|
||||
|
||||
static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
|
||||
|
||||
static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
|
||||
@@ -1379,16 +1382,9 @@ static U16 ZSTD_readLE16(const void* memPtr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static U32 ZSTD_readLE32(const void* memPtr)
|
||||
static U32 ZSTD_readLE24(const void* memPtr)
|
||||
{
|
||||
if (ZSTD_isLittleEndian())
|
||||
return ZSTD_read32(memPtr);
|
||||
else
|
||||
{
|
||||
const BYTE* p = (const BYTE*)memPtr;
|
||||
return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));
|
||||
}
|
||||
return ZSTD_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
|
||||
}
|
||||
|
||||
static U32 ZSTD_readBE32(const void* memPtr)
|
||||
@@ -1702,13 +1698,13 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
seqState->prevOffset = seq->offset;
|
||||
if (litLength == MaxLL)
|
||||
{
|
||||
U32 add = dumps<de ? *dumps++ : 0;
|
||||
const U32 add = dumps<de ? *dumps++ : 0;
|
||||
if (add < 255) litLength += add;
|
||||
else
|
||||
{
|
||||
if (dumps<=(de-3))
|
||||
{
|
||||
litLength = ZSTD_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
||||
litLength = ZSTD_readLE24(dumps);
|
||||
dumps += 3;
|
||||
}
|
||||
}
|
||||
@@ -1730,13 +1726,13 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
|
||||
if (matchLength == MaxML)
|
||||
{
|
||||
U32 add = dumps<de ? *dumps++ : 0;
|
||||
const U32 add = dumps<de ? *dumps++ : 0;
|
||||
if (add < 255) matchLength += add;
|
||||
else
|
||||
{
|
||||
if (dumps<=(de-3))
|
||||
{
|
||||
matchLength = ZSTD_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
||||
matchLength = ZSTD_readLE24(dumps);
|
||||
dumps += 3;
|
||||
}
|
||||
}
|
||||
@@ -1757,7 +1753,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
||||
BYTE* const base, BYTE* const oend)
|
||||
{
|
||||
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */
|
||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
|
||||
const BYTE* const ostart = op;
|
||||
const size_t litLength = sequence.litLength;
|
||||
BYTE* const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
||||
@@ -1999,36 +1995,59 @@ size_t ZSTDv01_decompress(void* dst, size_t maxDstSize, const void* src, size_t
|
||||
return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
|
||||
}
|
||||
|
||||
size_t ZSTDv01_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||
assumes `cSize` and `dBound` are _not_ NULL */
|
||||
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||
{
|
||||
*cSize = ret;
|
||||
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
size_t remainingSize = srcSize;
|
||||
size_t nbBlocks = 0;
|
||||
U32 magicNumber;
|
||||
blockProperties_t blockProperties;
|
||||
|
||||
/* Frame Header */
|
||||
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
magicNumber = ZSTD_readBE32(src);
|
||||
if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
|
||||
if (magicNumber != ZSTD_magicNumber) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||
return;
|
||||
}
|
||||
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
|
||||
|
||||
/* Loop on each block */
|
||||
while (1)
|
||||
{
|
||||
size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||
if (ZSTDv01_isError(blockSize)) return blockSize;
|
||||
if (ZSTDv01_isError(blockSize)) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, blockSize);
|
||||
return;
|
||||
}
|
||||
|
||||
ip += ZSTD_blockHeaderSize;
|
||||
remainingSize -= ZSTD_blockHeaderSize;
|
||||
if (blockSize > remainingSize) return ERROR(srcSize_wrong);
|
||||
if (blockSize > remainingSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
|
||||
if (blockSize == 0) break; /* bt_end */
|
||||
|
||||
ip += blockSize;
|
||||
remainingSize -= blockSize;
|
||||
nbBlocks++;
|
||||
}
|
||||
|
||||
return ip - (const BYTE*)src;
|
||||
*cSize = ip - (const BYTE*)src;
|
||||
*dBound = nbBlocks * BLOCKSIZE;
|
||||
}
|
||||
|
||||
/*******************************
|
||||
|
||||
+12
-7
@@ -35,13 +35,18 @@ ZSTDv01_decompress() : decompress ZSTD frames compliant with v0.1.x format
|
||||
size_t ZSTDv01_decompress( void* dst, size_t maxOriginalSize,
|
||||
const void* src, size_t compressedSize);
|
||||
|
||||
/**
|
||||
ZSTDv01_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.1.x format
|
||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
return : the number of bytes that would be read to decompress this frame
|
||||
or an errorCode if it fails (which can be tested using ZSTDv01_isError())
|
||||
*/
|
||||
size_t ZSTDv01_findFrameCompressedSize(const void* src, size_t compressedSize);
|
||||
/**
|
||||
ZSTDv01_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.1.x format
|
||||
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||
|
||||
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||
*/
|
||||
void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||
size_t* cSize, unsigned long long* dBound);
|
||||
|
||||
/**
|
||||
ZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error
|
||||
|
||||
+42
-18
@@ -217,6 +217,11 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE24(const void* memPtr)
|
||||
{
|
||||
return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE32(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
@@ -2728,6 +2733,8 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
|
||||
#define LITERAL_NOENTROPY 63
|
||||
#define COMMAND_NOENTROPY 7 /* to remove */
|
||||
|
||||
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||
|
||||
static const size_t ZSTD_blockHeaderSize = 3;
|
||||
static const size_t ZSTD_frameHeaderSize = 4;
|
||||
|
||||
@@ -3041,11 +3048,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
seqState->prevOffset = seq->offset;
|
||||
if (litLength == MaxLL)
|
||||
{
|
||||
U32 add = *dumps++;
|
||||
const U32 add = dumps<de ? *dumps++ : 0;
|
||||
if (add < 255) litLength += add;
|
||||
else
|
||||
else if (dumps + 3 <= de)
|
||||
{
|
||||
litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
||||
litLength = MEM_readLE24(dumps);
|
||||
dumps += 3;
|
||||
}
|
||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
@@ -3071,11 +3078,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
|
||||
if (matchLength == MaxML)
|
||||
{
|
||||
U32 add = *dumps++;
|
||||
const U32 add = dumps<de ? *dumps++ : 0;
|
||||
if (add < 255) matchLength += add;
|
||||
else
|
||||
else if (dumps + 3 <= de)
|
||||
{
|
||||
matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
||||
matchLength = MEM_readLE24(dumps);
|
||||
dumps += 3;
|
||||
}
|
||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
@@ -3096,7 +3103,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
||||
BYTE* const base, BYTE* const oend)
|
||||
{
|
||||
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */
|
||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
|
||||
const BYTE* const ostart = op;
|
||||
BYTE* const oLitEnd = op + sequence.litLength;
|
||||
BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
||||
@@ -3312,37 +3319,59 @@ static size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, siz
|
||||
return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
|
||||
}
|
||||
|
||||
static size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
||||
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||
assumes `cSize` and `dBound` are _not_ NULL */
|
||||
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||
{
|
||||
*cSize = ret;
|
||||
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
size_t remainingSize = srcSize;
|
||||
size_t nbBlocks = 0;
|
||||
U32 magicNumber;
|
||||
blockProperties_t blockProperties;
|
||||
|
||||
/* Frame Header */
|
||||
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
magicNumber = MEM_readLE32(src);
|
||||
if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
|
||||
if (magicNumber != ZSTD_magicNumber) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||
return;
|
||||
}
|
||||
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
|
||||
|
||||
/* Loop on each block */
|
||||
while (1)
|
||||
{
|
||||
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
||||
if (ZSTD_isError(cBlockSize)) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||
return;
|
||||
}
|
||||
|
||||
ip += ZSTD_blockHeaderSize;
|
||||
remainingSize -= ZSTD_blockHeaderSize;
|
||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
||||
if (cBlockSize > remainingSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cBlockSize == 0) break; /* bt_end */
|
||||
|
||||
ip += cBlockSize;
|
||||
remainingSize -= cBlockSize;
|
||||
nbBlocks++;
|
||||
}
|
||||
|
||||
return ip - (const BYTE*)src;
|
||||
*cSize = ip - (const BYTE*)src;
|
||||
*dBound = nbBlocks * BLOCKSIZE;
|
||||
}
|
||||
|
||||
/*******************************
|
||||
@@ -3458,11 +3487,6 @@ size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,
|
||||
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
||||
}
|
||||
|
||||
size_t ZSTDv02_findFrameCompressedSize(const void *src, size_t compressedSize)
|
||||
{
|
||||
return ZSTD_findFrameCompressedSize(src, compressedSize);
|
||||
}
|
||||
|
||||
ZSTDv02_Dctx* ZSTDv02_createDCtx(void)
|
||||
{
|
||||
return (ZSTDv02_Dctx*)ZSTD_createDCtx();
|
||||
|
||||
+12
-7
@@ -35,13 +35,18 @@ ZSTDv02_decompress() : decompress ZSTD frames compliant with v0.2.x format
|
||||
size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,
|
||||
const void* src, size_t compressedSize);
|
||||
|
||||
/**
|
||||
ZSTDv02_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.2.x format
|
||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
return : the number of bytes that would be read to decompress this frame
|
||||
or an errorCode if it fails (which can be tested using ZSTDv02_isError())
|
||||
*/
|
||||
size_t ZSTDv02_findFrameCompressedSize(const void* src, size_t compressedSize);
|
||||
/**
|
||||
ZSTDv02_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.2.x format
|
||||
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||
|
||||
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||
*/
|
||||
void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||
size_t* cSize, unsigned long long* dBound);
|
||||
|
||||
/**
|
||||
ZSTDv02_isError() : tells if the result of ZSTDv02_decompress() is an error
|
||||
|
||||
+43
-18
@@ -219,6 +219,11 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE24(const void* memPtr)
|
||||
{
|
||||
return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE32(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
@@ -2369,6 +2374,8 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
|
||||
#define LITERAL_NOENTROPY 63
|
||||
#define COMMAND_NOENTROPY 7 /* to remove */
|
||||
|
||||
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||
|
||||
static const size_t ZSTD_blockHeaderSize = 3;
|
||||
static const size_t ZSTD_frameHeaderSize = 4;
|
||||
|
||||
@@ -2682,11 +2689,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
seqState->prevOffset = seq->offset;
|
||||
if (litLength == MaxLL)
|
||||
{
|
||||
U32 add = *dumps++;
|
||||
const U32 add = dumps<de ? *dumps++ : 0;
|
||||
if (add < 255) litLength += add;
|
||||
else
|
||||
else if (dumps + 3 <= de)
|
||||
{
|
||||
litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
||||
litLength = MEM_readLE24(dumps);
|
||||
dumps += 3;
|
||||
}
|
||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
@@ -2712,11 +2719,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
|
||||
if (matchLength == MaxML)
|
||||
{
|
||||
U32 add = *dumps++;
|
||||
const U32 add = dumps<de ? *dumps++ : 0;
|
||||
if (add < 255) matchLength += add;
|
||||
else
|
||||
else if (dumps + 3 <= de)
|
||||
{
|
||||
matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
||||
matchLength = MEM_readLE24(dumps);
|
||||
dumps += 3;
|
||||
}
|
||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
@@ -2737,7 +2744,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
||||
BYTE* const base, BYTE* const oend)
|
||||
{
|
||||
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */
|
||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
|
||||
const BYTE* const ostart = op;
|
||||
BYTE* const oLitEnd = op + sequence.litLength;
|
||||
BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
||||
@@ -2953,36 +2960,59 @@ static size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, siz
|
||||
return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
|
||||
}
|
||||
|
||||
static size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||
assumes `cSize` and `dBound` are _not_ NULL */
|
||||
MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||
{
|
||||
*cSize = ret;
|
||||
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
size_t remainingSize = srcSize;
|
||||
size_t nbBlocks = 0;
|
||||
U32 magicNumber;
|
||||
blockProperties_t blockProperties;
|
||||
|
||||
/* Frame Header */
|
||||
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
magicNumber = MEM_readLE32(src);
|
||||
if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
|
||||
if (magicNumber != ZSTD_magicNumber) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||
return;
|
||||
}
|
||||
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
|
||||
|
||||
/* Loop on each block */
|
||||
while (1)
|
||||
{
|
||||
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
||||
if (ZSTD_isError(cBlockSize)) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||
return;
|
||||
}
|
||||
|
||||
ip += ZSTD_blockHeaderSize;
|
||||
remainingSize -= ZSTD_blockHeaderSize;
|
||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
||||
if (cBlockSize > remainingSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cBlockSize == 0) break; /* bt_end */
|
||||
|
||||
ip += cBlockSize;
|
||||
remainingSize -= cBlockSize;
|
||||
nbBlocks++;
|
||||
}
|
||||
|
||||
return ip - (const BYTE*)src;
|
||||
*cSize = ip - (const BYTE*)src;
|
||||
*dBound = nbBlocks * BLOCKSIZE;
|
||||
}
|
||||
|
||||
|
||||
@@ -3099,11 +3129,6 @@ size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,
|
||||
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
||||
}
|
||||
|
||||
size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_findFrameCompressedSize(src, srcSize);
|
||||
}
|
||||
|
||||
ZSTDv03_Dctx* ZSTDv03_createDCtx(void)
|
||||
{
|
||||
return (ZSTDv03_Dctx*)ZSTD_createDCtx();
|
||||
|
||||
+12
-7
@@ -35,13 +35,18 @@ ZSTDv03_decompress() : decompress ZSTD frames compliant with v0.3.x format
|
||||
size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,
|
||||
const void* src, size_t compressedSize);
|
||||
|
||||
/**
|
||||
ZSTDv03_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.3.x format
|
||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
return : the number of bytes that would be read to decompress this frame
|
||||
or an errorCode if it fails (which can be tested using ZSTDv03_isError())
|
||||
*/
|
||||
size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t compressedSize);
|
||||
/**
|
||||
ZSTDv03_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.3.x format
|
||||
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||
|
||||
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||
*/
|
||||
void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||
size_t* cSize, unsigned long long* dBound);
|
||||
|
||||
/**
|
||||
ZSTDv03_isError() : tells if the result of ZSTDv03_decompress() is an error
|
||||
|
||||
+43
-20
@@ -189,6 +189,11 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE24(const void* memPtr)
|
||||
{
|
||||
return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE32(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
@@ -373,6 +378,8 @@ static const size_t ZSTD_frameHeaderSize_min = 5;
|
||||
#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)
|
||||
#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)
|
||||
|
||||
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||
|
||||
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
||||
|
||||
|
||||
@@ -2806,13 +2813,12 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));
|
||||
prevOffset = litLength ? seq->offset : seqState->prevOffset;
|
||||
if (litLength == MaxLL) {
|
||||
U32 add = *dumps++;
|
||||
const U32 add = dumps<de ? *dumps++ : 0;
|
||||
if (add < 255) litLength += add;
|
||||
else {
|
||||
litLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16);
|
||||
else if (dumps + 3 <= de) {
|
||||
litLength = MEM_readLE24(dumps);
|
||||
dumps += 3;
|
||||
}
|
||||
if (dumps > de) { litLength = MaxLL+255; } /* late correction, to avoid using uninitialized memory */
|
||||
if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
}
|
||||
|
||||
@@ -2835,13 +2841,12 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
/* MatchLength */
|
||||
matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
|
||||
if (matchLength == MaxML) {
|
||||
U32 add = *dumps++;
|
||||
const U32 add = dumps<de ? *dumps++ : 0;
|
||||
if (add < 255) matchLength += add;
|
||||
else {
|
||||
matchLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16);
|
||||
else if (dumps + 3 <= de){
|
||||
matchLength = MEM_readLE24(dumps);
|
||||
dumps += 3;
|
||||
}
|
||||
if (dumps > de) { matchLength = MaxML+255; } /* late correction, to avoid using uninitialized memory */
|
||||
if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
}
|
||||
matchLength += MINMATCH;
|
||||
@@ -2860,7 +2865,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
||||
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
||||
{
|
||||
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
||||
BYTE* const oLitEnd = op + sequence.litLength;
|
||||
const size_t sequenceLength = sequence.litLength + sequence.matchLength;
|
||||
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
||||
@@ -3119,34 +3124,57 @@ static size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx,
|
||||
return op-ostart;
|
||||
}
|
||||
|
||||
static size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||
assumes `cSize` and `dBound` are _not_ NULL */
|
||||
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||
{
|
||||
*cSize = ret;
|
||||
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
size_t remainingSize = srcSize;
|
||||
size_t nbBlocks = 0;
|
||||
blockProperties_t blockProperties;
|
||||
|
||||
/* Frame Header */
|
||||
if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);
|
||||
if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
|
||||
if (srcSize < ZSTD_frameHeaderSize_min) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||
return;
|
||||
}
|
||||
ip += ZSTD_frameHeaderSize_min; remainingSize -= ZSTD_frameHeaderSize_min;
|
||||
|
||||
/* Loop on each block */
|
||||
while (1)
|
||||
{
|
||||
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
||||
if (ZSTD_isError(cBlockSize)) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||
return;
|
||||
}
|
||||
|
||||
ip += ZSTD_blockHeaderSize;
|
||||
remainingSize -= ZSTD_blockHeaderSize;
|
||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
||||
if (cBlockSize > remainingSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cBlockSize == 0) break; /* bt_end */
|
||||
|
||||
ip += cBlockSize;
|
||||
remainingSize -= cBlockSize;
|
||||
nbBlocks++;
|
||||
}
|
||||
|
||||
return ip - (const BYTE*)src;
|
||||
*cSize = ip - (const BYTE*)src;
|
||||
*dBound = nbBlocks * BLOCKSIZE;
|
||||
}
|
||||
|
||||
/* ******************************
|
||||
@@ -3578,11 +3606,6 @@ size_t ZSTDv04_decompress(void* dst, size_t maxDstSize, const void* src, size_t
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t ZSTDv04_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_findFrameCompressedSize(src, srcSize);
|
||||
}
|
||||
|
||||
size_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx) { return ZSTD_resetDCtx(dctx); }
|
||||
|
||||
size_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx)
|
||||
|
||||
+12
-7
@@ -35,13 +35,18 @@ ZSTDv04_decompress() : decompress ZSTD frames compliant with v0.4.x format
|
||||
size_t ZSTDv04_decompress( void* dst, size_t maxOriginalSize,
|
||||
const void* src, size_t compressedSize);
|
||||
|
||||
/**
|
||||
ZSTDv04_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.4.x format
|
||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
return : the number of bytes that would be read to decompress this frame
|
||||
or an errorCode if it fails (which can be tested using ZSTDv04_isError())
|
||||
*/
|
||||
size_t ZSTDv04_findFrameCompressedSize(const void* src, size_t compressedSize);
|
||||
/**
|
||||
ZSTDv04_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.4.x format
|
||||
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||
|
||||
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||
*/
|
||||
void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||
size_t* cSize, unsigned long long* dBound);
|
||||
|
||||
/**
|
||||
ZSTDv04_isError() : tells if the result of ZSTDv04_decompress() is an error
|
||||
|
||||
+123
-94
@@ -218,6 +218,11 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE24(const void* memPtr)
|
||||
{
|
||||
return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE32(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
@@ -491,6 +496,8 @@ static const size_t ZSTDv05_frameHeaderSize_min = 5;
|
||||
|
||||
#define WILDCOPY_OVERLENGTH 8
|
||||
|
||||
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||
|
||||
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
||||
|
||||
|
||||
@@ -1996,91 +2003,92 @@ size_t HUFv05_decompress4X2_usingDTable(
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const U16* DTable)
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*) cSrc;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
const void* const dtPtr = DTable;
|
||||
const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr) +1;
|
||||
const U32 dtLog = DTable[0];
|
||||
size_t errorCode;
|
||||
|
||||
/* Init */
|
||||
BITv05_DStream_t bitD1;
|
||||
BITv05_DStream_t bitD2;
|
||||
BITv05_DStream_t bitD3;
|
||||
BITv05_DStream_t bitD4;
|
||||
const size_t length1 = MEM_readLE16(istart);
|
||||
const size_t length2 = MEM_readLE16(istart+2);
|
||||
const size_t length3 = MEM_readLE16(istart+4);
|
||||
size_t length4;
|
||||
const BYTE* const istart1 = istart + 6; /* jumpTable */
|
||||
const BYTE* const istart2 = istart1 + length1;
|
||||
const BYTE* const istart3 = istart2 + length2;
|
||||
const BYTE* const istart4 = istart3 + length3;
|
||||
const size_t segmentSize = (dstSize+3) / 4;
|
||||
BYTE* const opStart2 = ostart + segmentSize;
|
||||
BYTE* const opStart3 = opStart2 + segmentSize;
|
||||
BYTE* const opStart4 = opStart3 + segmentSize;
|
||||
BYTE* op1 = ostart;
|
||||
BYTE* op2 = opStart2;
|
||||
BYTE* op3 = opStart3;
|
||||
BYTE* op4 = opStart4;
|
||||
U32 endSignal;
|
||||
|
||||
/* Check */
|
||||
if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*) cSrc;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
const void* const dtPtr = DTable;
|
||||
const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr) +1;
|
||||
const U32 dtLog = DTable[0];
|
||||
size_t errorCode;
|
||||
|
||||
length4 = cSrcSize - (length1 + length2 + length3 + 6);
|
||||
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
||||
errorCode = BITv05_initDStream(&bitD1, istart1, length1);
|
||||
if (HUFv05_isError(errorCode)) return errorCode;
|
||||
errorCode = BITv05_initDStream(&bitD2, istart2, length2);
|
||||
if (HUFv05_isError(errorCode)) return errorCode;
|
||||
errorCode = BITv05_initDStream(&bitD3, istart3, length3);
|
||||
if (HUFv05_isError(errorCode)) return errorCode;
|
||||
errorCode = BITv05_initDStream(&bitD4, istart4, length4);
|
||||
if (HUFv05_isError(errorCode)) return errorCode;
|
||||
/* Init */
|
||||
BITv05_DStream_t bitD1;
|
||||
BITv05_DStream_t bitD2;
|
||||
BITv05_DStream_t bitD3;
|
||||
BITv05_DStream_t bitD4;
|
||||
const size_t length1 = MEM_readLE16(istart);
|
||||
const size_t length2 = MEM_readLE16(istart+2);
|
||||
const size_t length3 = MEM_readLE16(istart+4);
|
||||
size_t length4;
|
||||
const BYTE* const istart1 = istart + 6; /* jumpTable */
|
||||
const BYTE* const istart2 = istart1 + length1;
|
||||
const BYTE* const istart3 = istart2 + length2;
|
||||
const BYTE* const istart4 = istart3 + length3;
|
||||
const size_t segmentSize = (dstSize+3) / 4;
|
||||
BYTE* const opStart2 = ostart + segmentSize;
|
||||
BYTE* const opStart3 = opStart2 + segmentSize;
|
||||
BYTE* const opStart4 = opStart3 + segmentSize;
|
||||
BYTE* op1 = ostart;
|
||||
BYTE* op2 = opStart2;
|
||||
BYTE* op3 = opStart3;
|
||||
BYTE* op4 = opStart4;
|
||||
U32 endSignal;
|
||||
|
||||
/* 16-32 symbols per loop (4-8 symbols per stream) */
|
||||
endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);
|
||||
for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {
|
||||
HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);
|
||||
HUFv05_DECODE_SYMBOLX2_1(op1, &bitD1);
|
||||
HUFv05_DECODE_SYMBOLX2_1(op2, &bitD2);
|
||||
HUFv05_DECODE_SYMBOLX2_1(op3, &bitD3);
|
||||
HUFv05_DECODE_SYMBOLX2_1(op4, &bitD4);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);
|
||||
HUFv05_DECODE_SYMBOLX2_0(op1, &bitD1);
|
||||
HUFv05_DECODE_SYMBOLX2_0(op2, &bitD2);
|
||||
HUFv05_DECODE_SYMBOLX2_0(op3, &bitD3);
|
||||
HUFv05_DECODE_SYMBOLX2_0(op4, &bitD4);
|
||||
length4 = cSrcSize - (length1 + length2 + length3 + 6);
|
||||
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
||||
errorCode = BITv05_initDStream(&bitD1, istart1, length1);
|
||||
if (HUFv05_isError(errorCode)) return errorCode;
|
||||
errorCode = BITv05_initDStream(&bitD2, istart2, length2);
|
||||
if (HUFv05_isError(errorCode)) return errorCode;
|
||||
errorCode = BITv05_initDStream(&bitD3, istart3, length3);
|
||||
if (HUFv05_isError(errorCode)) return errorCode;
|
||||
errorCode = BITv05_initDStream(&bitD4, istart4, length4);
|
||||
if (HUFv05_isError(errorCode)) return errorCode;
|
||||
|
||||
/* 16-32 symbols per loop (4-8 symbols per stream) */
|
||||
endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);
|
||||
for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {
|
||||
HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);
|
||||
HUFv05_DECODE_SYMBOLX2_1(op1, &bitD1);
|
||||
HUFv05_DECODE_SYMBOLX2_1(op2, &bitD2);
|
||||
HUFv05_DECODE_SYMBOLX2_1(op3, &bitD3);
|
||||
HUFv05_DECODE_SYMBOLX2_1(op4, &bitD4);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);
|
||||
HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);
|
||||
HUFv05_DECODE_SYMBOLX2_0(op1, &bitD1);
|
||||
HUFv05_DECODE_SYMBOLX2_0(op2, &bitD2);
|
||||
HUFv05_DECODE_SYMBOLX2_0(op3, &bitD3);
|
||||
HUFv05_DECODE_SYMBOLX2_0(op4, &bitD4);
|
||||
endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);
|
||||
}
|
||||
|
||||
/* check corruption */
|
||||
if (op1 > opStart2) return ERROR(corruption_detected);
|
||||
if (op2 > opStart3) return ERROR(corruption_detected);
|
||||
if (op3 > opStart4) return ERROR(corruption_detected);
|
||||
/* note : op4 supposed already verified within main loop */
|
||||
|
||||
/* finish bitStreams one by one */
|
||||
HUFv05_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
|
||||
HUFv05_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
|
||||
HUFv05_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
|
||||
HUFv05_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
|
||||
|
||||
/* check */
|
||||
endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);
|
||||
if (!endSignal) return ERROR(corruption_detected);
|
||||
|
||||
/* decoded size */
|
||||
return dstSize;
|
||||
}
|
||||
|
||||
/* check corruption */
|
||||
if (op1 > opStart2) return ERROR(corruption_detected);
|
||||
if (op2 > opStart3) return ERROR(corruption_detected);
|
||||
if (op3 > opStart4) return ERROR(corruption_detected);
|
||||
/* note : op4 supposed already verified within main loop */
|
||||
|
||||
/* finish bitStreams one by one */
|
||||
HUFv05_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
|
||||
HUFv05_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
|
||||
HUFv05_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
|
||||
HUFv05_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
|
||||
|
||||
/* check */
|
||||
endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);
|
||||
if (!endSignal) return ERROR(corruption_detected);
|
||||
|
||||
/* decoded size */
|
||||
return dstSize;
|
||||
}
|
||||
|
||||
|
||||
@@ -3148,14 +3156,13 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
litLength = FSEv05_peakSymbol(&(seqState->stateLL));
|
||||
prevOffset = litLength ? seq->offset : seqState->prevOffset;
|
||||
if (litLength == MaxLL) {
|
||||
U32 add = *dumps++;
|
||||
const U32 add = *dumps++;
|
||||
if (add < 255) litLength += add;
|
||||
else {
|
||||
litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no risk : dumps is always followed by seq tables > 1 byte */
|
||||
else if (dumps + 3 <= de) {
|
||||
litLength = MEM_readLE24(dumps);
|
||||
if (litLength&1) litLength>>=1, dumps += 3;
|
||||
else litLength = (U16)(litLength)>>1, dumps += 2;
|
||||
}
|
||||
if (dumps > de) { litLength = MaxLL+255; } /* late correction, to avoid using uninitialized memory */
|
||||
if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
}
|
||||
|
||||
@@ -3182,14 +3189,13 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)
|
||||
/* MatchLength */
|
||||
matchLength = FSEv05_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
|
||||
if (matchLength == MaxML) {
|
||||
U32 add = *dumps++;
|
||||
const U32 add = dumps<de ? *dumps++ : 0;
|
||||
if (add < 255) matchLength += add;
|
||||
else {
|
||||
matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
||||
else if (dumps + 3 <= de) {
|
||||
matchLength = MEM_readLE24(dumps);
|
||||
if (matchLength&1) matchLength>>=1, dumps += 3;
|
||||
else matchLength = (U16)(matchLength)>>1, dumps += 2;
|
||||
}
|
||||
if (dumps > de) { matchLength = MaxML+255; } /* late correction, to avoid using uninitialized memory */
|
||||
if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
}
|
||||
matchLength += MINMATCH;
|
||||
@@ -3217,7 +3223,7 @@ static size_t ZSTDv05_execSequence(BYTE* op,
|
||||
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
||||
{
|
||||
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
||||
BYTE* const oLitEnd = op + sequence.litLength;
|
||||
const size_t sequenceLength = sequence.litLength + sequence.matchLength;
|
||||
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
||||
@@ -3508,34 +3514,57 @@ size_t ZSTDv05_decompress(void* dst, size_t maxDstSize, const void* src, size_t
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t ZSTDv05_findFrameCompressedSize(const void *src, size_t srcSize)
|
||||
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||
assumes `cSize` and `dBound` are _not_ NULL */
|
||||
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||
{
|
||||
*cSize = ret;
|
||||
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
size_t remainingSize = srcSize;
|
||||
size_t nbBlocks = 0;
|
||||
blockProperties_t blockProperties;
|
||||
|
||||
/* Frame Header */
|
||||
if (srcSize < ZSTDv05_frameHeaderSize_min) return ERROR(srcSize_wrong);
|
||||
if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);
|
||||
if (srcSize < ZSTDv05_frameHeaderSize_min) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||
return;
|
||||
}
|
||||
ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min;
|
||||
|
||||
/* Loop on each block */
|
||||
while (1)
|
||||
{
|
||||
size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||
if (ZSTDv05_isError(cBlockSize)) return cBlockSize;
|
||||
if (ZSTDv05_isError(cBlockSize)) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||
return;
|
||||
}
|
||||
|
||||
ip += ZSTDv05_blockHeaderSize;
|
||||
remainingSize -= ZSTDv05_blockHeaderSize;
|
||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
||||
if (cBlockSize > remainingSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cBlockSize == 0) break; /* bt_end */
|
||||
|
||||
ip += cBlockSize;
|
||||
remainingSize -= cBlockSize;
|
||||
nbBlocks++;
|
||||
}
|
||||
|
||||
return ip - (const BYTE*)src;
|
||||
*cSize = ip - (const BYTE*)src;
|
||||
*dBound = nbBlocks * BLOCKSIZE;
|
||||
}
|
||||
|
||||
/* ******************************
|
||||
|
||||
+12
-7
@@ -33,13 +33,18 @@ extern "C" {
|
||||
size_t ZSTDv05_decompress( void* dst, size_t dstCapacity,
|
||||
const void* src, size_t compressedSize);
|
||||
|
||||
/**
|
||||
ZSTDv05_getFrameSrcSize() : get the source length of a ZSTD frame
|
||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
return : the number of bytes that would be read to decompress this frame
|
||||
or an errorCode if it fails (which can be tested using ZSTDv05_isError())
|
||||
*/
|
||||
size_t ZSTDv05_findFrameCompressedSize(const void* src, size_t compressedSize);
|
||||
/**
|
||||
ZSTDv05_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.5.x format
|
||||
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||
|
||||
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||
*/
|
||||
void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||
size_t* cSize, unsigned long long* dBound);
|
||||
|
||||
/* *************************************
|
||||
* Helper functions
|
||||
|
||||
+38
-12
@@ -506,6 +506,8 @@ typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
||||
#define FSEv06_ENCODING_STATIC 2
|
||||
#define FSEv06_ENCODING_DYNAMIC 3
|
||||
|
||||
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||
|
||||
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
|
||||
13,14,15,16 };
|
||||
@@ -3240,14 +3242,12 @@ static size_t ZSTDv06_decodeSeqHeaders(int* nbSeqPtr,
|
||||
}
|
||||
|
||||
/* FSE table descriptors */
|
||||
if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are "raw", hence no header, but at least xxLog bits per type */
|
||||
{ U32 const LLtype = *ip >> 6;
|
||||
U32 const Offtype = (*ip >> 4) & 3;
|
||||
U32 const MLtype = (*ip >> 2) & 3;
|
||||
ip++;
|
||||
|
||||
/* check */
|
||||
if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
|
||||
|
||||
/* Build DTables */
|
||||
{ size_t const bhSize = ZSTDv06_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);
|
||||
if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);
|
||||
@@ -3406,7 +3406,7 @@ static size_t ZSTDv06_execSequence(BYTE* op,
|
||||
if (sequence.offset < 8) {
|
||||
/* close range match, overlap */
|
||||
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
||||
int const sub2 = dec64table[sequence.offset];
|
||||
op[0] = match[0];
|
||||
op[1] = match[1];
|
||||
@@ -3654,36 +3654,62 @@ size_t ZSTDv06_decompress(void* dst, size_t dstCapacity, const void* src, size_t
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t ZSTDv06_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||
assumes `cSize` and `dBound` are _not_ NULL */
|
||||
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||
{
|
||||
*cSize = ret;
|
||||
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
size_t remainingSize = srcSize;
|
||||
size_t nbBlocks = 0;
|
||||
blockProperties_t blockProperties = { bt_compressed, 0 };
|
||||
|
||||
/* Frame Header */
|
||||
{ size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);
|
||||
if (ZSTDv06_isError(frameHeaderSize)) return frameHeaderSize;
|
||||
if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) return ERROR(prefix_unknown);
|
||||
if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
{ size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, srcSize);
|
||||
if (ZSTDv06_isError(frameHeaderSize)) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);
|
||||
return;
|
||||
}
|
||||
if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||
return;
|
||||
}
|
||||
if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
||||
}
|
||||
|
||||
/* Loop on each block */
|
||||
while (1) {
|
||||
size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||
if (ZSTDv06_isError(cBlockSize)) return cBlockSize;
|
||||
if (ZSTDv06_isError(cBlockSize)) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||
return;
|
||||
}
|
||||
|
||||
ip += ZSTDv06_blockHeaderSize;
|
||||
remainingSize -= ZSTDv06_blockHeaderSize;
|
||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
||||
if (cBlockSize > remainingSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cBlockSize == 0) break; /* bt_end */
|
||||
|
||||
ip += cBlockSize;
|
||||
remainingSize -= cBlockSize;
|
||||
nbBlocks++;
|
||||
}
|
||||
|
||||
return ip - (const BYTE*)src;
|
||||
*cSize = ip - (const BYTE*)src;
|
||||
*dBound = nbBlocks * ZSTDv06_BLOCKSIZE_MAX;
|
||||
}
|
||||
|
||||
/*_******************************
|
||||
|
||||
+10
-5
@@ -43,12 +43,17 @@ ZSTDLIBv06_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity,
|
||||
const void* src, size_t compressedSize);
|
||||
|
||||
/**
|
||||
ZSTDv06_getFrameSrcSize() : get the source length of a ZSTD frame
|
||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
return : the number of bytes that would be read to decompress this frame
|
||||
or an errorCode if it fails (which can be tested using ZSTDv06_isError())
|
||||
ZSTDv06_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.6.x format
|
||||
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||
|
||||
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||
*/
|
||||
size_t ZSTDv06_findFrameCompressedSize(const void* src, size_t compressedSize);
|
||||
void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||
size_t* cSize, unsigned long long* dBound);
|
||||
|
||||
/* *************************************
|
||||
* Helper functions
|
||||
|
||||
+42
-13
@@ -2740,6 +2740,8 @@ typedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t;
|
||||
#define FSEv07_ENCODING_STATIC 2
|
||||
#define FSEv07_ENCODING_DYNAMIC 3
|
||||
|
||||
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||
|
||||
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
|
||||
13,14,15,16 };
|
||||
@@ -3468,14 +3470,12 @@ static size_t ZSTDv07_decodeSeqHeaders(int* nbSeqPtr,
|
||||
}
|
||||
|
||||
/* FSE table descriptors */
|
||||
if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are "raw", hence no header, but at least xxLog bits per type */
|
||||
{ U32 const LLtype = *ip >> 6;
|
||||
U32 const OFtype = (*ip >> 4) & 3;
|
||||
U32 const MLtype = (*ip >> 2) & 3;
|
||||
ip++;
|
||||
|
||||
/* check */
|
||||
if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
|
||||
|
||||
/* Build DTables */
|
||||
{ size_t const llhSize = ZSTDv07_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);
|
||||
if (ZSTDv07_isError(llhSize)) return ERROR(corruption_detected);
|
||||
@@ -3631,7 +3631,7 @@ size_t ZSTDv07_execSequence(BYTE* op,
|
||||
if (sequence.offset < 8) {
|
||||
/* close range match, overlap */
|
||||
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
||||
int const sub2 = dec64table[sequence.offset];
|
||||
op[0] = match[0];
|
||||
op[1] = match[1];
|
||||
@@ -3895,19 +3895,40 @@ size_t ZSTDv07_decompress(void* dst, size_t dstCapacity, const void* src, size_t
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||
assumes `cSize` and `dBound` are _not_ NULL */
|
||||
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||
{
|
||||
*cSize = ret;
|
||||
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
size_t remainingSize = srcSize;
|
||||
size_t nbBlocks = 0;
|
||||
|
||||
/* check */
|
||||
if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Frame Header */
|
||||
{ size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);
|
||||
if (ZSTDv07_isError(frameHeaderSize)) return frameHeaderSize;
|
||||
if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) return ERROR(prefix_unknown);
|
||||
if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
{ size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, srcSize);
|
||||
if (ZSTDv07_isError(frameHeaderSize)) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);
|
||||
return;
|
||||
}
|
||||
if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||
return;
|
||||
}
|
||||
if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
||||
}
|
||||
|
||||
@@ -3915,20 +3936,28 @@ size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
while (1) {
|
||||
blockProperties_t blockProperties;
|
||||
size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||
if (ZSTDv07_isError(cBlockSize)) return cBlockSize;
|
||||
if (ZSTDv07_isError(cBlockSize)) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||
return;
|
||||
}
|
||||
|
||||
ip += ZSTDv07_blockHeaderSize;
|
||||
remainingSize -= ZSTDv07_blockHeaderSize;
|
||||
|
||||
if (blockProperties.blockType == bt_end) break;
|
||||
|
||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
||||
if (cBlockSize > remainingSize) {
|
||||
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||
return;
|
||||
}
|
||||
|
||||
ip += cBlockSize;
|
||||
remainingSize -= cBlockSize;
|
||||
nbBlocks++;
|
||||
}
|
||||
|
||||
return ip - (const BYTE*)src;
|
||||
*cSize = ip - (const BYTE*)src;
|
||||
*dBound = nbBlocks * ZSTDv07_BLOCKSIZE_ABSOLUTEMAX;
|
||||
}
|
||||
|
||||
/*_******************************
|
||||
|
||||
+10
-5
@@ -50,12 +50,17 @@ ZSTDLIBv07_API size_t ZSTDv07_decompress( void* dst, size_t dstCapacity,
|
||||
const void* src, size_t compressedSize);
|
||||
|
||||
/**
|
||||
ZSTDv07_getFrameSrcSize() : get the source length of a ZSTD frame
|
||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
return : the number of bytes that would be read to decompress this frame
|
||||
or an errorCode if it fails (which can be tested using ZSTDv07_isError())
|
||||
ZSTDv07_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.7.x format
|
||||
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||
|
||||
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||
*/
|
||||
size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t compressedSize);
|
||||
void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||
size_t* cSize, unsigned long long* dBound);
|
||||
|
||||
/*====== Helper functions ======*/
|
||||
ZSTDLIBv07_API unsigned ZSTDv07_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
|
||||
|
||||
+654
-475
@@ -70,8 +70,8 @@ extern "C" {
|
||||
|
||||
/*------ Version ------*/
|
||||
#define ZSTD_VERSION_MAJOR 1
|
||||
#define ZSTD_VERSION_MINOR 3
|
||||
#define ZSTD_VERSION_RELEASE 8
|
||||
#define ZSTD_VERSION_MINOR 4
|
||||
#define ZSTD_VERSION_RELEASE 1
|
||||
|
||||
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
|
||||
ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */
|
||||
@@ -82,13 +82,28 @@ ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library v
|
||||
#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)
|
||||
ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */
|
||||
|
||||
/***************************************
|
||||
* Default constant
|
||||
***************************************/
|
||||
/* *************************************
|
||||
* Default constant
|
||||
***************************************/
|
||||
#ifndef ZSTD_CLEVEL_DEFAULT
|
||||
# define ZSTD_CLEVEL_DEFAULT 3
|
||||
#endif
|
||||
|
||||
/* *************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
|
||||
/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */
|
||||
#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */
|
||||
#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */
|
||||
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */
|
||||
#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0
|
||||
|
||||
#define ZSTD_BLOCKSIZELOG_MAX 17
|
||||
#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX)
|
||||
|
||||
|
||||
|
||||
/***************************************
|
||||
* Simple API
|
||||
***************************************/
|
||||
@@ -145,12 +160,21 @@ ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t
|
||||
* @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */
|
||||
ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_findFrameCompressedSize() :
|
||||
* `src` should point to the start of a ZSTD frame or skippable frame.
|
||||
* `srcSize` must be >= first frame size
|
||||
* @return : the compressed size of the first frame starting at `src`,
|
||||
* suitable to pass as `srcSize` to `ZSTD_decompress` or similar,
|
||||
* or an error code if input is invalid */
|
||||
ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
|
||||
|
||||
|
||||
/*====== Helper functions ======*/
|
||||
#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
|
||||
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
|
||||
ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
|
||||
ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
|
||||
ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */
|
||||
ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
|
||||
|
||||
|
||||
@@ -159,9 +183,14 @@ ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compres
|
||||
***************************************/
|
||||
/*= Compression context
|
||||
* When compressing many times,
|
||||
* it is recommended to allocate a context just once, and re-use it for each successive compression operation.
|
||||
* it is recommended to allocate a context just once,
|
||||
* and re-use it for each successive compression operation.
|
||||
* This will make workload friendlier for system's memory.
|
||||
* Use one context per thread for parallel execution in multi-threaded environments. */
|
||||
* Note : re-using context is just a speed / resource optimization.
|
||||
* It doesn't change the compression ratio, which remains identical.
|
||||
* Note 2 : In multi-threaded environments,
|
||||
* use one different context per thread for parallel execution.
|
||||
*/
|
||||
typedef struct ZSTD_CCtx_s ZSTD_CCtx;
|
||||
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
|
||||
ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx);
|
||||
@@ -195,279 +224,6 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
|
||||
/**************************
|
||||
* Simple dictionary API
|
||||
***************************/
|
||||
/*! ZSTD_compress_usingDict() :
|
||||
* Compression at an explicit compression level using a Dictionary.
|
||||
* A dictionary can be any arbitrary data segment (also called a prefix),
|
||||
* or a buffer with specified information (see dictBuilder/zdict.h).
|
||||
* Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
* It's intended for a dictionary used only once.
|
||||
* Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
||||
ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize,
|
||||
int compressionLevel);
|
||||
|
||||
/*! ZSTD_decompress_usingDict() :
|
||||
* Decompression using a known Dictionary.
|
||||
* Dictionary must be identical to the one used during compression.
|
||||
* Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
* It's intended for a dictionary used only once.
|
||||
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
||||
ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize);
|
||||
|
||||
|
||||
/***********************************
|
||||
* Bulk processing dictionary API
|
||||
**********************************/
|
||||
typedef struct ZSTD_CDict_s ZSTD_CDict;
|
||||
|
||||
/*! ZSTD_createCDict() :
|
||||
* When compressing multiple messages / blocks using the same dictionary, it's recommended to load it only once.
|
||||
* ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup cost.
|
||||
* ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
|
||||
* `dictBuffer` can be released after ZSTD_CDict creation, because its content is copied within CDict.
|
||||
* Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate `dictBuffer` content.
|
||||
* Note : A ZSTD_CDict can be created from an empty dictBuffer, but it is inefficient when used to compress small data. */
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
|
||||
int compressionLevel);
|
||||
|
||||
/*! ZSTD_freeCDict() :
|
||||
* Function frees memory allocated by ZSTD_createCDict(). */
|
||||
ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
|
||||
|
||||
/*! ZSTD_compress_usingCDict() :
|
||||
* Compression using a digested Dictionary.
|
||||
* Recommended when same dictionary is used multiple times.
|
||||
* Note : compression level is _decided at dictionary creation time_,
|
||||
* and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
|
||||
ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_CDict* cdict);
|
||||
|
||||
|
||||
typedef struct ZSTD_DDict_s ZSTD_DDict;
|
||||
|
||||
/*! ZSTD_createDDict() :
|
||||
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||
* dictBuffer can be released after DDict creation, as its content is copied inside DDict. */
|
||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
|
||||
|
||||
/*! ZSTD_freeDDict() :
|
||||
* Function frees memory allocated with ZSTD_createDDict() */
|
||||
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
|
||||
|
||||
/*! ZSTD_decompress_usingDDict() :
|
||||
* Decompression using a digested Dictionary.
|
||||
* Recommended when same dictionary is used multiple times. */
|
||||
ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_DDict* ddict);
|
||||
|
||||
|
||||
/****************************
|
||||
* Streaming
|
||||
****************************/
|
||||
|
||||
typedef struct ZSTD_inBuffer_s {
|
||||
const void* src; /**< start of input buffer */
|
||||
size_t size; /**< size of input buffer */
|
||||
size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */
|
||||
} ZSTD_inBuffer;
|
||||
|
||||
typedef struct ZSTD_outBuffer_s {
|
||||
void* dst; /**< start of output buffer */
|
||||
size_t size; /**< size of output buffer */
|
||||
size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */
|
||||
} ZSTD_outBuffer;
|
||||
|
||||
|
||||
|
||||
/*-***********************************************************************
|
||||
* Streaming compression - HowTo
|
||||
*
|
||||
* A ZSTD_CStream object is required to track streaming operation.
|
||||
* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
|
||||
* ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
|
||||
* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
|
||||
*
|
||||
* For parallel execution, use one separate ZSTD_CStream per thread.
|
||||
*
|
||||
* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
|
||||
*
|
||||
* Parameters are sticky : when starting a new compression on the same context,
|
||||
* it will re-use the same sticky parameters as previous compression session.
|
||||
* When in doubt, it's recommended to fully initialize the context before usage.
|
||||
* Use ZSTD_initCStream() to set the parameter to a selected compression level.
|
||||
* Use advanced API (ZSTD_CCtx_setParameter(), etc.) to set more specific parameters.
|
||||
*
|
||||
* Use ZSTD_compressStream() as many times as necessary to consume input stream.
|
||||
* The function will automatically update both `pos` fields within `input` and `output`.
|
||||
* Note that the function may not consume the entire input,
|
||||
* for example, because the output buffer is already full,
|
||||
* in which case `input.pos < input.size`.
|
||||
* The caller must check if input has been entirely consumed.
|
||||
* If not, the caller must make some room to receive more compressed data,
|
||||
* and then present again remaining input data.
|
||||
* @return : a size hint, preferred nb of bytes to use as input for next function call
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
* Note 1 : it's just a hint, to help latency a little, any value will work fine.
|
||||
* Note 2 : size hint is guaranteed to be <= ZSTD_CStreamInSize()
|
||||
*
|
||||
* At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
|
||||
* using ZSTD_flushStream(). `output->pos` will be updated.
|
||||
* Note that, if `output->size` is too small, a single invocation of ZSTD_flushStream() might not be enough (return code > 0).
|
||||
* In which case, make some room to receive more compressed data, and call again ZSTD_flushStream().
|
||||
* @return : 0 if internal buffers are entirely flushed,
|
||||
* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
*
|
||||
* ZSTD_endStream() instructs to finish a frame.
|
||||
* It will perform a flush and write frame epilogue.
|
||||
* The epilogue is required for decoders to consider a frame completed.
|
||||
* flush() operation is the same, and follows same rules as ZSTD_flushStream().
|
||||
* @return : 0 if frame fully completed and fully flushed,
|
||||
* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
*
|
||||
* *******************************************************************/
|
||||
|
||||
typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */
|
||||
/* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
|
||||
/*===== ZSTD_CStream management functions =====*/
|
||||
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
|
||||
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
|
||||
|
||||
/*===== Streaming compression functions =====*/
|
||||
ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */
|
||||
ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */
|
||||
|
||||
|
||||
|
||||
/*-***************************************************************************
|
||||
* Streaming decompression - HowTo
|
||||
*
|
||||
* A ZSTD_DStream object is required to track streaming operations.
|
||||
* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
|
||||
* ZSTD_DStream objects can be re-used multiple times.
|
||||
*
|
||||
* Use ZSTD_initDStream() to start a new decompression operation.
|
||||
* @return : recommended first input size
|
||||
* Alternatively, use advanced API to set specific properties.
|
||||
*
|
||||
* Use ZSTD_decompressStream() repetitively to consume your input.
|
||||
* The function will update both `pos` fields.
|
||||
* If `input.pos < input.size`, some input has not been consumed.
|
||||
* It's up to the caller to present again remaining data.
|
||||
* The function tries to flush all data decoded immediately, respecting output buffer size.
|
||||
* If `output.pos < output.size`, decoder has flushed everything it could.
|
||||
* But if `output.pos == output.size`, there might be some data left within internal buffers.,
|
||||
* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
|
||||
* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
|
||||
* @return : 0 when a frame is completely decoded and fully flushed,
|
||||
* or an error code, which can be tested using ZSTD_isError(),
|
||||
* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
|
||||
* the return value is a suggested next input size (just a hint for better latency)
|
||||
* that will never request more than the remaining frame size.
|
||||
* *******************************************************************************/
|
||||
|
||||
typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */
|
||||
/* For compatibility with versions <= v1.2.0, prefer differentiating them. */
|
||||
/*===== ZSTD_DStream management functions =====*/
|
||||
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
|
||||
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
|
||||
|
||||
/*===== Streaming decompression functions =====*/
|
||||
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
|
||||
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */
|
||||
ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
|
||||
|
||||
#endif /* ZSTD_H_235446 */
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* ADVANCED AND EXPERIMENTAL FUNCTIONS
|
||||
****************************************************************************************
|
||||
* The definitions in the following section are considered experimental.
|
||||
* They are provided for advanced scenarios.
|
||||
* They should never be used with a dynamic library, as prototypes may change in the future.
|
||||
* Use them only in association with static linking.
|
||||
* ***************************************************************************************/
|
||||
|
||||
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
|
||||
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Candidate API for promotion to stable status
|
||||
****************************************************************************************
|
||||
* The following symbols and constants form the "staging area" :
|
||||
* they are considered to join "stable API" by v1.4.0.
|
||||
* The proposal is written so that it can be made stable "as is",
|
||||
* though it's still possible to suggest improvements.
|
||||
* Staging is in fact last chance for changes,
|
||||
* the API is locked once reaching "stable" status.
|
||||
* ***************************************************************************************/
|
||||
|
||||
|
||||
/* === Constants === */
|
||||
|
||||
/* all magic numbers are supposed read/written to/from files/memory using little-endian convention */
|
||||
#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */
|
||||
#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */
|
||||
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */
|
||||
#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0
|
||||
|
||||
#define ZSTD_BLOCKSIZELOG_MAX 17
|
||||
#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX)
|
||||
|
||||
|
||||
/* === query limits === */
|
||||
|
||||
ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */
|
||||
|
||||
|
||||
/* === frame size === */
|
||||
|
||||
/*! ZSTD_findFrameCompressedSize() :
|
||||
* `src` should point to the start of a ZSTD frame or skippable frame.
|
||||
* `srcSize` must be >= first frame size
|
||||
* @return : the compressed size of the first frame starting at `src`,
|
||||
* suitable to pass as `srcSize` to `ZSTD_decompress` or similar,
|
||||
* or an error code if input is invalid */
|
||||
ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
|
||||
|
||||
|
||||
/* === Memory management === */
|
||||
|
||||
/*! ZSTD_sizeof_*() :
|
||||
* These functions give the _current_ memory usage of selected object.
|
||||
* Note that object memory usage can evolve (increase or decrease) over time. */
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
|
||||
/***************************************
|
||||
* Advanced compression API
|
||||
***************************************/
|
||||
@@ -503,7 +259,10 @@ typedef enum { ZSTD_fast=1,
|
||||
|
||||
typedef enum {
|
||||
|
||||
/* compression parameters */
|
||||
/* compression parameters
|
||||
* Note: When compressing with a ZSTD_CDict these parameters are superseded
|
||||
* by the parameters used to construct the ZSTD_CDict. See ZSTD_CCtx_refCDict()
|
||||
* for more info (superseded-by-cdict). */
|
||||
ZSTD_c_compressionLevel=100, /* Update all compression parameters according to pre-defined cLevel table
|
||||
* Default level is ZSTD_CLEVEL_DEFAULT==3.
|
||||
* Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.
|
||||
@@ -625,6 +384,8 @@ typedef enum {
|
||||
* ZSTD_c_format
|
||||
* ZSTD_c_forceMaxWindow
|
||||
* ZSTD_c_forceAttachDict
|
||||
* ZSTD_c_literalCompressionMode
|
||||
* ZSTD_c_targetCBlockSize
|
||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||
* note : never ever use experimentalParam? names directly;
|
||||
* also, the enums values themselves are unstable and can still change.
|
||||
@@ -632,10 +393,11 @@ typedef enum {
|
||||
ZSTD_c_experimentalParam1=500,
|
||||
ZSTD_c_experimentalParam2=10,
|
||||
ZSTD_c_experimentalParam3=1000,
|
||||
ZSTD_c_experimentalParam4=1001
|
||||
ZSTD_c_experimentalParam4=1001,
|
||||
ZSTD_c_experimentalParam5=1002,
|
||||
ZSTD_c_experimentalParam6=1003,
|
||||
} ZSTD_cParameter;
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t error;
|
||||
int lowerBound;
|
||||
@@ -677,10 +439,443 @@ ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param
|
||||
* Note 3 : Whenever all input data is provided and consumed in a single round,
|
||||
* for example with ZSTD_compress2(),
|
||||
* or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),
|
||||
* this value is automatically overriden by srcSize instead.
|
||||
* this value is automatically overridden by srcSize instead.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);
|
||||
|
||||
typedef enum {
|
||||
ZSTD_reset_session_only = 1,
|
||||
ZSTD_reset_parameters = 2,
|
||||
ZSTD_reset_session_and_parameters = 3
|
||||
} ZSTD_ResetDirective;
|
||||
|
||||
/*! ZSTD_CCtx_reset() :
|
||||
* There are 2 different things that can be reset, independently or jointly :
|
||||
* - The session : will stop compressing current frame, and make CCtx ready to start a new one.
|
||||
* Useful after an error, or to interrupt any ongoing compression.
|
||||
* Any internal data not yet flushed is cancelled.
|
||||
* Compression parameters and dictionary remain unchanged.
|
||||
* They will be used to compress next frame.
|
||||
* Resetting session never fails.
|
||||
* - The parameters : changes all parameters back to "default".
|
||||
* This removes any reference to any dictionary too.
|
||||
* Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)
|
||||
* otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())
|
||||
* - Both : similar to resetting the session, followed by resetting parameters.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);
|
||||
|
||||
/*! ZSTD_compress2() :
|
||||
* Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.
|
||||
* ZSTD_compress2() always starts a new frame.
|
||||
* Should cctx hold data from a previously unfinished frame, everything about it is forgotten.
|
||||
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
|
||||
* - The function is always blocking, returns when compression is completed.
|
||||
* Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
|
||||
* @return : compressed size written into `dst` (<= `dstCapacity),
|
||||
* or an error code if it fails (which can be tested using ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
|
||||
/***************************************
|
||||
* Advanced decompression API
|
||||
***************************************/
|
||||
|
||||
/* The advanced API pushes parameters one by one into an existing DCtx context.
|
||||
* Parameters are sticky, and remain valid for all following frames
|
||||
* using the same DCtx context.
|
||||
* It's possible to reset parameters to default values using ZSTD_DCtx_reset().
|
||||
* Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream().
|
||||
* Therefore, no new decompression function is necessary.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
|
||||
ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which
|
||||
* the streaming API will refuse to allocate memory buffer
|
||||
* in order to protect the host from unreasonable memory requirements.
|
||||
* This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
|
||||
* By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).
|
||||
* Special: value 0 means "use default maximum windowLog". */
|
||||
|
||||
/* note : additional experimental parameters are also available
|
||||
* within the experimental section of the API.
|
||||
* At the time of this writing, they include :
|
||||
* ZSTD_c_format
|
||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||
* note : never ever use experimentalParam? names directly
|
||||
*/
|
||||
ZSTD_d_experimentalParam1=1000
|
||||
|
||||
} ZSTD_dParameter;
|
||||
|
||||
/*! ZSTD_dParam_getBounds() :
|
||||
* All parameters must belong to an interval with lower and upper bounds,
|
||||
* otherwise they will either trigger an error or be automatically clamped.
|
||||
* @return : a structure, ZSTD_bounds, which contains
|
||||
* - an error status field, which must be tested using ZSTD_isError()
|
||||
* - both lower and upper bounds, inclusive
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);
|
||||
|
||||
/*! ZSTD_DCtx_setParameter() :
|
||||
* Set one compression parameter, selected by enum ZSTD_dParameter.
|
||||
* All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().
|
||||
* Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
|
||||
* Setting a parameter is only possible during frame initialization (before starting decompression).
|
||||
* @return : 0, or an error code (which can be tested using ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);
|
||||
|
||||
/*! ZSTD_DCtx_reset() :
|
||||
* Return a DCtx to clean state.
|
||||
* Session and parameters can be reset jointly or separately.
|
||||
* Parameters can only be reset when no active frame is being decompressed.
|
||||
* @return : 0, or an error code, which can be tested with ZSTD_isError()
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
|
||||
|
||||
|
||||
/****************************
|
||||
* Streaming
|
||||
****************************/
|
||||
|
||||
typedef struct ZSTD_inBuffer_s {
|
||||
const void* src; /**< start of input buffer */
|
||||
size_t size; /**< size of input buffer */
|
||||
size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */
|
||||
} ZSTD_inBuffer;
|
||||
|
||||
typedef struct ZSTD_outBuffer_s {
|
||||
void* dst; /**< start of output buffer */
|
||||
size_t size; /**< size of output buffer */
|
||||
size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */
|
||||
} ZSTD_outBuffer;
|
||||
|
||||
|
||||
|
||||
/*-***********************************************************************
|
||||
* Streaming compression - HowTo
|
||||
*
|
||||
* A ZSTD_CStream object is required to track streaming operation.
|
||||
* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
|
||||
* ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
|
||||
* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
|
||||
*
|
||||
* For parallel execution, use one separate ZSTD_CStream per thread.
|
||||
*
|
||||
* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
|
||||
*
|
||||
* Parameters are sticky : when starting a new compression on the same context,
|
||||
* it will re-use the same sticky parameters as previous compression session.
|
||||
* When in doubt, it's recommended to fully initialize the context before usage.
|
||||
* Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),
|
||||
* ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to
|
||||
* set more specific parameters, the pledged source size, or load a dictionary.
|
||||
*
|
||||
* Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to
|
||||
* consume input stream. The function will automatically update both `pos`
|
||||
* fields within `input` and `output`.
|
||||
* Note that the function may not consume the entire input, for example, because
|
||||
* the output buffer is already full, in which case `input.pos < input.size`.
|
||||
* The caller must check if input has been entirely consumed.
|
||||
* If not, the caller must make some room to receive more compressed data,
|
||||
* and then present again remaining input data.
|
||||
* note: ZSTD_e_continue is guaranteed to make some forward progress when called,
|
||||
* but doesn't guarantee maximal forward progress. This is especially relevant
|
||||
* when compressing with multiple threads. The call won't block if it can
|
||||
* consume some input, but if it can't it will wait for some, but not all,
|
||||
* output to be flushed.
|
||||
* @return : provides a minimum amount of data remaining to be flushed from internal buffers
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
*
|
||||
* At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
|
||||
* using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.
|
||||
* Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).
|
||||
* In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.
|
||||
* You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the
|
||||
* operation.
|
||||
* note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will
|
||||
* block until the flush is complete or the output buffer is full.
|
||||
* @return : 0 if internal buffers are entirely flushed,
|
||||
* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
*
|
||||
* Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.
|
||||
* It will perform a flush and write frame epilogue.
|
||||
* The epilogue is required for decoders to consider a frame completed.
|
||||
* flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.
|
||||
* You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to
|
||||
* start a new frame.
|
||||
* note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will
|
||||
* block until the flush is complete or the output buffer is full.
|
||||
* @return : 0 if frame fully completed and fully flushed,
|
||||
* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
*
|
||||
* *******************************************************************/
|
||||
|
||||
typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */
|
||||
/* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
|
||||
/*===== ZSTD_CStream management functions =====*/
|
||||
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
|
||||
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
|
||||
|
||||
/*===== Streaming compression functions =====*/
|
||||
typedef enum {
|
||||
ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */
|
||||
ZSTD_e_flush=1, /* flush any data provided so far,
|
||||
* it creates (at least) one new block, that can be decoded immediately on reception;
|
||||
* frame will continue: any future data can still reference previously compressed data, improving compression.
|
||||
* note : multithreaded compression will block to flush as much output as possible. */
|
||||
ZSTD_e_end=2 /* flush any remaining data _and_ close current frame.
|
||||
* note that frame is only closed after compressed data is fully flushed (return value == 0).
|
||||
* After that point, any additional data starts a new frame.
|
||||
* note : each frame is independent (does not reference any content from previous frame).
|
||||
: note : multithreaded compression will block to flush as much output as possible. */
|
||||
} ZSTD_EndDirective;
|
||||
|
||||
/*! ZSTD_compressStream2() :
|
||||
* Behaves about the same as ZSTD_compressStream, with additional control on end directive.
|
||||
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
|
||||
* - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
|
||||
* - output->pos must be <= dstCapacity, input->pos must be <= srcSize
|
||||
* - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
|
||||
* - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
|
||||
* - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
|
||||
* and then immediately returns, just indicating that there is some data remaining to be flushed.
|
||||
* The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
|
||||
* - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
|
||||
* - @return provides a minimum amount of data remaining to be flushed from internal buffers
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
* if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
|
||||
* This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
|
||||
* For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
|
||||
* - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
|
||||
* only ZSTD_e_end or ZSTD_e_flush operations are allowed.
|
||||
* Before starting a new compression job, or changing compression parameters,
|
||||
* it is required to fully flush internal buffers.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective endOp);
|
||||
|
||||
|
||||
/* These buffer sizes are softly recommended.
|
||||
* They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output.
|
||||
* Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(),
|
||||
* reducing the amount of memory shuffling and buffering, resulting in minor performance savings.
|
||||
*
|
||||
* However, note that these recommendations are from the perspective of a C caller program.
|
||||
* If the streaming interface is invoked from some other language,
|
||||
* especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo,
|
||||
* a major performance rule is to reduce crossing such interface to an absolute minimum.
|
||||
* It's not rare that performance ends being spent more into the interface, rather than compression itself.
|
||||
* In which cases, prefer using large buffers, as large as practical,
|
||||
* for both input and output, to reduce the nb of roundtrips.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */
|
||||
ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */
|
||||
|
||||
|
||||
/* *****************************************************************************
|
||||
* This following is a legacy streaming API.
|
||||
* It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2().
|
||||
* It is redundant, but remains fully supported.
|
||||
* Advanced parameters and dictionary compression can only be used through the
|
||||
* new API.
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* Equivalent to:
|
||||
*
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
|
||||
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
|
||||
/*!
|
||||
* Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).
|
||||
* NOTE: The return value is different. ZSTD_compressStream() returns a hint for
|
||||
* the next read size (if non-zero and not an error). ZSTD_compressStream2()
|
||||
* returns the minimum nb of bytes left to flush (if non-zero and not an error).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */
|
||||
ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */
|
||||
ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
|
||||
|
||||
/*-***************************************************************************
|
||||
* Streaming decompression - HowTo
|
||||
*
|
||||
* A ZSTD_DStream object is required to track streaming operations.
|
||||
* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
|
||||
* ZSTD_DStream objects can be re-used multiple times.
|
||||
*
|
||||
* Use ZSTD_initDStream() to start a new decompression operation.
|
||||
* @return : recommended first input size
|
||||
* Alternatively, use advanced API to set specific properties.
|
||||
*
|
||||
* Use ZSTD_decompressStream() repetitively to consume your input.
|
||||
* The function will update both `pos` fields.
|
||||
* If `input.pos < input.size`, some input has not been consumed.
|
||||
* It's up to the caller to present again remaining data.
|
||||
* The function tries to flush all data decoded immediately, respecting output buffer size.
|
||||
* If `output.pos < output.size`, decoder has flushed everything it could.
|
||||
* But if `output.pos == output.size`, there might be some data left within internal buffers.,
|
||||
* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
|
||||
* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
|
||||
* @return : 0 when a frame is completely decoded and fully flushed,
|
||||
* or an error code, which can be tested using ZSTD_isError(),
|
||||
* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
|
||||
* the return value is a suggested next input size (just a hint for better latency)
|
||||
* that will never request more than the remaining frame size.
|
||||
* *******************************************************************************/
|
||||
|
||||
typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */
|
||||
/* For compatibility with versions <= v1.2.0, prefer differentiating them. */
|
||||
/*===== ZSTD_DStream management functions =====*/
|
||||
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
|
||||
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
|
||||
|
||||
/*===== Streaming decompression functions =====*/
|
||||
|
||||
/* This function is redundant with the advanced API and equivalent to:
|
||||
*
|
||||
* ZSTD_DCtx_reset(zds);
|
||||
* ZSTD_DCtx_refDDict(zds, NULL);
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */
|
||||
ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
|
||||
|
||||
|
||||
/**************************
|
||||
* Simple dictionary API
|
||||
***************************/
|
||||
/*! ZSTD_compress_usingDict() :
|
||||
* Compression at an explicit compression level using a Dictionary.
|
||||
* A dictionary can be any arbitrary data segment (also called a prefix),
|
||||
* or a buffer with specified information (see dictBuilder/zdict.h).
|
||||
* Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
* It's intended for a dictionary used only once.
|
||||
* Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
||||
ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize,
|
||||
int compressionLevel);
|
||||
|
||||
/*! ZSTD_decompress_usingDict() :
|
||||
* Decompression using a known Dictionary.
|
||||
* Dictionary must be identical to the one used during compression.
|
||||
* Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
* It's intended for a dictionary used only once.
|
||||
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
||||
ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize);
|
||||
|
||||
|
||||
/***********************************
|
||||
* Bulk processing dictionary API
|
||||
**********************************/
|
||||
typedef struct ZSTD_CDict_s ZSTD_CDict;
|
||||
|
||||
/*! ZSTD_createCDict() :
|
||||
* When compressing multiple messages / blocks using the same dictionary, it's recommended to load it only once.
|
||||
* ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup cost.
|
||||
* ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
|
||||
* `dictBuffer` can be released after ZSTD_CDict creation, because its content is copied within CDict.
|
||||
* Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate `dictBuffer` content.
|
||||
* Note : A ZSTD_CDict can be created from an empty dictBuffer, but it is inefficient when used to compress small data. */
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
|
||||
int compressionLevel);
|
||||
|
||||
/*! ZSTD_freeCDict() :
|
||||
* Function frees memory allocated by ZSTD_createCDict(). */
|
||||
ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
|
||||
|
||||
/*! ZSTD_compress_usingCDict() :
|
||||
* Compression using a digested Dictionary.
|
||||
* Recommended when same dictionary is used multiple times.
|
||||
* Note : compression level is _decided at dictionary creation time_,
|
||||
* and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
|
||||
ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_CDict* cdict);
|
||||
|
||||
|
||||
typedef struct ZSTD_DDict_s ZSTD_DDict;
|
||||
|
||||
/*! ZSTD_createDDict() :
|
||||
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||
* dictBuffer can be released after DDict creation, as its content is copied inside DDict. */
|
||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
|
||||
|
||||
/*! ZSTD_freeDDict() :
|
||||
* Function frees memory allocated with ZSTD_createDDict() */
|
||||
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
|
||||
|
||||
/*! ZSTD_decompress_usingDDict() :
|
||||
* Decompression using a digested Dictionary.
|
||||
* Recommended when same dictionary is used multiple times. */
|
||||
ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_DDict* ddict);
|
||||
|
||||
|
||||
/********************************
|
||||
* Dictionary helper functions
|
||||
*******************************/
|
||||
|
||||
/*! ZSTD_getDictID_fromDict() :
|
||||
* Provides the dictID stored within dictionary.
|
||||
* if @return == 0, the dictionary is not conformant with Zstandard specification.
|
||||
* It can still be loaded, but as a content-only dictionary. */
|
||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
|
||||
|
||||
/*! ZSTD_getDictID_fromDDict() :
|
||||
* Provides the dictID of the dictionary loaded into `ddict`.
|
||||
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
||||
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
||||
|
||||
/*! ZSTD_getDictID_fromFrame() :
|
||||
* Provides the dictID required to decompressed the frame stored within `src`.
|
||||
* If @return == 0, the dictID could not be decoded.
|
||||
* This could for one of the following reasons :
|
||||
* - The frame does not require a dictionary to be decoded (most common case).
|
||||
* - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
|
||||
* Note : this use case also happens when using a non-conformant dictionary.
|
||||
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
|
||||
* - This is not a Zstandard frame.
|
||||
* When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */
|
||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Advanced dictionary and prefix API
|
||||
*
|
||||
* This API allows dictionaries to be used with ZSTD_compress2(),
|
||||
* ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
|
||||
* only reset with the context is reset with ZSTD_reset_parameters or
|
||||
* ZSTD_reset_session_and_parameters. Prefixes are single-use.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*! ZSTD_CCtx_loadDictionary() :
|
||||
* Create an internal CDict from `dict` buffer.
|
||||
* Decompression will have to use same dictionary.
|
||||
@@ -703,7 +898,9 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
|
||||
/*! ZSTD_CCtx_refCDict() :
|
||||
* Reference a prepared dictionary, to be used for all next compressed frames.
|
||||
* Note that compression parameters are enforced from within CDict,
|
||||
* and supercede any compression parameter previously set within CCtx.
|
||||
* and supersede any compression parameter previously set within CCtx.
|
||||
* The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
|
||||
* The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
|
||||
* The dictionary will remain valid for future compressed frames using same CCtx.
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
* Special : Referencing a NULL CDict means "return to no-dictionary mode".
|
||||
@@ -733,136 +930,6 @@ ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
|
||||
const void* prefix, size_t prefixSize);
|
||||
|
||||
|
||||
typedef enum {
|
||||
ZSTD_reset_session_only = 1,
|
||||
ZSTD_reset_parameters = 2,
|
||||
ZSTD_reset_session_and_parameters = 3
|
||||
} ZSTD_ResetDirective;
|
||||
|
||||
/*! ZSTD_CCtx_reset() :
|
||||
* There are 2 different things that can be reset, independently or jointly :
|
||||
* - The session : will stop compressing current frame, and make CCtx ready to start a new one.
|
||||
* Useful after an error, or to interrupt any ongoing compression.
|
||||
* Any internal data not yet flushed is cancelled.
|
||||
* Compression parameters and dictionary remain unchanged.
|
||||
* They will be used to compress next frame.
|
||||
* Resetting session never fails.
|
||||
* - The parameters : changes all parameters back to "default".
|
||||
* This removes any reference to any dictionary too.
|
||||
* Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)
|
||||
* otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())
|
||||
* - Both : similar to resetting the session, followed by resetting parameters.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);
|
||||
|
||||
|
||||
|
||||
/*! ZSTD_compress2() :
|
||||
* Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.
|
||||
* ZSTD_compress2() always starts a new frame.
|
||||
* Should cctx hold data from a previously unfinished frame, everything about it is forgotten.
|
||||
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
|
||||
* - The function is always blocking, returns when compression is completed.
|
||||
* Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
|
||||
* @return : compressed size written into `dst` (<= `dstCapacity),
|
||||
* or an error code if it fails (which can be tested using ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
typedef enum {
|
||||
ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */
|
||||
ZSTD_e_flush=1, /* flush any data provided so far,
|
||||
* it creates (at least) one new block, that can be decoded immediately on reception;
|
||||
* frame will continue: any future data can still reference previously compressed data, improving compression. */
|
||||
ZSTD_e_end=2 /* flush any remaining data _and_ close current frame.
|
||||
* note that frame is only closed after compressed data is fully flushed (return value == 0).
|
||||
* After that point, any additional data starts a new frame.
|
||||
* note : each frame is independent (does not reference any content from previous frame). */
|
||||
} ZSTD_EndDirective;
|
||||
|
||||
/*! ZSTD_compressStream2() :
|
||||
* Behaves about the same as ZSTD_compressStream, with additional control on end directive.
|
||||
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
|
||||
* - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
|
||||
* - outpot->pos must be <= dstCapacity, input->pos must be <= srcSize
|
||||
* - outpot->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
|
||||
* - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
|
||||
* - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
|
||||
* and then immediately returns, just indicating that there is some data remaining to be flushed.
|
||||
* The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
|
||||
* - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
|
||||
* - @return provides a minimum amount of data remaining to be flushed from internal buffers
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
* if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
|
||||
* This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
|
||||
* For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
|
||||
* - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
|
||||
* only ZSTD_e_end or ZSTD_e_flush operations are allowed.
|
||||
* Before starting a new compression job, or changing compression parameters,
|
||||
* it is required to fully flush internal buffers.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective endOp);
|
||||
|
||||
|
||||
|
||||
/* ============================== */
|
||||
/* Advanced decompression API */
|
||||
/* ============================== */
|
||||
|
||||
/* The advanced API pushes parameters one by one into an existing DCtx context.
|
||||
* Parameters are sticky, and remain valid for all following frames
|
||||
* using the same DCtx context.
|
||||
* It's possible to reset parameters to default values using ZSTD_DCtx_reset().
|
||||
* Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream().
|
||||
* Therefore, no new decompression function is necessary.
|
||||
*/
|
||||
|
||||
|
||||
typedef enum {
|
||||
|
||||
ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which
|
||||
* the streaming API will refuse to allocate memory buffer
|
||||
* in order to protect the host from unreasonable memory requirements.
|
||||
* This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
|
||||
* By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) */
|
||||
|
||||
/* note : additional experimental parameters are also available
|
||||
* within the experimental section of the API.
|
||||
* At the time of this writing, they include :
|
||||
* ZSTD_c_format
|
||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||
* note : never ever use experimentalParam? names directly
|
||||
*/
|
||||
ZSTD_d_experimentalParam1=1000
|
||||
|
||||
} ZSTD_dParameter;
|
||||
|
||||
|
||||
/*! ZSTD_dParam_getBounds() :
|
||||
* All parameters must belong to an interval with lower and upper bounds,
|
||||
* otherwise they will either trigger an error or be automatically clamped.
|
||||
* @return : a structure, ZSTD_bounds, which contains
|
||||
* - an error status field, which must be tested using ZSTD_isError()
|
||||
* - both lower and upper bounds, inclusive
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);
|
||||
|
||||
/*! ZSTD_DCtx_setParameter() :
|
||||
* Set one compression parameter, selected by enum ZSTD_dParameter.
|
||||
* All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().
|
||||
* Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
|
||||
* Setting a parameter is only possible during frame initialization (before starting decompression).
|
||||
* @return : 0, or an error code (which can be tested using ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);
|
||||
|
||||
|
||||
/*! ZSTD_DCtx_loadDictionary() :
|
||||
* Create an internal DDict from dict buffer,
|
||||
* to be used to decompress next frames.
|
||||
@@ -910,15 +977,32 @@ ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,
|
||||
const void* prefix, size_t prefixSize);
|
||||
|
||||
/*! ZSTD_DCtx_reset() :
|
||||
* Return a DCtx to clean state.
|
||||
* Session and parameters can be reset jointly or separately.
|
||||
* Parameters can only be reset when no active frame is being decompressed.
|
||||
* @return : 0, or an error code, which can be tested with ZSTD_isError()
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
|
||||
/* === Memory management === */
|
||||
|
||||
/*! ZSTD_sizeof_*() :
|
||||
* These functions give the _current_ memory usage of selected object.
|
||||
* Note that object memory usage can evolve (increase or decrease) over time. */
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
#endif /* ZSTD_H_235446 */
|
||||
|
||||
|
||||
/* **************************************************************************************
|
||||
* ADVANCED AND EXPERIMENTAL FUNCTIONS
|
||||
****************************************************************************************
|
||||
* The definitions in the following section are considered experimental.
|
||||
* They are provided for advanced scenarios.
|
||||
* They should never be used with a dynamic library, as prototypes may change in the future.
|
||||
* Use them only in association with static linking.
|
||||
* ***************************************************************************************/
|
||||
|
||||
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
|
||||
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
|
||||
|
||||
/****************************************************************************************
|
||||
* experimental API (static linking only)
|
||||
@@ -962,7 +1046,7 @@ ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
|
||||
#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame
|
||||
* requiring larger than (1<<ZSTD_WINDOWLOG_LIMIT_DEFAULT) window size,
|
||||
* to preserve host's memory from unreasonable requirements.
|
||||
* This limit can be overriden using ZSTD_DCtx_setParameter(,ZSTD_d_windowLogMax,).
|
||||
* This limit can be overridden using ZSTD_DCtx_setParameter(,ZSTD_d_windowLogMax,).
|
||||
* The limit does not apply for one-pass decoders (such as ZSTD_decompress()), since no additional memory is allocated */
|
||||
|
||||
|
||||
@@ -976,6 +1060,10 @@ ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
|
||||
#define ZSTD_LDM_HASHRATELOG_MIN 0
|
||||
#define ZSTD_LDM_HASHRATELOG_MAX (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
|
||||
|
||||
/* Advanced parameter bounds */
|
||||
#define ZSTD_TARGETCBLOCKSIZE_MIN 64
|
||||
#define ZSTD_TARGETCBLOCKSIZE_MAX ZSTD_BLOCKSIZE_MAX
|
||||
|
||||
/* internal */
|
||||
#define ZSTD_HASHLOG3_MAX 17
|
||||
|
||||
@@ -1064,15 +1152,24 @@ typedef enum {
|
||||
ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */
|
||||
} ZSTD_dictAttachPref_e;
|
||||
|
||||
typedef enum {
|
||||
ZSTD_lcm_auto = 0, /**< Automatically determine the compression mode based on the compression level.
|
||||
* Negative compression levels will be uncompressed, and positive compression
|
||||
* levels will be compressed. */
|
||||
ZSTD_lcm_huffman = 1, /**< Always attempt Huffman compression. Uncompressed literals will still be
|
||||
* emitted if Huffman compression is not profitable. */
|
||||
ZSTD_lcm_uncompressed = 2, /**< Always emit uncompressed literals. */
|
||||
} ZSTD_literalCompressionMode_e;
|
||||
|
||||
|
||||
/***************************************
|
||||
* Frame size functions
|
||||
***************************************/
|
||||
|
||||
/*! ZSTD_findDecompressedSize() :
|
||||
* `src` should point the start of a series of ZSTD encoded and/or skippable frames
|
||||
* `src` should point to the start of a series of ZSTD encoded and/or skippable frames
|
||||
* `srcSize` must be the _exact_ size of this series
|
||||
* (i.e. there should be a frame boundary exactly at `srcSize` bytes after `src`)
|
||||
* (i.e. there should be a frame boundary at `src + srcSize`)
|
||||
* @return : - decompressed size of all data in all successive frames
|
||||
* - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN
|
||||
* - if an error occurred: ZSTD_CONTENTSIZE_ERROR
|
||||
@@ -1092,6 +1189,21 @@ typedef enum {
|
||||
* however it does mean that all frame data must be present and valid. */
|
||||
ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_decompressBound() :
|
||||
* `src` should point to the start of a series of ZSTD encoded and/or skippable frames
|
||||
* `srcSize` must be the _exact_ size of this series
|
||||
* (i.e. there should be a frame boundary at `src + srcSize`)
|
||||
* @return : - upper-bound for the decompressed size of all data in all successive frames
|
||||
* - if an error occured: ZSTD_CONTENTSIZE_ERROR
|
||||
*
|
||||
* note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame.
|
||||
* note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
|
||||
* in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.
|
||||
* note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:
|
||||
* upper-bound = # blocks * min(128 KB, Window_Size)
|
||||
*/
|
||||
ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_frameHeaderSize() :
|
||||
* srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
|
||||
* @return : size of the Frame Header,
|
||||
@@ -1110,7 +1222,7 @@ ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
|
||||
* It will also consider src size to be arbitrarily "large", which is worst case.
|
||||
* If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation.
|
||||
* ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
|
||||
* ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
* ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
* Note : CCtx size estimation is only correct for single-threaded compression. */
|
||||
ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
@@ -1122,7 +1234,7 @@ ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
|
||||
* It will also consider src size to be arbitrarily "large", which is worst case.
|
||||
* If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
|
||||
* ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
|
||||
* ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
* ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
* Note : CStream size estimation is only correct for single-threaded compression.
|
||||
* ZSTD_DStream memory budget depends on window Size.
|
||||
* This information can be passed manually, using ZSTD_estimateDStreamSize,
|
||||
@@ -1226,22 +1338,26 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictS
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||
|
||||
/*! ZSTD_getCParams() :
|
||||
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
||||
* `estimatedSrcSize` value is optional, select 0 if not known */
|
||||
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
||||
* `estimatedSrcSize` value is optional, select 0 if not known */
|
||||
ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_getParams() :
|
||||
* same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
|
||||
* All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */
|
||||
* same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
|
||||
* All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */
|
||||
ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_checkCParams() :
|
||||
* Ensure param values remain within authorized range */
|
||||
* Ensure param values remain within authorized range.
|
||||
* @return 0 on success, or an error code (can be checked with ZSTD_isError()) */
|
||||
ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
|
||||
/*! ZSTD_adjustCParams() :
|
||||
* optimize params for a given `srcSize` and `dictSize`.
|
||||
* both values are optional, select `0` if unknown. */
|
||||
* `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
* `dictSize` must be `0` when there is no dictionary.
|
||||
* cPar can be invalid : all parameters will be clamped within valid range in the @return struct.
|
||||
* This function never fails (wide contract) */
|
||||
ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_compress_advanced() :
|
||||
@@ -1314,6 +1430,17 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
|
||||
* See the comments on that enum for an explanation of the feature. */
|
||||
#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4
|
||||
|
||||
/* Controls how the literals are compressed (default is auto).
|
||||
* The value must be of type ZSTD_literalCompressionMode_e.
|
||||
* See ZSTD_literalCompressionMode_t enum definition for details.
|
||||
*/
|
||||
#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5
|
||||
|
||||
/* Tries to fit compressed block size to be around targetCBlockSize.
|
||||
* No target when targetCBlockSize == 0.
|
||||
* There is no guarantee on compressed block size (default:0) */
|
||||
#define ZSTD_c_targetCBlockSize ZSTD_c_experimentalParam6
|
||||
|
||||
/*! ZSTD_CCtx_getParameter() :
|
||||
* Get the requested compression parameter value, selected by enum ZSTD_cParameter,
|
||||
* and store it into int* value.
|
||||
@@ -1325,10 +1452,10 @@ ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param
|
||||
/*! ZSTD_CCtx_params :
|
||||
* Quick howto :
|
||||
* - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
|
||||
* - ZSTD_CCtxParam_setParameter() : Push parameters one by one into
|
||||
* an existing ZSTD_CCtx_params structure.
|
||||
* This is similar to
|
||||
* ZSTD_CCtx_setParameter().
|
||||
* - ZSTD_CCtxParams_setParameter() : Push parameters one by one into
|
||||
* an existing ZSTD_CCtx_params structure.
|
||||
* This is similar to
|
||||
* ZSTD_CCtx_setParameter().
|
||||
* - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to
|
||||
* an existing CCtx.
|
||||
* These parameters will be applied to
|
||||
@@ -1359,20 +1486,20 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compre
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
|
||||
|
||||
/*! ZSTD_CCtxParam_setParameter() :
|
||||
/*! ZSTD_CCtxParams_setParameter() :
|
||||
* Similar to ZSTD_CCtx_setParameter.
|
||||
* Set one compression parameter, selected by enum ZSTD_cParameter.
|
||||
* Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
|
||||
|
||||
/*! ZSTD_CCtxParam_getParameter() :
|
||||
/*! ZSTD_CCtxParams_getParameter() :
|
||||
* Similar to ZSTD_CCtx_getParameter.
|
||||
* Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParam_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
||||
|
||||
/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
|
||||
* Apply a set of ZSTD_CCtx_params to the compression context.
|
||||
@@ -1415,31 +1542,6 @@ ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
|
||||
* it must remain read accessible throughout the lifetime of DDict */
|
||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
|
||||
|
||||
|
||||
/*! ZSTD_getDictID_fromDict() :
|
||||
* Provides the dictID stored within dictionary.
|
||||
* if @return == 0, the dictionary is not conformant with Zstandard specification.
|
||||
* It can still be loaded, but as a content-only dictionary. */
|
||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
|
||||
|
||||
/*! ZSTD_getDictID_fromDDict() :
|
||||
* Provides the dictID of the dictionary loaded into `ddict`.
|
||||
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
||||
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
||||
|
||||
/*! ZSTD_getDictID_fromFrame() :
|
||||
* Provides the dictID required to decompressed the frame stored within `src`.
|
||||
* If @return == 0, the dictID could not be decoded.
|
||||
* This could for one of the following reasons :
|
||||
* - The frame does not require a dictionary to be decoded (most common case).
|
||||
* - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
|
||||
* Note : this use case also happens when using a non-conformant dictionary.
|
||||
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
|
||||
* - This is not a Zstandard frame.
|
||||
* When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */
|
||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_DCtx_loadDictionary_byReference() :
|
||||
* Same as ZSTD_DCtx_loadDictionary(),
|
||||
* but references `dict` content instead of copying it into `dctx`.
|
||||
@@ -1501,14 +1603,68 @@ ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
|
||||
********************************************************************/
|
||||
|
||||
/*===== Advanced Streaming compression functions =====*/
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct. If it is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, "0" also disables frame content size field. It may be enabled in the future. */
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.*/
|
||||
/**! ZSTD_initCStream_srcSize() :
|
||||
* This function is deprecated, and equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
|
||||
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
||||
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
||||
*
|
||||
* pledgedSrcSize must be correct. If it is not known at init time, use
|
||||
* ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
|
||||
* "0" also disables frame content size field. It may be enabled in the future.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize);
|
||||
/**! ZSTD_initCStream_usingDict() :
|
||||
* This function is deprecated, and is equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
||||
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
|
||||
*
|
||||
* Creates of an internal CDict (incompatible with static CCtx), except if
|
||||
* dict == NULL or dictSize < 8, in which case no dict is used.
|
||||
* Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if
|
||||
* it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel);
|
||||
/**! ZSTD_initCStream_advanced() :
|
||||
* This function is deprecated, and is approximately equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_setZstdParams(zcs, params); // Set the zstd params and leave the rest as-is
|
||||
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
||||
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
|
||||
*
|
||||
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
|
||||
* value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy. */
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize); /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters. pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. */
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize);
|
||||
/**! ZSTD_initCStream_usingCDict() :
|
||||
* This function is deprecated, and equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_refCDict(zcs, cdict);
|
||||
*
|
||||
* note : cdict will just be referenced, and must outlive compression session
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
|
||||
/**! ZSTD_initCStream_usingCDict_advanced() :
|
||||
* This function is deprecated, and is approximately equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_setZstdFrameParams(zcs, fParams); // Set the zstd frame params and leave the rest as-is
|
||||
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
||||
* ZSTD_CCtx_refCDict(zcs, cdict);
|
||||
*
|
||||
* same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
|
||||
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
|
||||
* value ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize);
|
||||
|
||||
/*! ZSTD_resetCStream() :
|
||||
* This function is deprecated, and is equivalent to:
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
||||
*
|
||||
* start a new frame, using same parameters from previous frame.
|
||||
* This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
|
||||
* Note that zcs must be init at least once before using ZSTD_resetCStream().
|
||||
@@ -1555,9 +1711,32 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
|
||||
|
||||
|
||||
/*===== Advanced Streaming decompression functions =====*/
|
||||
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: no dictionary will be used if dict == NULL or dictSize < 8 */
|
||||
ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict is referenced, it must outlive decompression session */
|
||||
ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */
|
||||
/**
|
||||
* This function is deprecated, and is equivalent to:
|
||||
*
|
||||
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
* ZSTD_DCtx_loadDictionary(zds, dict, dictSize);
|
||||
*
|
||||
* note: no dictionary will be used if dict == NULL or dictSize < 8
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
|
||||
/**
|
||||
* This function is deprecated, and is equivalent to:
|
||||
*
|
||||
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
* ZSTD_DCtx_refDDict(zds, ddict);
|
||||
*
|
||||
* note : ddict is referenced, it must outlive decompression session
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
|
||||
/**
|
||||
* This function is deprecated, and is equivalent to:
|
||||
*
|
||||
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
*
|
||||
* re-use decompression parameters from previous init; saves dictionary loading
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
@@ -1696,7 +1875,7 @@ typedef struct {
|
||||
unsigned checksumFlag;
|
||||
} ZSTD_frameHeader;
|
||||
|
||||
/** ZSTD_getFrameHeader() :
|
||||
/*! ZSTD_getFrameHeader() :
|
||||
* decode Frame Header, or requires larger `srcSize`.
|
||||
* @return : 0, `zfhPtr` is correctly filled,
|
||||
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
|
||||
|
||||
@@ -33,4 +33,5 @@ afl
|
||||
|
||||
# Misc files
|
||||
*.bat
|
||||
!windres/generate_res.bat
|
||||
dirTest*
|
||||
|
||||
+10
-10
@@ -51,7 +51,7 @@ endif
|
||||
CFLAGS ?= -O3
|
||||
DEBUGFLAGS+=-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \
|
||||
-Wstrict-prototypes -Wundef -Wpointer-arith \
|
||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||
-Wredundant-decls -Wmissing-prototypes -Wc++-compat
|
||||
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||
@@ -165,7 +165,7 @@ $(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP)
|
||||
zstd : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) $(LZ4CPP)
|
||||
zstd : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD)
|
||||
zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
||||
zstd : $(ZSTDLIB_FILES) zstdcli.o util.o fileio.o benchfn.o benchzstd.o datagen.o dibio.o
|
||||
zstd : $(ZSTDLIB_FILES) zstdcli.o util.o timefn.o fileio.o benchfn.o benchzstd.o datagen.o dibio.o
|
||||
@echo "$(THREAD_MSG)"
|
||||
@echo "$(ZLIB_MSG)"
|
||||
@echo "$(LZMA_MSG)"
|
||||
@@ -183,13 +183,13 @@ zstd-release: zstd
|
||||
zstd32 : CPPFLAGS += $(THREAD_CPP)
|
||||
zstd32 : LDFLAGS += $(THREAD_LD)
|
||||
zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
||||
zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c
|
||||
zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c timefn.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c
|
||||
ifneq (,$(filter Windows%,$(OS)))
|
||||
windres/generate_res.bat
|
||||
endif
|
||||
$(CC) -m32 $(FLAGS) $^ $(RES32_FILE) -o $@$(EXT)
|
||||
|
||||
zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o util.o fileio.c benchfn.o benchzstd.o datagen.o dibio.o
|
||||
zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o util.o fileio.c benchfn.o benchzstd.o timefn.o datagen.o dibio.o
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS)
|
||||
|
||||
zstd-nomt : THREAD_CPP :=
|
||||
@@ -222,13 +222,13 @@ zstd-pgo :
|
||||
|
||||
# minimal target, with only zstd compression and decompression. no bench. no legacy.
|
||||
zstd-small: CFLAGS = -Os -s
|
||||
zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c util.c fileio.c
|
||||
zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c util.c timefn.c fileio.c
|
||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o $@$(EXT)
|
||||
|
||||
zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c util.c fileio.c
|
||||
zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c util.c timefn.c fileio.c
|
||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o $@$(EXT)
|
||||
|
||||
zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c util.c fileio.c
|
||||
zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c util.c timefn.c fileio.c
|
||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT)
|
||||
|
||||
zstdmt: zstd
|
||||
@@ -265,9 +265,9 @@ man: zstd.1 zstdgrep.1 zstdless.1
|
||||
|
||||
.PHONY: clean-man
|
||||
clean-man:
|
||||
rm zstd.1
|
||||
rm zstdgrep.1
|
||||
rm zstdless.1
|
||||
$(RM) zstd.1
|
||||
$(RM) zstdgrep.1
|
||||
$(RM) zstdless.1
|
||||
|
||||
.PHONY: preview-man
|
||||
preview-man: clean-man man
|
||||
|
||||
+2
-2
@@ -37,7 +37,7 @@ There are however other Makefile targets that create different variations of CLI
|
||||
`.gz` support is automatically enabled when `zlib` library is detected at build time.
|
||||
It's possible to disable `.gz` support, by setting `HAVE_ZLIB=0`.
|
||||
Example : `make zstd HAVE_ZLIB=0`
|
||||
It's also possible to force compilation with zlib support, `using HAVE_ZLIB=1`.
|
||||
It's also possible to force compilation with zlib support, using `HAVE_ZLIB=1`.
|
||||
In which case, linking stage will fail if `zlib` library cannot be found.
|
||||
This is useful to prevent silent feature disabling.
|
||||
|
||||
@@ -45,7 +45,7 @@ There are however other Makefile targets that create different variations of CLI
|
||||
This is ordered through commands `--format=xz` and `--format=lzma` respectively.
|
||||
Alternatively, symlinks named `xz`, `unxz`, `lzma`, or `unlzma` will mimic intended behavior.
|
||||
`.xz` and `.lzma` support is automatically enabled when `lzma` library is detected at build time.
|
||||
It's possible to disable `.xz` and `.lzma` support, by setting `HAVE_LZMA=0` .
|
||||
It's possible to disable `.xz` and `.lzma` support, by setting `HAVE_LZMA=0`.
|
||||
Example : `make zstd HAVE_LZMA=0`
|
||||
It's also possible to force compilation with lzma support, using `HAVE_LZMA=1`.
|
||||
In which case, linking stage will fail if `lzma` library cannot be found.
|
||||
|
||||
+44
-51
@@ -13,25 +13,19 @@
|
||||
/* *************************************
|
||||
* Includes
|
||||
***************************************/
|
||||
#include "platform.h" /* Large Files support */
|
||||
#include "util.h" /* UTIL_getFileSize, UTIL_sleep */
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <string.h> /* memset */
|
||||
#include <stdio.h> /* fprintf, fopen */
|
||||
#undef NDEBUG /* assert must not be disabled */
|
||||
#include <assert.h> /* assert */
|
||||
|
||||
#include "mem.h"
|
||||
#include "timefn.h" /* UTIL_time_t, UTIL_getTime */
|
||||
#include "benchfn.h"
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
#define TIMELOOP_MICROSEC (1*1000000ULL) /* 1 second */
|
||||
#define TIMELOOP_MICROSEC SEC_TO_MICRO /* 1 second */
|
||||
#define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */
|
||||
#define ACTIVEPERIOD_MICROSEC (70*TIMELOOP_MICROSEC) /* 70 seconds */
|
||||
#define COOLPERIOD_SEC 10
|
||||
|
||||
#define KB *(1 <<10)
|
||||
#define MB *(1 <<20)
|
||||
@@ -39,14 +33,16 @@
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Errors
|
||||
* Debug errors
|
||||
***************************************/
|
||||
#ifndef DEBUG
|
||||
# define DEBUG 0
|
||||
#if defined(DEBUG) && (DEBUG >= 1)
|
||||
# include <stdio.h> /* fprintf */
|
||||
# define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||
# define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }
|
||||
#else
|
||||
# define DEBUGOUTPUT(...)
|
||||
#endif
|
||||
|
||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }
|
||||
|
||||
/* error without displaying */
|
||||
#define RETURN_QUIET_ERROR(retValue, ...) { \
|
||||
@@ -57,6 +53,9 @@
|
||||
return retValue; \
|
||||
}
|
||||
|
||||
/* Abort execution if a condition is not met */
|
||||
#define CONTROL(c) { if (!(c)) { DEBUGOUTPUT("error: %s \n", #c); abort(); } }
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Benchmarking an arbitrary function
|
||||
@@ -71,13 +70,13 @@ int BMK_isSuccessful_runOutcome(BMK_runOutcome_t outcome)
|
||||
* check outcome validity first, using BMK_isValid_runResult() */
|
||||
BMK_runTime_t BMK_extract_runTime(BMK_runOutcome_t outcome)
|
||||
{
|
||||
assert(outcome.error_tag_never_ever_use_directly == 0);
|
||||
CONTROL(outcome.error_tag_never_ever_use_directly == 0);
|
||||
return outcome.internal_never_ever_use_directly;
|
||||
}
|
||||
|
||||
size_t BMK_extract_errorResult(BMK_runOutcome_t outcome)
|
||||
{
|
||||
assert(outcome.error_tag_never_ever_use_directly != 0);
|
||||
CONTROL(outcome.error_tag_never_ever_use_directly != 0);
|
||||
return outcome.error_result_never_ever_use_directly;
|
||||
}
|
||||
|
||||
@@ -116,15 +115,7 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
|
||||
{ size_t i;
|
||||
for(i = 0; i < p.blockCount; i++) {
|
||||
memset(p.dstBuffers[i], 0xE5, p.dstCapacities[i]); /* warm up and erase result buffer */
|
||||
}
|
||||
#if 0
|
||||
/* based on testing these seem to lower accuracy of multiple calls of 1 nbLoops vs 1 call of multiple nbLoops
|
||||
* (Makes former slower)
|
||||
*/
|
||||
UTIL_sleepMilli(5); /* give processor time to other processes */
|
||||
UTIL_waitForNextTick();
|
||||
#endif
|
||||
}
|
||||
} }
|
||||
|
||||
/* benchmark */
|
||||
{ UTIL_time_t const clockStart = UTIL_getTime();
|
||||
@@ -146,9 +137,9 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
|
||||
} }
|
||||
} /* for (loopNb = 0; loopNb < nbLoops; loopNb++) */
|
||||
|
||||
{ U64 const totalTime = UTIL_clockSpanNano(clockStart);
|
||||
{ PTime const totalTime = UTIL_clockSpanNano(clockStart);
|
||||
BMK_runTime_t rt;
|
||||
rt.nanoSecPerRun = totalTime / nbLoops;
|
||||
rt.nanoSecPerRun = (double)totalTime / nbLoops;
|
||||
rt.sumOfReturn = dstSize;
|
||||
return BMK_setValid_runTime(rt);
|
||||
} }
|
||||
@@ -158,9 +149,9 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
|
||||
/* ==== Benchmarking any function, providing intermediate results ==== */
|
||||
|
||||
struct BMK_timedFnState_s {
|
||||
U64 timeSpent_ns;
|
||||
U64 timeBudget_ns;
|
||||
U64 runBudget_ns;
|
||||
PTime timeSpent_ns;
|
||||
PTime timeBudget_ns;
|
||||
PTime runBudget_ns;
|
||||
BMK_runTime_t fastestRun;
|
||||
unsigned nbLoops;
|
||||
UTIL_time_t coolTime;
|
||||
@@ -174,8 +165,20 @@ BMK_timedFnState_t* BMK_createTimedFnState(unsigned total_ms, unsigned run_ms)
|
||||
return r;
|
||||
}
|
||||
|
||||
void BMK_freeTimedFnState(BMK_timedFnState_t* state) {
|
||||
free(state);
|
||||
void BMK_freeTimedFnState(BMK_timedFnState_t* state) { free(state); }
|
||||
|
||||
BMK_timedFnState_t*
|
||||
BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms)
|
||||
{
|
||||
typedef char check_size[ 2 * (sizeof(BMK_timedFnState_shell) >= sizeof(struct BMK_timedFnState_s)) - 1]; /* static assert : a compilation failure indicates that BMK_timedFnState_shell is not large enough */
|
||||
typedef struct { check_size c; BMK_timedFnState_t tfs; } tfs_align; /* force tfs to be aligned at its next best position */
|
||||
size_t const tfs_alignment = offsetof(tfs_align, tfs); /* provides the minimal alignment restriction for BMK_timedFnState_t */
|
||||
BMK_timedFnState_t* const r = (BMK_timedFnState_t*)buffer;
|
||||
if (buffer == NULL) return NULL;
|
||||
if (size < sizeof(struct BMK_timedFnState_s)) return NULL;
|
||||
if ((size_t)buffer % tfs_alignment) return NULL; /* buffer must be properly aligned */
|
||||
BMK_resetTimedFnState(r, total_ms, run_ms);
|
||||
return r;
|
||||
}
|
||||
|
||||
void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms)
|
||||
@@ -184,9 +187,9 @@ void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms,
|
||||
if (!run_ms) run_ms = 1;
|
||||
if (run_ms > total_ms) run_ms = total_ms;
|
||||
timedFnState->timeSpent_ns = 0;
|
||||
timedFnState->timeBudget_ns = (U64)total_ms * TIMELOOP_NANOSEC / 1000;
|
||||
timedFnState->runBudget_ns = (U64)run_ms * TIMELOOP_NANOSEC / 1000;
|
||||
timedFnState->fastestRun.nanoSecPerRun = (U64)(-1LL);
|
||||
timedFnState->timeBudget_ns = (PTime)total_ms * TIMELOOP_NANOSEC / 1000;
|
||||
timedFnState->runBudget_ns = (PTime)run_ms * TIMELOOP_NANOSEC / 1000;
|
||||
timedFnState->fastestRun.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000; /* hopefully large enough : must be larger than any potential measurement */
|
||||
timedFnState->fastestRun.sumOfReturn = (size_t)(-1LL);
|
||||
timedFnState->nbLoops = 1;
|
||||
timedFnState->coolTime = UTIL_getTime();
|
||||
@@ -208,37 +211,27 @@ int BMK_isCompleted_TimedFn(const BMK_timedFnState_t* timedFnState)
|
||||
BMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* cont,
|
||||
BMK_benchParams_t p)
|
||||
{
|
||||
U64 const runBudget_ns = cont->runBudget_ns;
|
||||
U64 const runTimeMin_ns = runBudget_ns / 2;
|
||||
PTime const runBudget_ns = cont->runBudget_ns;
|
||||
PTime const runTimeMin_ns = runBudget_ns / 2;
|
||||
int completed = 0;
|
||||
BMK_runTime_t bestRunTime = cont->fastestRun;
|
||||
|
||||
while (!completed) {
|
||||
BMK_runOutcome_t runResult;
|
||||
|
||||
/* Overheat protection */
|
||||
if (UTIL_clockSpanMicro(cont->coolTime) > ACTIVEPERIOD_MICROSEC) {
|
||||
DEBUGOUTPUT("\rcooling down ... \r");
|
||||
UTIL_sleep(COOLPERIOD_SEC);
|
||||
cont->coolTime = UTIL_getTime();
|
||||
}
|
||||
|
||||
/* reinitialize capacity */
|
||||
runResult = BMK_benchFunction(p, cont->nbLoops);
|
||||
BMK_runOutcome_t const runResult = BMK_benchFunction(p, cont->nbLoops);
|
||||
|
||||
if(!BMK_isSuccessful_runOutcome(runResult)) { /* error : move out */
|
||||
return runResult;
|
||||
}
|
||||
|
||||
{ BMK_runTime_t const newRunTime = BMK_extract_runTime(runResult);
|
||||
U64 const loopDuration_ns = newRunTime.nanoSecPerRun * cont->nbLoops;
|
||||
double const loopDuration_ns = newRunTime.nanoSecPerRun * cont->nbLoops;
|
||||
|
||||
cont->timeSpent_ns += loopDuration_ns;
|
||||
cont->timeSpent_ns += (unsigned long long)loopDuration_ns;
|
||||
|
||||
/* estimate nbLoops for next run to last approximately 1 second */
|
||||
if (loopDuration_ns > (runBudget_ns / 50)) {
|
||||
U64 const fastestRun_ns = MIN(bestRunTime.nanoSecPerRun, newRunTime.nanoSecPerRun);
|
||||
cont->nbLoops = (U32)(runBudget_ns / fastestRun_ns) + 1;
|
||||
double const fastestRun_ns = MIN(bestRunTime.nanoSecPerRun, newRunTime.nanoSecPerRun);
|
||||
cont->nbLoops = (unsigned)(runBudget_ns / fastestRun_ns) + 1;
|
||||
} else {
|
||||
/* previous run was too short : blindly increase workload by x multiplier */
|
||||
const unsigned multiplier = 10;
|
||||
|
||||
+39
-23
@@ -31,7 +31,7 @@ extern "C" {
|
||||
/* BMK_runTime_t: valid result return type */
|
||||
|
||||
typedef struct {
|
||||
unsigned long long nanoSecPerRun; /* time per iteration (over all blocks) */
|
||||
double nanoSecPerRun; /* time per iteration (over all blocks) */
|
||||
size_t sumOfReturn; /* sum of return values */
|
||||
} BMK_runTime_t;
|
||||
|
||||
@@ -58,30 +58,31 @@ typedef size_t (*BMK_initFn_t)(void* initPayload);
|
||||
typedef unsigned (*BMK_errorFn_t)(size_t);
|
||||
|
||||
|
||||
/* BMK_benchFunction() parameters are provided through following structure.
|
||||
* This is preferable for readability,
|
||||
* as the number of parameters required is pretty large.
|
||||
/* BMK_benchFunction() parameters are provided via the following structure.
|
||||
* A structure is preferable for readability,
|
||||
* as the number of parameters required is fairly large.
|
||||
* No initializer is provided, because it doesn't make sense to provide some "default" :
|
||||
* all parameters should be specified by the caller */
|
||||
* all parameters must be specified by the caller.
|
||||
* optional parameters are labelled explicitly, and accept value NULL when not used */
|
||||
typedef struct {
|
||||
BMK_benchFn_t benchFn; /* the function to benchmark, over the set of blocks */
|
||||
void* benchPayload; /* pass custom parameters to benchFn :
|
||||
* (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload) */
|
||||
BMK_initFn_t initFn; /* (*initFn)(initPayload) is run once per run, at the beginning. */
|
||||
void* initPayload; /* Both arguments can be NULL, in which case nothing is run. */
|
||||
BMK_errorFn_t errorFn; /* errorFn will check each return value of benchFn over each block, to determine if it failed or not.
|
||||
* errorFn can be NULL, in which case no check is performed.
|
||||
* errorFn must return 0 when benchFn was successful, and >= 1 if it detects an error.
|
||||
* Execution is stopped as soon as an error is detected.
|
||||
* the triggering return value can be retrieved using BMK_extract_errorResult(). */
|
||||
size_t blockCount; /* number of blocks to operate benchFn on.
|
||||
* It's also the size of all array parameters :
|
||||
* srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults */
|
||||
const void *const * srcBuffers; /* array of buffers to be operated on by benchFn */
|
||||
const size_t* srcSizes; /* array of the sizes of srcBuffers buffers */
|
||||
void *const * dstBuffers;/* array of buffers to be written into by benchFn */
|
||||
const size_t* dstCapacities; /* array of the capacities of dstBuffers buffers */
|
||||
size_t* blockResults; /* Optional: store the return value of benchFn for each block. Use NULL if this result is not requested. */
|
||||
BMK_benchFn_t benchFn; /* the function to benchmark, over the set of blocks */
|
||||
void* benchPayload; /* pass custom parameters to benchFn :
|
||||
* (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload) */
|
||||
BMK_initFn_t initFn; /* (*initFn)(initPayload) is run once per run, at the beginning. */
|
||||
void* initPayload; /* Both arguments can be NULL, in which case nothing is run. */
|
||||
BMK_errorFn_t errorFn; /* errorFn will check each return value of benchFn over each block, to determine if it failed or not.
|
||||
* errorFn can be NULL, in which case no check is performed.
|
||||
* errorFn must return 0 when benchFn was successful, and >= 1 if it detects an error.
|
||||
* Execution is stopped as soon as an error is detected.
|
||||
* the triggering return value can be retrieved using BMK_extract_errorResult(). */
|
||||
size_t blockCount; /* number of blocks to operate benchFn on.
|
||||
* It's also the size of all array parameters :
|
||||
* srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults */
|
||||
const void *const * srcBuffers; /* read-only array of buffers to be operated on by benchFn */
|
||||
const size_t* srcSizes; /* read-only array containing sizes of srcBuffers */
|
||||
void *const * dstBuffers; /* array of buffers to be written into by benchFn. This array is not optional, it must be provided even if unused by benchfn. */
|
||||
const size_t* dstCapacities; /* read-only array containing capacities of dstBuffers. This array must be present. */
|
||||
size_t* blockResults; /* Optional: store the return value of benchFn for each block. Use NULL if this result is not requested. */
|
||||
} BMK_benchParams_t;
|
||||
|
||||
|
||||
@@ -159,6 +160,21 @@ void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms,
|
||||
void BMK_freeTimedFnState(BMK_timedFnState_t* state);
|
||||
|
||||
|
||||
/* BMK_timedFnState_shell and BMK_initStatic_timedFnState() :
|
||||
* Makes it possible to statically allocate a BMK_timedFnState_t on stack.
|
||||
* BMK_timedFnState_shell is only there to allocate space,
|
||||
* never ever access its members.
|
||||
* BMK_timedFnState_t() actually accepts any buffer.
|
||||
* It will check if provided buffer is large enough and is correctly aligned,
|
||||
* and will return NULL if conditions are not respected.
|
||||
*/
|
||||
#define BMK_TIMEDFNSTATE_SIZE 64
|
||||
typedef union {
|
||||
char never_access_space[BMK_TIMEDFNSTATE_SIZE];
|
||||
long long alignment_enforcer; /* must be aligned on 8-bytes boundaries */
|
||||
} BMK_timedFnState_shell;
|
||||
BMK_timedFnState_t* BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms);
|
||||
|
||||
|
||||
#endif /* BENCH_FN_H_23876 */
|
||||
|
||||
|
||||
+30
-19
@@ -28,6 +28,7 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h> /* assert */
|
||||
|
||||
#include "timefn.h" /* UTIL_time_t */
|
||||
#include "benchfn.h"
|
||||
#include "mem.h"
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
@@ -135,7 +136,8 @@ BMK_advancedParams_t BMK_initAdvancedParams(void) {
|
||||
0, /* ldmMinMatch */
|
||||
0, /* ldmHashLog */
|
||||
0, /* ldmBuckSizeLog */
|
||||
0 /* ldmHashRateLog */
|
||||
0, /* ldmHashRateLog */
|
||||
ZSTD_lcm_auto /* literalCompressionMode */
|
||||
};
|
||||
return res;
|
||||
}
|
||||
@@ -159,9 +161,13 @@ typedef struct {
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
static void BMK_initCCtx(ZSTD_CCtx* ctx,
|
||||
const void* dictBuffer, size_t dictBufferSize, int cLevel,
|
||||
const ZSTD_compressionParameters* comprParams, const BMK_advancedParams_t* adv) {
|
||||
static void
|
||||
BMK_initCCtx(ZSTD_CCtx* ctx,
|
||||
const void* dictBuffer, size_t dictBufferSize,
|
||||
int cLevel,
|
||||
const ZSTD_compressionParameters* comprParams,
|
||||
const BMK_advancedParams_t* adv)
|
||||
{
|
||||
ZSTD_CCtx_reset(ctx, ZSTD_reset_session_and_parameters);
|
||||
if (adv->nbWorkers==1) {
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, 0));
|
||||
@@ -174,12 +180,13 @@ static void BMK_initCCtx(ZSTD_CCtx* ctx,
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashLog, adv->ldmHashLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmBucketSizeLog, adv->ldmBucketSizeLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashRateLog, adv->ldmHashRateLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_windowLog, comprParams->windowLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_hashLog, comprParams->hashLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_chainLog, comprParams->chainLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_searchLog, comprParams->searchLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_minMatch, comprParams->minMatch));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_targetLength, comprParams->targetLength));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_windowLog, (int)comprParams->windowLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_hashLog, (int)comprParams->hashLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_chainLog, (int)comprParams->chainLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_searchLog, (int)comprParams->searchLog));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_minMatch, (int)comprParams->minMatch));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_targetLength, (int)comprParams->targetLength));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_literalCompressionMode, (int)adv->literalCompressionMode));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_strategy, comprParams->strategy));
|
||||
CHECK_Z(ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize));
|
||||
}
|
||||
@@ -376,7 +383,7 @@ BMK_benchMemAdvancedNoAlloc(
|
||||
}
|
||||
}
|
||||
|
||||
/* warmimg up `compressedBuffer` */
|
||||
/* warming up `compressedBuffer` */
|
||||
if (adv->mode == BMK_decodeOnly) {
|
||||
memcpy(compressedBuffer, srcBuffer, loadedCompressedSize);
|
||||
} else {
|
||||
@@ -444,7 +451,7 @@ BMK_benchMemAdvancedNoAlloc(
|
||||
cSize = cResult.sumOfReturn;
|
||||
ratio = (double)srcSize / cSize;
|
||||
{ BMK_benchResult_t newResult;
|
||||
newResult.cSpeed = ((U64)srcSize * TIMELOOP_NANOSEC / cResult.nanoSecPerRun);
|
||||
newResult.cSpeed = (U64)((double)srcSize * TIMELOOP_NANOSEC / cResult.nanoSecPerRun);
|
||||
benchResult.cSize = cSize;
|
||||
if (newResult.cSpeed > benchResult.cSpeed)
|
||||
benchResult.cSpeed = newResult.cSpeed;
|
||||
@@ -468,7 +475,7 @@ BMK_benchMemAdvancedNoAlloc(
|
||||
}
|
||||
|
||||
{ BMK_runTime_t const dResult = BMK_extract_runTime(dOutcome);
|
||||
U64 const newDSpeed = (srcSize * TIMELOOP_NANOSEC / dResult.nanoSecPerRun);
|
||||
U64 const newDSpeed = (U64)((double)srcSize * TIMELOOP_NANOSEC / dResult.nanoSecPerRun);
|
||||
if (newDSpeed > benchResult.dSpeed)
|
||||
benchResult.dSpeed = newDSpeed;
|
||||
}
|
||||
@@ -505,17 +512,21 @@ BMK_benchMemAdvancedNoAlloc(
|
||||
pos = (U32)(u - bacc);
|
||||
bNb = pos / (128 KB);
|
||||
DISPLAY("(sample %u, block %u, pos %u) \n", segNb, bNb, pos);
|
||||
if (u>5) {
|
||||
int n;
|
||||
{ size_t const lowest = (u>5) ? 5 : u;
|
||||
size_t n;
|
||||
DISPLAY("origin: ");
|
||||
for (n=-5; n<0; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]);
|
||||
for (n=lowest; n>0; n--)
|
||||
DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u-n]);
|
||||
DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]);
|
||||
for (n=1; n<3; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]);
|
||||
for (n=1; n<3; n++)
|
||||
DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]);
|
||||
DISPLAY(" \n");
|
||||
DISPLAY("decode: ");
|
||||
for (n=-5; n<0; n++) DISPLAY("%02X ", resultBuffer[u+n]);
|
||||
for (n=lowest; n>0; n++)
|
||||
DISPLAY("%02X ", resultBuffer[u-n]);
|
||||
DISPLAY(" :%02X: ", resultBuffer[u]);
|
||||
for (n=1; n<3; n++) DISPLAY("%02X ", resultBuffer[u+n]);
|
||||
for (n=1; n<3; n++)
|
||||
DISPLAY("%02X ", resultBuffer[u+n]);
|
||||
DISPLAY(" \n");
|
||||
}
|
||||
break;
|
||||
|
||||
+13
-12
@@ -105,17 +105,18 @@ typedef enum {
|
||||
} BMK_mode_t;
|
||||
|
||||
typedef struct {
|
||||
BMK_mode_t mode; /* 0: all, 1: compress only 2: decode only */
|
||||
unsigned nbSeconds; /* default timing is in nbSeconds */
|
||||
size_t blockSize; /* Maximum size of each block*/
|
||||
unsigned nbWorkers; /* multithreading */
|
||||
unsigned realTime; /* real time priority */
|
||||
int additionalParam; /* used by python speed benchmark */
|
||||
unsigned ldmFlag; /* enables long distance matching */
|
||||
unsigned ldmMinMatch; /* below: parameters for long distance matching, see zstd.1.md */
|
||||
unsigned ldmHashLog;
|
||||
unsigned ldmBucketSizeLog;
|
||||
unsigned ldmHashRateLog;
|
||||
BMK_mode_t mode; /* 0: all, 1: compress only 2: decode only */
|
||||
unsigned nbSeconds; /* default timing is in nbSeconds */
|
||||
size_t blockSize; /* Maximum size of each block*/
|
||||
int nbWorkers; /* multithreading */
|
||||
unsigned realTime; /* real time priority */
|
||||
int additionalParam; /* used by python speed benchmark */
|
||||
int ldmFlag; /* enables long distance matching */
|
||||
int ldmMinMatch; /* below: parameters for long distance matching, see zstd.1.md */
|
||||
int ldmHashLog;
|
||||
int ldmBucketSizeLog;
|
||||
int ldmHashRateLog;
|
||||
ZSTD_literalCompressionMode_e literalCompressionMode;
|
||||
} BMK_advancedParams_t;
|
||||
|
||||
/* returns default parameters used by nonAdvanced functions */
|
||||
@@ -169,7 +170,7 @@ BMK_benchOutcome_t BMK_syntheticTest(
|
||||
* comprParams - basic compression parameters
|
||||
* dictBuffer - a dictionary if used, null otherwise
|
||||
* dictBufferSize - size of dictBuffer, 0 otherwise
|
||||
* diplayLevel - see BMK_benchFiles
|
||||
* displayLevel - see BMK_benchFiles
|
||||
* displayName - name used by display
|
||||
* @return:
|
||||
* a variant, which expresses either an error, or a valid result.
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <errno.h> /* errno */
|
||||
#include <assert.h>
|
||||
|
||||
#include "timefn.h" /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */
|
||||
#include "mem.h" /* read */
|
||||
#include "error_private.h"
|
||||
#include "dibio.h"
|
||||
|
||||
+363
-210
@@ -24,13 +24,14 @@
|
||||
* Includes
|
||||
***************************************/
|
||||
#include "platform.h" /* Large Files support, SET_BINARY_MODE */
|
||||
#include "util.h" /* UTIL_getFileSize, UTIL_isRegularFile */
|
||||
#include "util.h" /* UTIL_getFileSize, UTIL_isRegularFile, UTIL_isSameFile */
|
||||
#include <stdio.h> /* fprintf, fopen, fread, _fileno, stdin, stdout */
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <string.h> /* strcmp, strlen */
|
||||
#include <assert.h>
|
||||
#include <errno.h> /* errno */
|
||||
#include <signal.h>
|
||||
#include "timefn.h" /* UTIL_getTime, UTIL_clockSpanMicro */
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# include <sys/stat.h>
|
||||
@@ -79,23 +80,29 @@
|
||||
/*-*************************************
|
||||
* Macros
|
||||
***************************************/
|
||||
|
||||
struct FIO_display_prefs_s {
|
||||
int displayLevel; /* 0 : no display; 1: errors; 2: + result + interaction + warnings; 3: + progression; 4: + information */
|
||||
U32 noProgress;
|
||||
};
|
||||
|
||||
static FIO_display_prefs_t g_display_prefs = {2, 0};
|
||||
|
||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define DISPLAYOUT(...) fprintf(stdout, __VA_ARGS__)
|
||||
#define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
|
||||
static int g_displayLevel = 2; /* 0 : no display; 1: errors; 2: + result + interaction + warnings; 3: + progression; 4: + information */
|
||||
void FIO_setNotificationLevel(unsigned level) { g_displayLevel=level; }
|
||||
#define DISPLAYLEVEL(l, ...) { if (g_display_prefs.displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
|
||||
|
||||
static const U64 g_refreshRate = SEC_TO_MICRO / 6;
|
||||
static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
|
||||
|
||||
#define READY_FOR_UPDATE() (!g_noProgress && UTIL_clockSpanMicro(g_displayClock) > g_refreshRate)
|
||||
#define READY_FOR_UPDATE() (!g_display_prefs.noProgress && UTIL_clockSpanMicro(g_displayClock) > g_refreshRate)
|
||||
#define DELAY_NEXT_UPDATE() { g_displayClock = UTIL_getTime(); }
|
||||
#define DISPLAYUPDATE(l, ...) { \
|
||||
if (g_displayLevel>=l && !g_noProgress) { \
|
||||
if (READY_FOR_UPDATE() || (g_displayLevel>=4)) { \
|
||||
if (g_display_prefs.displayLevel>=l && !g_display_prefs.noProgress) { \
|
||||
if (READY_FOR_UPDATE() || (g_display_prefs.displayLevel>=4)) { \
|
||||
DELAY_NEXT_UPDATE(); \
|
||||
DISPLAY(__VA_ARGS__); \
|
||||
if (g_displayLevel>=4) fflush(stderr); \
|
||||
if (g_display_prefs.displayLevel>=4) fflush(stderr); \
|
||||
} } }
|
||||
|
||||
#undef MIN /* in case it would be already defined */
|
||||
@@ -168,7 +175,7 @@ static void clearHandler(void)
|
||||
|
||||
#if !defined(BACKTRACE_ENABLE)
|
||||
/* automatic detector : backtrace enabled by default on linux+glibc and osx */
|
||||
# if (defined(__linux__) && defined(__GLIBC__)) \
|
||||
# if (defined(__linux__) && (defined(__GLIBC__) && !defined(__UCLIBC__))) \
|
||||
|| (defined(__APPLE__) && defined(__MACH__))
|
||||
# define BACKTRACE_ENABLE 1
|
||||
# else
|
||||
@@ -189,7 +196,7 @@ static void ABRThandler(int sig) {
|
||||
const char* name;
|
||||
void* addrlist[MAX_STACK_FRAMES];
|
||||
char** symbollist;
|
||||
U32 addrlen, i;
|
||||
int addrlen, i;
|
||||
|
||||
switch (sig) {
|
||||
case SIGABRT: name = "SIGABRT"; break;
|
||||
@@ -237,10 +244,13 @@ void FIO_addAbortHandler()
|
||||
***************************************************************/
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
# define LONG_SEEK _fseeki64
|
||||
# define LONG_TELL _ftelli64
|
||||
#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */
|
||||
# define LONG_SEEK fseeko
|
||||
# define LONG_TELL ftello
|
||||
#elif defined(__MINGW32__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) && defined(__MSVCRT__)
|
||||
# define LONG_SEEK fseeko64
|
||||
# define LONG_TELL ftello64
|
||||
#elif defined(_WIN32) && !defined(__DJGPP__)
|
||||
# include <windows.h>
|
||||
static int LONG_SEEK(FILE* file, __int64 offset, int origin) {
|
||||
@@ -259,102 +269,198 @@ void FIO_addAbortHandler()
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
static __int64 LONG_TELL(FILE* file) {
|
||||
LARGE_INTEGER off, newOff;
|
||||
off.QuadPart = 0;
|
||||
newOff.QuadPart = 0;
|
||||
SetFilePointerEx((HANDLE) _get_osfhandle(_fileno(file)), off, &newOff, FILE_CURRENT);
|
||||
return newOff.QuadPart;
|
||||
}
|
||||
#else
|
||||
# define LONG_SEEK fseek
|
||||
# define LONG_TELL ftell
|
||||
#endif
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Local Parameters - Not thread safe
|
||||
* Parameters: Typedefs
|
||||
***************************************/
|
||||
static FIO_compressionType_t g_compressionType = FIO_zstdCompression;
|
||||
void FIO_setCompressionType(FIO_compressionType_t compressionType) { g_compressionType = compressionType; }
|
||||
static U32 g_overwrite = 0;
|
||||
void FIO_overwriteMode(void) { g_overwrite = 1; }
|
||||
static U32 g_sparseFileSupport = ZSTD_SPARSE_DEFAULT; /* 0: no sparse allowed; 1: auto (file yes, stdout no); 2: force sparse */
|
||||
void FIO_setSparseWrite(unsigned sparse) { g_sparseFileSupport = sparse; }
|
||||
static U32 g_dictIDFlag = 1;
|
||||
void FIO_setDictIDFlag(unsigned dictIDFlag) { g_dictIDFlag = dictIDFlag; }
|
||||
static U32 g_checksumFlag = 1;
|
||||
void FIO_setChecksumFlag(unsigned checksumFlag) { g_checksumFlag = checksumFlag; }
|
||||
static U32 g_removeSrcFile = 0;
|
||||
void FIO_setRemoveSrcFile(unsigned flag) { g_removeSrcFile = (flag>0); }
|
||||
static unsigned g_memLimit = 0;
|
||||
void FIO_setMemLimit(unsigned memLimit) { g_memLimit = memLimit; }
|
||||
static unsigned g_nbWorkers = 1;
|
||||
void FIO_setNbWorkers(unsigned nbWorkers) {
|
||||
|
||||
struct FIO_prefs_s {
|
||||
|
||||
/* Algorithm preferences */
|
||||
FIO_compressionType_t compressionType;
|
||||
U32 sparseFileSupport; /* 0: no sparse allowed; 1: auto (file yes, stdout no); 2: force sparse */
|
||||
int dictIDFlag;
|
||||
int checksumFlag;
|
||||
int blockSize;
|
||||
int overlapLog;
|
||||
U32 adaptiveMode;
|
||||
int rsyncable;
|
||||
int minAdaptLevel;
|
||||
int maxAdaptLevel;
|
||||
int ldmFlag;
|
||||
int ldmHashLog;
|
||||
int ldmMinMatch;
|
||||
int ldmBucketSizeLog;
|
||||
int ldmHashRateLog;
|
||||
size_t targetCBlockSize;
|
||||
ZSTD_literalCompressionMode_e literalCompressionMode;
|
||||
|
||||
/* IO preferences */
|
||||
U32 removeSrcFile;
|
||||
U32 overwrite;
|
||||
|
||||
/* Computation resources preferences */
|
||||
unsigned memLimit;
|
||||
int nbWorkers;
|
||||
};
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Parameters: Initialization
|
||||
***************************************/
|
||||
|
||||
#define FIO_OVERLAP_LOG_NOTSET 9999
|
||||
#define FIO_LDM_PARAM_NOTSET 9999
|
||||
|
||||
|
||||
FIO_prefs_t* FIO_createPreferences(void)
|
||||
{
|
||||
FIO_prefs_t* const ret = (FIO_prefs_t*)malloc(sizeof(FIO_prefs_t));
|
||||
if (!ret) EXM_THROW(21, "Allocation error : not enough memory");
|
||||
|
||||
ret->compressionType = FIO_zstdCompression;
|
||||
ret->overwrite = 0;
|
||||
ret->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
|
||||
ret->dictIDFlag = 1;
|
||||
ret->checksumFlag = 1;
|
||||
ret->removeSrcFile = 0;
|
||||
ret->memLimit = 0;
|
||||
ret->nbWorkers = 1;
|
||||
ret->blockSize = 0;
|
||||
ret->overlapLog = FIO_OVERLAP_LOG_NOTSET;
|
||||
ret->adaptiveMode = 0;
|
||||
ret->rsyncable = 0;
|
||||
ret->minAdaptLevel = -50; /* initializing this value requires a constant, so ZSTD_minCLevel() doesn't work */
|
||||
ret->maxAdaptLevel = 22; /* initializing this value requires a constant, so ZSTD_maxCLevel() doesn't work */
|
||||
ret->ldmFlag = 0;
|
||||
ret->ldmHashLog = 0;
|
||||
ret->ldmMinMatch = 0;
|
||||
ret->ldmBucketSizeLog = FIO_LDM_PARAM_NOTSET;
|
||||
ret->ldmHashRateLog = FIO_LDM_PARAM_NOTSET;
|
||||
ret->targetCBlockSize = 0;
|
||||
ret->literalCompressionMode = ZSTD_lcm_auto;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FIO_freePreferences(FIO_prefs_t* const prefs)
|
||||
{
|
||||
free(prefs);
|
||||
}
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Parameters: Display Options
|
||||
***************************************/
|
||||
|
||||
void FIO_setNotificationLevel(int level) { g_display_prefs.displayLevel=level; }
|
||||
|
||||
void FIO_setNoProgress(unsigned noProgress) { g_display_prefs.noProgress = noProgress; }
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Parameters: Setters
|
||||
***************************************/
|
||||
|
||||
void FIO_setCompressionType(FIO_prefs_t* const prefs, FIO_compressionType_t compressionType) { prefs->compressionType = compressionType; }
|
||||
|
||||
void FIO_overwriteMode(FIO_prefs_t* const prefs) { prefs->overwrite = 1; }
|
||||
|
||||
void FIO_setSparseWrite(FIO_prefs_t* const prefs, unsigned sparse) { prefs->sparseFileSupport = sparse; }
|
||||
|
||||
void FIO_setDictIDFlag(FIO_prefs_t* const prefs, int dictIDFlag) { prefs->dictIDFlag = dictIDFlag; }
|
||||
|
||||
void FIO_setChecksumFlag(FIO_prefs_t* const prefs, int checksumFlag) { prefs->checksumFlag = checksumFlag; }
|
||||
|
||||
void FIO_setRemoveSrcFile(FIO_prefs_t* const prefs, unsigned flag) { prefs->removeSrcFile = (flag>0); }
|
||||
|
||||
void FIO_setMemLimit(FIO_prefs_t* const prefs, unsigned memLimit) { prefs->memLimit = memLimit; }
|
||||
|
||||
void FIO_setNbWorkers(FIO_prefs_t* const prefs, int nbWorkers) {
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
if (nbWorkers > 0) DISPLAYLEVEL(2, "Note : multi-threading is disabled \n");
|
||||
#endif
|
||||
g_nbWorkers = nbWorkers;
|
||||
prefs->nbWorkers = nbWorkers;
|
||||
}
|
||||
static U32 g_blockSize = 0;
|
||||
void FIO_setBlockSize(unsigned blockSize) {
|
||||
if (blockSize && g_nbWorkers==0)
|
||||
|
||||
void FIO_setBlockSize(FIO_prefs_t* const prefs, int blockSize) {
|
||||
if (blockSize && prefs->nbWorkers==0)
|
||||
DISPLAYLEVEL(2, "Setting block size is useless in single-thread mode \n");
|
||||
g_blockSize = blockSize;
|
||||
prefs->blockSize = blockSize;
|
||||
}
|
||||
#define FIO_OVERLAP_LOG_NOTSET 9999
|
||||
static unsigned g_overlapLog = FIO_OVERLAP_LOG_NOTSET;
|
||||
void FIO_setOverlapLog(unsigned overlapLog){
|
||||
if (overlapLog && g_nbWorkers==0)
|
||||
|
||||
void FIO_setOverlapLog(FIO_prefs_t* const prefs, int overlapLog){
|
||||
if (overlapLog && prefs->nbWorkers==0)
|
||||
DISPLAYLEVEL(2, "Setting overlapLog is useless in single-thread mode \n");
|
||||
g_overlapLog = overlapLog;
|
||||
prefs->overlapLog = overlapLog;
|
||||
}
|
||||
static U32 g_adaptiveMode = 0;
|
||||
void FIO_setAdaptiveMode(unsigned adapt) {
|
||||
if ((adapt>0) && (g_nbWorkers==0))
|
||||
|
||||
void FIO_setAdaptiveMode(FIO_prefs_t* const prefs, unsigned adapt) {
|
||||
if ((adapt>0) && (prefs->nbWorkers==0))
|
||||
EXM_THROW(1, "Adaptive mode is not compatible with single thread mode \n");
|
||||
g_adaptiveMode = adapt;
|
||||
prefs->adaptiveMode = adapt;
|
||||
}
|
||||
static U32 g_rsyncable = 0;
|
||||
void FIO_setRsyncable(unsigned rsyncable) {
|
||||
if ((rsyncable>0) && (g_nbWorkers==0))
|
||||
|
||||
void FIO_setRsyncable(FIO_prefs_t* const prefs, int rsyncable) {
|
||||
if ((rsyncable>0) && (prefs->nbWorkers==0))
|
||||
EXM_THROW(1, "Rsyncable mode is not compatible with single thread mode \n");
|
||||
g_rsyncable = rsyncable;
|
||||
prefs->rsyncable = rsyncable;
|
||||
}
|
||||
static int g_minAdaptLevel = -50; /* initializing this value requires a constant, so ZSTD_minCLevel() doesn't work */
|
||||
void FIO_setAdaptMin(int minCLevel)
|
||||
|
||||
void FIO_setTargetCBlockSize(FIO_prefs_t* const prefs, size_t targetCBlockSize) {
|
||||
prefs->targetCBlockSize = targetCBlockSize;
|
||||
}
|
||||
|
||||
void FIO_setLiteralCompressionMode(
|
||||
FIO_prefs_t* const prefs,
|
||||
ZSTD_literalCompressionMode_e mode) {
|
||||
prefs->literalCompressionMode = mode;
|
||||
}
|
||||
|
||||
void FIO_setAdaptMin(FIO_prefs_t* const prefs, int minCLevel)
|
||||
{
|
||||
#ifndef ZSTD_NOCOMPRESS
|
||||
assert(minCLevel >= ZSTD_minCLevel());
|
||||
#endif
|
||||
g_minAdaptLevel = minCLevel;
|
||||
prefs->minAdaptLevel = minCLevel;
|
||||
}
|
||||
static int g_maxAdaptLevel = 22; /* initializing this value requires a constant, so ZSTD_maxCLevel() doesn't work */
|
||||
void FIO_setAdaptMax(int maxCLevel)
|
||||
|
||||
void FIO_setAdaptMax(FIO_prefs_t* const prefs, int maxCLevel)
|
||||
{
|
||||
g_maxAdaptLevel = maxCLevel;
|
||||
prefs->maxAdaptLevel = maxCLevel;
|
||||
}
|
||||
|
||||
static U32 g_ldmFlag = 0;
|
||||
void FIO_setLdmFlag(unsigned ldmFlag) {
|
||||
g_ldmFlag = (ldmFlag>0);
|
||||
}
|
||||
static U32 g_ldmHashLog = 0;
|
||||
void FIO_setLdmHashLog(unsigned ldmHashLog) {
|
||||
g_ldmHashLog = ldmHashLog;
|
||||
}
|
||||
static U32 g_ldmMinMatch = 0;
|
||||
void FIO_setLdmMinMatch(unsigned ldmMinMatch) {
|
||||
g_ldmMinMatch = ldmMinMatch;
|
||||
void FIO_setLdmFlag(FIO_prefs_t* const prefs, unsigned ldmFlag) {
|
||||
prefs->ldmFlag = (ldmFlag>0);
|
||||
}
|
||||
|
||||
#define FIO_LDM_PARAM_NOTSET 9999
|
||||
static U32 g_ldmBucketSizeLog = FIO_LDM_PARAM_NOTSET;
|
||||
void FIO_setLdmBucketSizeLog(unsigned ldmBucketSizeLog) {
|
||||
g_ldmBucketSizeLog = ldmBucketSizeLog;
|
||||
void FIO_setLdmHashLog(FIO_prefs_t* const prefs, int ldmHashLog) {
|
||||
prefs->ldmHashLog = ldmHashLog;
|
||||
}
|
||||
|
||||
static U32 g_ldmHashRateLog = FIO_LDM_PARAM_NOTSET;
|
||||
void FIO_setLdmHashRateLog(unsigned ldmHashRateLog) {
|
||||
g_ldmHashRateLog = ldmHashRateLog;
|
||||
}
|
||||
static U32 g_noProgress = 0;
|
||||
void FIO_setNoProgress(unsigned noProgress) {
|
||||
g_noProgress = noProgress;
|
||||
void FIO_setLdmMinMatch(FIO_prefs_t* const prefs, int ldmMinMatch) {
|
||||
prefs->ldmMinMatch = ldmMinMatch;
|
||||
}
|
||||
|
||||
void FIO_setLdmBucketSizeLog(FIO_prefs_t* const prefs, int ldmBucketSizeLog) {
|
||||
prefs->ldmBucketSizeLog = ldmBucketSizeLog;
|
||||
}
|
||||
|
||||
|
||||
void FIO_setLdmHashRateLog(FIO_prefs_t* const prefs, int ldmHashRateLog) {
|
||||
prefs->ldmHashRateLog = ldmHashRateLog;
|
||||
}
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -410,45 +516,27 @@ static FILE* FIO_openSrcFile(const char* srcFileName)
|
||||
/** FIO_openDstFile() :
|
||||
* condition : `dstFileName` must be non-NULL.
|
||||
* @result : FILE* to `dstFileName`, or NULL if it fails */
|
||||
static FILE* FIO_openDstFile(const char* srcFileName, const char* dstFileName)
|
||||
static FILE* FIO_openDstFile(FIO_prefs_t* const prefs, const char* srcFileName, const char* dstFileName)
|
||||
{
|
||||
assert(dstFileName != NULL);
|
||||
if (!strcmp (dstFileName, stdoutmark)) {
|
||||
DISPLAYLEVEL(4,"Using stdout for output \n");
|
||||
SET_BINARY_MODE(stdout);
|
||||
if (g_sparseFileSupport == 1) {
|
||||
g_sparseFileSupport = 0;
|
||||
if (prefs->sparseFileSupport == 1) {
|
||||
prefs->sparseFileSupport = 0;
|
||||
DISPLAYLEVEL(4, "Sparse File Support is automatically disabled on stdout ; try --sparse \n");
|
||||
}
|
||||
return stdout;
|
||||
}
|
||||
|
||||
/* ensure dst is not the same file as src */
|
||||
if (srcFileName != NULL) {
|
||||
#ifdef _MSC_VER
|
||||
/* note : Visual does not support file identification by inode.
|
||||
* The following work-around is limited to detecting exact name repetition only,
|
||||
* aka `filename` is considered different from `subdir/../filename` */
|
||||
if (!strcmp(srcFileName, dstFileName)) {
|
||||
DISPLAYLEVEL(1, "zstd: Refusing to open a output file which will overwrite the input file \n");
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
stat_t srcStat;
|
||||
stat_t dstStat;
|
||||
if (UTIL_getFileStat(srcFileName, &srcStat)
|
||||
&& UTIL_getFileStat(dstFileName, &dstStat)) {
|
||||
if (srcStat.st_dev == dstStat.st_dev
|
||||
&& srcStat.st_ino == dstStat.st_ino) {
|
||||
DISPLAYLEVEL(1, "zstd: Refusing to open a output file which will overwrite the input file \n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* ensure dst is not the same as src */
|
||||
if (srcFileName != NULL && UTIL_isSameFile(srcFileName, dstFileName)) {
|
||||
DISPLAYLEVEL(1, "zstd: Refusing to open an output file which will overwrite the input file \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_sparseFileSupport == 1) {
|
||||
g_sparseFileSupport = ZSTD_SPARSE_DEFAULT;
|
||||
if (prefs->sparseFileSupport == 1) {
|
||||
prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
|
||||
}
|
||||
|
||||
if (UTIL_isRegularFile(dstFileName)) {
|
||||
@@ -460,8 +548,8 @@ static FILE* FIO_openDstFile(const char* srcFileName, const char* dstFileName)
|
||||
}
|
||||
if (fCheck != NULL) { /* dst file exists, authorization prompt */
|
||||
fclose(fCheck);
|
||||
if (!g_overwrite) {
|
||||
if (g_displayLevel <= 1) {
|
||||
if (!prefs->overwrite) {
|
||||
if (g_display_prefs.displayLevel <= 1) {
|
||||
/* No interaction possible */
|
||||
DISPLAY("zstd: %s already exists; not overwritten \n",
|
||||
dstFileName);
|
||||
@@ -482,8 +570,11 @@ static FILE* FIO_openDstFile(const char* srcFileName, const char* dstFileName)
|
||||
} }
|
||||
|
||||
{ FILE* const f = fopen( dstFileName, "wb" );
|
||||
if (f == NULL)
|
||||
if (f == NULL) {
|
||||
DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno));
|
||||
} else {
|
||||
chmod(dstFileName, 00600);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
@@ -536,10 +627,12 @@ typedef struct {
|
||||
size_t srcBufferSize;
|
||||
void* dstBuffer;
|
||||
size_t dstBufferSize;
|
||||
const char* dictFileName;
|
||||
ZSTD_CStream* cctx;
|
||||
} cRess_t;
|
||||
|
||||
static cRess_t FIO_createCResources(const char* dictFileName, int cLevel,
|
||||
static cRess_t FIO_createCResources(FIO_prefs_t* const prefs,
|
||||
const char* dictFileName, int cLevel,
|
||||
U64 srcSize,
|
||||
ZSTD_compressionParameters comprParams) {
|
||||
cRess_t ress;
|
||||
@@ -562,43 +655,47 @@ static cRess_t FIO_createCResources(const char* dictFileName, int cLevel,
|
||||
size_t const dictBuffSize = FIO_createDictBuffer(&dictBuffer, dictFileName); /* works with dictFileName==NULL */
|
||||
if (dictFileName && (dictBuffer==NULL))
|
||||
EXM_THROW(32, "allocation error : can't create dictBuffer");
|
||||
ress.dictFileName = dictFileName;
|
||||
|
||||
if (g_adaptiveMode && !g_ldmFlag && !comprParams.windowLog)
|
||||
if (prefs->adaptiveMode && !prefs->ldmFlag && !comprParams.windowLog)
|
||||
comprParams.windowLog = ADAPT_WINDOWLOG_DEFAULT;
|
||||
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, 1) ); /* always enable content size when available (note: supposed to be default) */
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, g_dictIDFlag) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, g_checksumFlag) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, prefs->dictIDFlag) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, prefs->checksumFlag) );
|
||||
/* compression level */
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) );
|
||||
/* max compressed block size */
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetCBlockSize, (int)prefs->targetCBlockSize) );
|
||||
/* long distance matching */
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableLongDistanceMatching, g_ldmFlag) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashLog, g_ldmHashLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmMinMatch, g_ldmMinMatch) );
|
||||
if (g_ldmBucketSizeLog != FIO_LDM_PARAM_NOTSET) {
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmBucketSizeLog, g_ldmBucketSizeLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableLongDistanceMatching, prefs->ldmFlag) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashLog, prefs->ldmHashLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmMinMatch, prefs->ldmMinMatch) );
|
||||
if (prefs->ldmBucketSizeLog != FIO_LDM_PARAM_NOTSET) {
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmBucketSizeLog, prefs->ldmBucketSizeLog) );
|
||||
}
|
||||
if (g_ldmHashRateLog != FIO_LDM_PARAM_NOTSET) {
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashRateLog, g_ldmHashRateLog) );
|
||||
if (prefs->ldmHashRateLog != FIO_LDM_PARAM_NOTSET) {
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashRateLog, prefs->ldmHashRateLog) );
|
||||
}
|
||||
/* compression parameters */
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowLog, comprParams.windowLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_chainLog, comprParams.chainLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_hashLog, comprParams.hashLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_searchLog, comprParams.searchLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_minMatch, comprParams.minMatch) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetLength, comprParams.targetLength) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowLog, (int)comprParams.windowLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_chainLog, (int)comprParams.chainLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_hashLog, (int)comprParams.hashLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_searchLog, (int)comprParams.searchLog) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_minMatch, (int)comprParams.minMatch) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetLength, (int)comprParams.targetLength) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_strategy, comprParams.strategy) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_literalCompressionMode, (int)prefs->literalCompressionMode) );
|
||||
/* multi-threading */
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
DISPLAYLEVEL(5,"set nb workers = %u \n", g_nbWorkers);
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_nbWorkers, g_nbWorkers) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, g_blockSize) );
|
||||
if (g_overlapLog != FIO_OVERLAP_LOG_NOTSET) {
|
||||
DISPLAYLEVEL(3,"set overlapLog = %u \n", g_overlapLog);
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_overlapLog, g_overlapLog) );
|
||||
DISPLAYLEVEL(5,"set nb workers = %u \n", prefs->nbWorkers);
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_nbWorkers, prefs->nbWorkers) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, prefs->blockSize) );
|
||||
if (prefs->overlapLog != FIO_OVERLAP_LOG_NOTSET) {
|
||||
DISPLAYLEVEL(3,"set overlapLog = %u \n", prefs->overlapLog);
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_overlapLog, prefs->overlapLog) );
|
||||
}
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_rsyncable, g_rsyncable) );
|
||||
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_rsyncable, prefs->rsyncable) );
|
||||
#endif
|
||||
/* dictionary */
|
||||
CHECK( ZSTD_CCtx_setPledgedSrcSize(ress.cctx, srcSize) ); /* set the value temporarily for dictionary loading, to adapt compression parameters */
|
||||
@@ -774,15 +871,19 @@ FIO_compressLzmaFrame(cRess_t* ress,
|
||||
#endif
|
||||
|
||||
#ifdef ZSTD_LZ4COMPRESS
|
||||
|
||||
#if LZ4_VERSION_NUMBER <= 10600
|
||||
#define LZ4F_blockLinked blockLinked
|
||||
#define LZ4F_max64KB max64KB
|
||||
#endif
|
||||
|
||||
static int FIO_LZ4_GetBlockSize_FromBlockId (int id) { return (1 << (8 + (2 * id))); }
|
||||
|
||||
static unsigned long long
|
||||
FIO_compressLz4Frame(cRess_t* ress,
|
||||
const char* srcFileName, U64 const srcFileSize,
|
||||
int compressionLevel, U64* readsize)
|
||||
int compressionLevel, int checksumFlag,
|
||||
U64* readsize)
|
||||
{
|
||||
const size_t blockSize = FIO_LZ4_GetBlockSize_FromBlockId(LZ4F_max64KB);
|
||||
unsigned long long inFileSize = 0, outFileSize = 0;
|
||||
@@ -802,7 +903,7 @@ FIO_compressLz4Frame(cRess_t* ress,
|
||||
prefs.compressionLevel = compressionLevel;
|
||||
prefs.frameInfo.blockMode = LZ4F_blockLinked;
|
||||
prefs.frameInfo.blockSizeID = LZ4F_max64KB;
|
||||
prefs.frameInfo.contentChecksumFlag = (contentChecksum_t)g_checksumFlag;
|
||||
prefs.frameInfo.contentChecksumFlag = (contentChecksum_t)checksumFlag;
|
||||
#if LZ4_VERSION_NUMBER >= 10600
|
||||
prefs.frameInfo.contentSize = (srcFileSize==UTIL_FILESIZE_UNKNOWN) ? 0 : srcFileSize;
|
||||
#endif
|
||||
@@ -876,7 +977,8 @@ FIO_compressLz4Frame(cRess_t* ress,
|
||||
|
||||
|
||||
static unsigned long long
|
||||
FIO_compressZstdFrame(const cRess_t* ressPtr,
|
||||
FIO_compressZstdFrame(FIO_prefs_t* const prefs,
|
||||
const cRess_t* ressPtr,
|
||||
const char* srcFileName, U64 fileSize,
|
||||
int compressionLevel, U64* readsize)
|
||||
{
|
||||
@@ -947,7 +1049,7 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
|
||||
double const cShare = (double)zfp.produced / (zfp.consumed + !zfp.consumed/*avoid div0*/) * 100;
|
||||
|
||||
/* display progress notifications */
|
||||
if (g_displayLevel >= 3) {
|
||||
if (g_display_prefs.displayLevel >= 3) {
|
||||
DISPLAYUPDATE(3, "\r(L%i) Buffered :%4u MB - Consumed :%4u MB - Compressed :%4u MB => %.2f%% ",
|
||||
compressionLevel,
|
||||
(unsigned)((zfp.ingested - zfp.consumed) >> 20),
|
||||
@@ -963,7 +1065,7 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
|
||||
}
|
||||
|
||||
/* adaptive mode : statistics measurement and speed correction */
|
||||
if (g_adaptiveMode) {
|
||||
if (prefs->adaptiveMode) {
|
||||
|
||||
/* check output speed */
|
||||
if (zfp.currentJobID > 1) { /* only possible if nbWorkers >= 1 */
|
||||
@@ -971,12 +1073,12 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
|
||||
unsigned long long newlyProduced = zfp.produced - previous_zfp_update.produced;
|
||||
unsigned long long newlyFlushed = zfp.flushed - previous_zfp_update.flushed;
|
||||
assert(zfp.produced >= previous_zfp_update.produced);
|
||||
assert(g_nbWorkers >= 1);
|
||||
assert(prefs->nbWorkers >= 1);
|
||||
|
||||
/* test if compression is blocked
|
||||
* either because output is slow and all buffers are full
|
||||
* or because input is slow and no job can start while waiting for at least one buffer to be filled.
|
||||
* note : excluse starting part, since currentJobID > 1 */
|
||||
* note : exclude starting part, since currentJobID > 1 */
|
||||
if ( (zfp.consumed == previous_zfp_update.consumed) /* no data compressed : no data available, or no more buffer to compress to, OR compression is really slow (compression of a single block is slower than update rate)*/
|
||||
&& (zfp.nbActiveWorkers == 0) /* confirmed : no compression ongoing */
|
||||
) {
|
||||
@@ -1000,7 +1102,7 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
|
||||
DISPLAYLEVEL(6, "compression level adaptation check \n")
|
||||
|
||||
/* check input speed */
|
||||
if (zfp.currentJobID > g_nbWorkers+1) { /* warm up period, to fill all workers */
|
||||
if (zfp.currentJobID > (unsigned)(prefs->nbWorkers+1)) { /* warm up period, to fill all workers */
|
||||
if (inputBlocked <= 0) {
|
||||
DISPLAYLEVEL(6, "input is never blocked => input is slower than ingestion \n");
|
||||
speedChange = slower;
|
||||
@@ -1032,14 +1134,14 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
|
||||
DISPLAYLEVEL(6, "slower speed , higher compression \n")
|
||||
compressionLevel ++;
|
||||
if (compressionLevel > ZSTD_maxCLevel()) compressionLevel = ZSTD_maxCLevel();
|
||||
if (compressionLevel > g_maxAdaptLevel) compressionLevel = g_maxAdaptLevel;
|
||||
if (compressionLevel > prefs->maxAdaptLevel) compressionLevel = prefs->maxAdaptLevel;
|
||||
compressionLevel += (compressionLevel == 0); /* skip 0 */
|
||||
ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, compressionLevel);
|
||||
}
|
||||
if (speedChange == faster) {
|
||||
DISPLAYLEVEL(6, "faster speed , lighter compression \n")
|
||||
compressionLevel --;
|
||||
if (compressionLevel < g_minAdaptLevel) compressionLevel = g_minAdaptLevel;
|
||||
if (compressionLevel < prefs->minAdaptLevel) compressionLevel = prefs->minAdaptLevel;
|
||||
compressionLevel -= (compressionLevel == 0); /* skip 0 */
|
||||
ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, compressionLevel);
|
||||
}
|
||||
@@ -1069,20 +1171,23 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
|
||||
* 1 : missing or pb opening srcFileName
|
||||
*/
|
||||
static int
|
||||
FIO_compressFilename_internal(cRess_t ress,
|
||||
FIO_compressFilename_internal(FIO_prefs_t* const prefs,
|
||||
cRess_t ress,
|
||||
const char* dstFileName, const char* srcFileName,
|
||||
int compressionLevel)
|
||||
{
|
||||
UTIL_time_t const timeStart = UTIL_getTime();
|
||||
clock_t const cpuStart = clock();
|
||||
U64 readsize = 0;
|
||||
U64 compressedfilesize = 0;
|
||||
U64 const fileSize = UTIL_getFileSize(srcFileName);
|
||||
DISPLAYLEVEL(5, "%s: %u bytes \n", srcFileName, (unsigned)fileSize);
|
||||
|
||||
/* compression format selection */
|
||||
switch (g_compressionType) {
|
||||
switch (prefs->compressionType) {
|
||||
default:
|
||||
case FIO_zstdCompression:
|
||||
compressedfilesize = FIO_compressZstdFrame(&ress, srcFileName, fileSize, compressionLevel, &readsize);
|
||||
compressedfilesize = FIO_compressZstdFrame(prefs, &ress, srcFileName, fileSize, compressionLevel, &readsize);
|
||||
break;
|
||||
|
||||
case FIO_gzipCompression:
|
||||
@@ -1098,7 +1203,7 @@ FIO_compressFilename_internal(cRess_t ress,
|
||||
case FIO_xzCompression:
|
||||
case FIO_lzmaCompression:
|
||||
#ifdef ZSTD_LZMACOMPRESS
|
||||
compressedfilesize = FIO_compressLzmaFrame(&ress, srcFileName, fileSize, compressionLevel, &readsize, g_compressionType==FIO_lzmaCompression);
|
||||
compressedfilesize = FIO_compressLzmaFrame(&ress, srcFileName, fileSize, compressionLevel, &readsize, prefs->compressionType==FIO_lzmaCompression);
|
||||
#else
|
||||
(void)compressionLevel;
|
||||
EXM_THROW(20, "zstd: %s: file cannot be compressed as xz/lzma (zstd compiled without ZSTD_LZMACOMPRESS) -- ignored \n",
|
||||
@@ -1108,7 +1213,7 @@ FIO_compressFilename_internal(cRess_t ress,
|
||||
|
||||
case FIO_lz4Compression:
|
||||
#ifdef ZSTD_LZ4COMPRESS
|
||||
compressedfilesize = FIO_compressLz4Frame(&ress, srcFileName, fileSize, compressionLevel, &readsize);
|
||||
compressedfilesize = FIO_compressLz4Frame(&ress, srcFileName, fileSize, compressionLevel, prefs->checksumFlag, &readsize);
|
||||
#else
|
||||
(void)compressionLevel;
|
||||
EXM_THROW(20, "zstd: %s: file cannot be compressed as lz4 (zstd compiled without ZSTD_LZ4COMPRESS) -- ignored \n",
|
||||
@@ -1125,6 +1230,15 @@ FIO_compressFilename_internal(cRess_t ress,
|
||||
(unsigned long long)readsize, (unsigned long long) compressedfilesize,
|
||||
dstFileName);
|
||||
|
||||
/* Elapsed Time and CPU Load */
|
||||
{ clock_t const cpuEnd = clock();
|
||||
double const cpuLoad_s = (double)(cpuEnd - cpuStart) / CLOCKS_PER_SEC;
|
||||
U64 const timeLength_ns = UTIL_clockSpanNano(timeStart);
|
||||
double const timeLength_s = (double)timeLength_ns / 1000000000;
|
||||
double const cpuLoad_pct = (cpuLoad_s / timeLength_s) * 100;
|
||||
DISPLAYLEVEL(4, "%-20s : Completed in %.2f sec (cpu load : %.0f%%)\n",
|
||||
srcFileName, timeLength_s, cpuLoad_pct);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1138,7 +1252,8 @@ FIO_compressFilename_internal(cRess_t ress,
|
||||
* @return : 0 : compression completed correctly,
|
||||
* 1 : pb
|
||||
*/
|
||||
static int FIO_compressFilename_dstFile(cRess_t ress,
|
||||
static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs,
|
||||
cRess_t ress,
|
||||
const char* dstFileName,
|
||||
const char* srcFileName,
|
||||
int compressionLevel)
|
||||
@@ -1153,7 +1268,7 @@ static int FIO_compressFilename_dstFile(cRess_t ress,
|
||||
if (ress.dstFile == NULL) {
|
||||
closeDstFile = 1;
|
||||
DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s", dstFileName);
|
||||
ress.dstFile = FIO_openDstFile(srcFileName, dstFileName);
|
||||
ress.dstFile = FIO_openDstFile(prefs, srcFileName, dstFileName);
|
||||
if (ress.dstFile==NULL) return 1; /* could not open dstFileName */
|
||||
/* Must only be added after FIO_openDstFile() succeeds.
|
||||
* Otherwise we may delete the destination file if it already exists,
|
||||
@@ -1166,7 +1281,7 @@ static int FIO_compressFilename_dstFile(cRess_t ress,
|
||||
transfer_permissions = 1;
|
||||
}
|
||||
|
||||
result = FIO_compressFilename_internal(ress, dstFileName, srcFileName, compressionLevel);
|
||||
result = FIO_compressFilename_internal(prefs, ress, dstFileName, srcFileName, compressionLevel);
|
||||
|
||||
if (closeDstFile) {
|
||||
FILE* const dstFile = ress.dstFile;
|
||||
@@ -1199,27 +1314,34 @@ static int FIO_compressFilename_dstFile(cRess_t ress,
|
||||
* 1 : missing or pb opening srcFileName
|
||||
*/
|
||||
static int
|
||||
FIO_compressFilename_srcFile(cRess_t ress,
|
||||
FIO_compressFilename_srcFile(FIO_prefs_t* const prefs,
|
||||
cRess_t ress,
|
||||
const char* dstFileName,
|
||||
const char* srcFileName,
|
||||
int compressionLevel)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* File check */
|
||||
/* ensure src is not a directory */
|
||||
if (UTIL_isDirectory(srcFileName)) {
|
||||
DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ensure src is not the same as dict (if present) */
|
||||
if (ress.dictFileName != NULL && UTIL_isSameFile(srcFileName, ress.dictFileName)) {
|
||||
DISPLAYLEVEL(1, "zstd: cannot use %s as an input file and dictionary \n", srcFileName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ress.srcFile = FIO_openSrcFile(srcFileName);
|
||||
if (ress.srcFile == NULL) return 1; /* srcFile could not be opened */
|
||||
|
||||
result = FIO_compressFilename_dstFile(ress, dstFileName, srcFileName, compressionLevel);
|
||||
result = FIO_compressFilename_dstFile(prefs, ress, dstFileName, srcFileName, compressionLevel);
|
||||
|
||||
fclose(ress.srcFile);
|
||||
ress.srcFile = NULL;
|
||||
if ( g_removeSrcFile /* --rm */
|
||||
if ( prefs->removeSrcFile /* --rm */
|
||||
&& result == 0 /* success */
|
||||
&& strcmp(srcFileName, stdinmark) /* exception : don't erase stdin */
|
||||
) {
|
||||
@@ -1234,19 +1356,17 @@ FIO_compressFilename_srcFile(cRess_t ress,
|
||||
}
|
||||
|
||||
|
||||
int FIO_compressFilename(const char* dstFileName, const char* srcFileName,
|
||||
int FIO_compressFilename(FIO_prefs_t* const prefs,
|
||||
const char* dstFileName, const char* srcFileName,
|
||||
const char* dictFileName, int compressionLevel,
|
||||
ZSTD_compressionParameters comprParams)
|
||||
{
|
||||
clock_t const start = clock();
|
||||
U64 const fileSize = UTIL_getFileSize(srcFileName);
|
||||
U64 const srcSize = (fileSize == UTIL_FILESIZE_UNKNOWN) ? ZSTD_CONTENTSIZE_UNKNOWN : fileSize;
|
||||
|
||||
cRess_t const ress = FIO_createCResources(dictFileName, compressionLevel, srcSize, comprParams);
|
||||
int const result = FIO_compressFilename_srcFile(ress, dstFileName, srcFileName, compressionLevel);
|
||||
cRess_t const ress = FIO_createCResources(prefs, dictFileName, compressionLevel, srcSize, comprParams);
|
||||
int const result = FIO_compressFilename_srcFile(prefs, ress, dstFileName, srcFileName, compressionLevel);
|
||||
|
||||
double const seconds = (double)(clock() - start) / CLOCKS_PER_SEC;
|
||||
DISPLAYLEVEL(4, "Completed in %.2f sec \n", seconds);
|
||||
|
||||
FIO_freeCResources(ress);
|
||||
return result;
|
||||
@@ -1288,7 +1408,8 @@ FIO_determineCompressedName(const char* srcFileName, const char* suffix)
|
||||
* into one destination (outFileName)
|
||||
* or into one file each (outFileName == NULL, but suffix != NULL).
|
||||
*/
|
||||
int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFiles,
|
||||
int FIO_compressMultipleFilenames(FIO_prefs_t* const prefs,
|
||||
const char** inFileNamesTable, unsigned nbFiles,
|
||||
const char* outFileName, const char* suffix,
|
||||
const char* dictFileName, int compressionLevel,
|
||||
ZSTD_compressionParameters comprParams)
|
||||
@@ -1297,19 +1418,19 @@ int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFile
|
||||
U64 const firstFileSize = UTIL_getFileSize(inFileNamesTable[0]);
|
||||
U64 const firstSrcSize = (firstFileSize == UTIL_FILESIZE_UNKNOWN) ? ZSTD_CONTENTSIZE_UNKNOWN : firstFileSize;
|
||||
U64 const srcSize = (nbFiles != 1) ? ZSTD_CONTENTSIZE_UNKNOWN : firstSrcSize ;
|
||||
cRess_t ress = FIO_createCResources(dictFileName, compressionLevel, srcSize, comprParams);
|
||||
cRess_t ress = FIO_createCResources(prefs, dictFileName, compressionLevel, srcSize, comprParams);
|
||||
|
||||
/* init */
|
||||
assert(outFileName != NULL || suffix != NULL);
|
||||
|
||||
if (outFileName != NULL) { /* output into a single destination (stdout typically) */
|
||||
ress.dstFile = FIO_openDstFile(NULL, outFileName);
|
||||
ress.dstFile = FIO_openDstFile(prefs, NULL, outFileName);
|
||||
if (ress.dstFile == NULL) { /* could not open outFileName */
|
||||
error = 1;
|
||||
} else {
|
||||
unsigned u;
|
||||
for (u=0; u<nbFiles; u++)
|
||||
error |= FIO_compressFilename_srcFile(ress, outFileName, inFileNamesTable[u], compressionLevel);
|
||||
error |= FIO_compressFilename_srcFile(prefs, ress, outFileName, inFileNamesTable[u], compressionLevel);
|
||||
if (fclose(ress.dstFile))
|
||||
EXM_THROW(29, "Write error (%s) : cannot properly close %s",
|
||||
strerror(errno), outFileName);
|
||||
@@ -1320,7 +1441,7 @@ int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFile
|
||||
for (u=0; u<nbFiles; u++) {
|
||||
const char* const srcFileName = inFileNamesTable[u];
|
||||
const char* const dstFileName = FIO_determineCompressedName(srcFileName, suffix); /* cannot fail */
|
||||
error |= FIO_compressFilename_srcFile(ress, dstFileName, srcFileName, compressionLevel);
|
||||
error |= FIO_compressFilename_srcFile(prefs, ress, dstFileName, srcFileName, compressionLevel);
|
||||
} }
|
||||
|
||||
FIO_freeCResources(ress);
|
||||
@@ -1346,7 +1467,7 @@ typedef struct {
|
||||
FILE* dstFile;
|
||||
} dRess_t;
|
||||
|
||||
static dRess_t FIO_createDResources(const char* dictFileName)
|
||||
static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFileName)
|
||||
{
|
||||
dRess_t ress;
|
||||
memset(&ress, 0, sizeof(ress));
|
||||
@@ -1355,7 +1476,7 @@ static dRess_t FIO_createDResources(const char* dictFileName)
|
||||
ress.dctx = ZSTD_createDStream();
|
||||
if (ress.dctx==NULL)
|
||||
EXM_THROW(60, "Error: %s : can't create ZSTD_DStream", strerror(errno));
|
||||
CHECK( ZSTD_DCtx_setMaxWindowSize(ress.dctx, g_memLimit) );
|
||||
CHECK( ZSTD_DCtx_setMaxWindowSize(ress.dctx, prefs->memLimit) );
|
||||
ress.srcBufferSize = ZSTD_DStreamInSize();
|
||||
ress.srcBuffer = malloc(ress.srcBufferSize);
|
||||
ress.dstBufferSize = ZSTD_DStreamOutSize();
|
||||
@@ -1383,7 +1504,7 @@ static void FIO_freeDResources(dRess_t ress)
|
||||
|
||||
/** FIO_fwriteSparse() :
|
||||
* @return : storedSkips, to be provided to next call to FIO_fwriteSparse() of LZ4IO_fwriteSparseEnd() */
|
||||
static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSize, unsigned storedSkips)
|
||||
static unsigned FIO_fwriteSparse(FIO_prefs_t* const prefs, FILE* file, const void* buffer, size_t bufferSize, unsigned storedSkips)
|
||||
{
|
||||
const size_t* const bufferT = (const size_t*)buffer; /* Buffer is supposed malloc'ed, hence aligned on size_t */
|
||||
size_t bufferSizeT = bufferSize / sizeof(size_t);
|
||||
@@ -1391,7 +1512,7 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
|
||||
const size_t* ptrT = bufferT;
|
||||
static const size_t segmentSizeT = (32 KB) / sizeof(size_t); /* 0-test re-attempted every 32 KB */
|
||||
|
||||
if (!g_sparseFileSupport) { /* normal write */
|
||||
if (!prefs->sparseFileSupport) { /* normal write */
|
||||
size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file);
|
||||
if (sizeCheck != bufferSize)
|
||||
EXM_THROW(70, "Write error : %s (cannot write decoded block)",
|
||||
@@ -1444,7 +1565,7 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
|
||||
if (seekResult)
|
||||
EXM_THROW(74, "Sparse skip error ; try --no-sparse");
|
||||
storedSkips = 0;
|
||||
{ size_t const sizeCheck = fwrite(restPtr, 1, restEnd - restPtr, file);
|
||||
{ size_t const sizeCheck = fwrite(restPtr, 1, (size_t)(restEnd - restPtr), file);
|
||||
if (sizeCheck != (size_t)(restEnd - restPtr))
|
||||
EXM_THROW(75, "Write error : cannot write decoded end of block");
|
||||
} } } }
|
||||
@@ -1452,10 +1573,12 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
|
||||
return storedSkips;
|
||||
}
|
||||
|
||||
static void FIO_fwriteSparseEnd(FILE* file, unsigned storedSkips)
|
||||
static void
|
||||
FIO_fwriteSparseEnd(FIO_prefs_t* const prefs, FILE* file, unsigned storedSkips)
|
||||
{
|
||||
if (storedSkips>0) {
|
||||
assert(g_sparseFileSupport > 0); /* storedSkips>0 implies sparse support is enabled */
|
||||
assert(prefs->sparseFileSupport > 0); /* storedSkips>0 implies sparse support is enabled */
|
||||
(void)prefs; /* assert can be disabled, in which case prefs becomes unused */
|
||||
if (LONG_SEEK(file, storedSkips-1, SEEK_CUR) != 0)
|
||||
EXM_THROW(69, "Final skip error (sparse file support)");
|
||||
/* last zero must be explicitly written,
|
||||
@@ -1469,7 +1592,10 @@ static void FIO_fwriteSparseEnd(FILE* file, unsigned storedSkips)
|
||||
|
||||
/** FIO_passThrough() : just copy input into output, for compatibility with gzip -df mode
|
||||
@return : 0 (no error) */
|
||||
static unsigned FIO_passThrough(FILE* foutput, FILE* finput, void* buffer, size_t bufferSize, size_t alreadyLoaded)
|
||||
static int FIO_passThrough(FIO_prefs_t* const prefs,
|
||||
FILE* foutput, FILE* finput,
|
||||
void* buffer, size_t bufferSize,
|
||||
size_t alreadyLoaded)
|
||||
{
|
||||
size_t const blockSize = MIN(64 KB, bufferSize);
|
||||
size_t readFromInput = 1;
|
||||
@@ -1484,10 +1610,10 @@ static unsigned FIO_passThrough(FILE* foutput, FILE* finput, void* buffer, size_
|
||||
|
||||
while (readFromInput) {
|
||||
readFromInput = fread(buffer, 1, blockSize, finput);
|
||||
storedSkips = FIO_fwriteSparse(foutput, buffer, readFromInput, storedSkips);
|
||||
storedSkips = FIO_fwriteSparse(prefs, foutput, buffer, readFromInput, storedSkips);
|
||||
}
|
||||
|
||||
FIO_fwriteSparseEnd(foutput, storedSkips);
|
||||
FIO_fwriteSparseEnd(prefs, foutput, storedSkips);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1506,7 +1632,7 @@ static unsigned FIO_highbit64(unsigned long long v)
|
||||
|
||||
/* FIO_zstdErrorHelp() :
|
||||
* detailed error message when requested window size is too large */
|
||||
static void FIO_zstdErrorHelp(dRess_t* ress, size_t err, char const* srcFileName)
|
||||
static void FIO_zstdErrorHelp(FIO_prefs_t* const prefs, dRess_t* ress, size_t err, char const* srcFileName)
|
||||
{
|
||||
ZSTD_frameHeader header;
|
||||
|
||||
@@ -1519,9 +1645,9 @@ static void FIO_zstdErrorHelp(dRess_t* ress, size_t err, char const* srcFileName
|
||||
if (err == 0) {
|
||||
unsigned long long const windowSize = header.windowSize;
|
||||
unsigned const windowLog = FIO_highbit64(windowSize) + ((windowSize & (windowSize - 1)) != 0);
|
||||
assert(g_memLimit > 0);
|
||||
assert(prefs->memLimit > 0);
|
||||
DISPLAYLEVEL(1, "%s : Window size larger than maximum : %llu > %u\n",
|
||||
srcFileName, windowSize, g_memLimit);
|
||||
srcFileName, windowSize, prefs->memLimit);
|
||||
if (windowLog <= ZSTD_WINDOWLOG_MAX) {
|
||||
unsigned const windowMB = (unsigned)((windowSize >> 20) + ((windowSize & ((1 MB) - 1)) != 0));
|
||||
assert(windowSize < (U64)(1ULL << 52)); /* ensure now overflow for windowMB */
|
||||
@@ -1538,7 +1664,9 @@ static void FIO_zstdErrorHelp(dRess_t* ress, size_t err, char const* srcFileName
|
||||
* @return : size of decoded zstd frame, or an error code
|
||||
*/
|
||||
#define FIO_ERROR_FRAME_DECODING ((unsigned long long)(-2))
|
||||
static unsigned long long FIO_decompressZstdFrame(dRess_t* ress,
|
||||
static unsigned long long FIO_decompressZstdFrame(
|
||||
FIO_prefs_t* const prefs,
|
||||
dRess_t* ress,
|
||||
FILE* finput,
|
||||
const char* srcFileName,
|
||||
U64 alreadyDecoded)
|
||||
@@ -1567,12 +1695,12 @@ static unsigned long long FIO_decompressZstdFrame(dRess_t* ress,
|
||||
if (ZSTD_isError(readSizeHint)) {
|
||||
DISPLAYLEVEL(1, "%s : Decoding error (36) : %s \n",
|
||||
srcFileName, ZSTD_getErrorName(readSizeHint));
|
||||
FIO_zstdErrorHelp(ress, readSizeHint, srcFileName);
|
||||
FIO_zstdErrorHelp(prefs, ress, readSizeHint, srcFileName);
|
||||
return FIO_ERROR_FRAME_DECODING;
|
||||
}
|
||||
|
||||
/* Write block */
|
||||
storedSkips = FIO_fwriteSparse(ress->dstFile, ress->dstBuffer, outBuff.pos, storedSkips);
|
||||
storedSkips = FIO_fwriteSparse(prefs, ress->dstFile, ress->dstBuffer, outBuff.pos, storedSkips);
|
||||
frameSize += outBuff.pos;
|
||||
DISPLAYUPDATE(2, "\r%-20.20s : %u MB... ",
|
||||
srcFileName, (unsigned)((alreadyDecoded+frameSize)>>20) );
|
||||
@@ -1603,7 +1731,7 @@ static unsigned long long FIO_decompressZstdFrame(dRess_t* ress,
|
||||
ress->srcBufferLoaded += readSize;
|
||||
} } }
|
||||
|
||||
FIO_fwriteSparseEnd(ress->dstFile, storedSkips);
|
||||
FIO_fwriteSparseEnd(prefs, ress->dstFile, storedSkips);
|
||||
|
||||
return frameSize;
|
||||
}
|
||||
@@ -1834,7 +1962,7 @@ static unsigned long long FIO_decompressLz4Frame(dRess_t* ress,
|
||||
* @return : 0 : OK
|
||||
* 1 : error
|
||||
*/
|
||||
static int FIO_decompressFrames(dRess_t ress, FILE* srcFile,
|
||||
static int FIO_decompressFrames(FIO_prefs_t* const prefs, dRess_t ress, FILE* srcFile,
|
||||
const char* dstFileName, const char* srcFileName)
|
||||
{
|
||||
unsigned readSomething = 0;
|
||||
@@ -1862,7 +1990,7 @@ static int FIO_decompressFrames(dRess_t ress, FILE* srcFile,
|
||||
return 1;
|
||||
}
|
||||
if (ZSTD_isFrame(buf, ress.srcBufferLoaded)) {
|
||||
unsigned long long const frameSize = FIO_decompressZstdFrame(&ress, srcFile, srcFileName, filesize);
|
||||
unsigned long long const frameSize = FIO_decompressZstdFrame(prefs, &ress, srcFile, srcFileName, filesize);
|
||||
if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;
|
||||
filesize += frameSize;
|
||||
} else if (buf[0] == 31 && buf[1] == 139) { /* gz magic number */
|
||||
@@ -1893,9 +2021,11 @@ static int FIO_decompressFrames(dRess_t ress, FILE* srcFile,
|
||||
DISPLAYLEVEL(1, "zstd: %s: lz4 file cannot be uncompressed (zstd compiled without HAVE_LZ4) -- ignored \n", srcFileName);
|
||||
return 1;
|
||||
#endif
|
||||
} else if ((g_overwrite) && !strcmp (dstFileName, stdoutmark)) { /* pass-through mode */
|
||||
return FIO_passThrough(ress.dstFile, srcFile,
|
||||
ress.srcBuffer, ress.srcBufferSize, ress.srcBufferLoaded);
|
||||
} else if ((prefs->overwrite) && !strcmp (dstFileName, stdoutmark)) { /* pass-through mode */
|
||||
return FIO_passThrough(prefs,
|
||||
ress.dstFile, srcFile,
|
||||
ress.srcBuffer, ress.srcBufferSize,
|
||||
ress.srcBufferLoaded);
|
||||
} else {
|
||||
DISPLAYLEVEL(1, "zstd: %s: unsupported format \n", srcFileName);
|
||||
return 1;
|
||||
@@ -1915,7 +2045,8 @@ static int FIO_decompressFrames(dRess_t ress, FILE* srcFile,
|
||||
@return : 0 : OK
|
||||
1 : operation aborted
|
||||
*/
|
||||
static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile,
|
||||
static int FIO_decompressDstFile(FIO_prefs_t* const prefs,
|
||||
dRess_t ress, FILE* srcFile,
|
||||
const char* dstFileName, const char* srcFileName)
|
||||
{
|
||||
int result;
|
||||
@@ -1926,7 +2057,7 @@ static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile,
|
||||
if (ress.dstFile == NULL) {
|
||||
releaseDstFile = 1;
|
||||
|
||||
ress.dstFile = FIO_openDstFile(srcFileName, dstFileName);
|
||||
ress.dstFile = FIO_openDstFile(prefs, srcFileName, dstFileName);
|
||||
if (ress.dstFile==0) return 1;
|
||||
|
||||
/* Must only be added after FIO_openDstFile() succeeds.
|
||||
@@ -1941,7 +2072,7 @@ static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile,
|
||||
}
|
||||
|
||||
|
||||
result = FIO_decompressFrames(ress, srcFile, dstFileName, srcFileName);
|
||||
result = FIO_decompressFrames(prefs, ress, srcFile, dstFileName, srcFileName);
|
||||
|
||||
if (releaseDstFile) {
|
||||
FILE* const dstFile = ress.dstFile;
|
||||
@@ -1974,7 +2105,7 @@ static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile,
|
||||
@return : 0 : OK
|
||||
1 : error
|
||||
*/
|
||||
static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const char* srcFileName)
|
||||
static int FIO_decompressSrcFile(FIO_prefs_t* const prefs, dRess_t ress, const char* dstFileName, const char* srcFileName)
|
||||
{
|
||||
FILE* srcFile;
|
||||
int result;
|
||||
@@ -1988,14 +2119,14 @@ static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const ch
|
||||
if (srcFile==NULL) return 1;
|
||||
ress.srcBufferLoaded = 0;
|
||||
|
||||
result = FIO_decompressDstFile(ress, srcFile, dstFileName, srcFileName);
|
||||
result = FIO_decompressDstFile(prefs, ress, srcFile, dstFileName, srcFileName);
|
||||
|
||||
/* Close file */
|
||||
if (fclose(srcFile)) {
|
||||
DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno)); /* error should not happen */
|
||||
return 1;
|
||||
}
|
||||
if ( g_removeSrcFile /* --rm */
|
||||
if ( prefs->removeSrcFile /* --rm */
|
||||
&& (result==0) /* decompression successful */
|
||||
&& strcmp(srcFileName, stdinmark) ) /* not stdin */ {
|
||||
/* We must clear the handler, since after this point calling it would
|
||||
@@ -2012,12 +2143,13 @@ static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const ch
|
||||
|
||||
|
||||
|
||||
int FIO_decompressFilename(const char* dstFileName, const char* srcFileName,
|
||||
int FIO_decompressFilename(FIO_prefs_t* const prefs,
|
||||
const char* dstFileName, const char* srcFileName,
|
||||
const char* dictFileName)
|
||||
{
|
||||
dRess_t const ress = FIO_createDResources(dictFileName);
|
||||
dRess_t const ress = FIO_createDResources(prefs, dictFileName);
|
||||
|
||||
int const decodingError = FIO_decompressSrcFile(ress, dstFileName, srcFileName);
|
||||
int const decodingError = FIO_decompressSrcFile(prefs, ress, dstFileName, srcFileName);
|
||||
|
||||
FIO_freeDResources(ress);
|
||||
return decodingError;
|
||||
@@ -2094,19 +2226,20 @@ FIO_determineDstName(const char* srcFileName)
|
||||
|
||||
|
||||
int
|
||||
FIO_decompressMultipleFilenames(const char* srcNamesTable[], unsigned nbFiles,
|
||||
FIO_decompressMultipleFilenames(FIO_prefs_t* const prefs,
|
||||
const char* srcNamesTable[], unsigned nbFiles,
|
||||
const char* outFileName,
|
||||
const char* dictFileName)
|
||||
{
|
||||
int error = 0;
|
||||
dRess_t ress = FIO_createDResources(dictFileName);
|
||||
dRess_t ress = FIO_createDResources(prefs, dictFileName);
|
||||
|
||||
if (outFileName) {
|
||||
unsigned u;
|
||||
ress.dstFile = FIO_openDstFile(NULL, outFileName);
|
||||
ress.dstFile = FIO_openDstFile(prefs, NULL, outFileName);
|
||||
if (ress.dstFile == 0) EXM_THROW(71, "cannot open %s", outFileName);
|
||||
for (u=0; u<nbFiles; u++)
|
||||
error |= FIO_decompressSrcFile(ress, outFileName, srcNamesTable[u]);
|
||||
error |= FIO_decompressSrcFile(prefs, ress, outFileName, srcNamesTable[u]);
|
||||
if (fclose(ress.dstFile))
|
||||
EXM_THROW(72, "Write error : %s : cannot properly close output file",
|
||||
strerror(errno));
|
||||
@@ -2117,7 +2250,7 @@ FIO_decompressMultipleFilenames(const char* srcNamesTable[], unsigned nbFiles,
|
||||
const char* const dstFileName = FIO_determineDstName(srcFileName);
|
||||
if (dstFileName == NULL) { error=1; continue; }
|
||||
|
||||
error |= FIO_decompressSrcFile(ress, dstFileName, srcFileName);
|
||||
error |= FIO_decompressSrcFile(prefs, ress, dstFileName, srcFileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2142,7 +2275,13 @@ typedef struct {
|
||||
U32 nbFiles;
|
||||
} fileInfo_t;
|
||||
|
||||
typedef enum { info_success=0, info_frame_error=1, info_not_zstd=2, info_file_error=3 } InfoError;
|
||||
typedef enum {
|
||||
info_success=0,
|
||||
info_frame_error=1,
|
||||
info_not_zstd=2,
|
||||
info_file_error=3,
|
||||
info_truncated_input=4,
|
||||
} InfoError;
|
||||
|
||||
#define ERROR_IF(c,n,...) { \
|
||||
if (c) { \
|
||||
@@ -2164,6 +2303,12 @@ FIO_analyzeFrames(fileInfo_t* info, FILE* const srcFile)
|
||||
&& (numBytesRead == 0)
|
||||
&& (info->compressedSize > 0)
|
||||
&& (info->compressedSize != UTIL_FILESIZE_UNKNOWN) ) {
|
||||
unsigned long long file_position = (unsigned long long) LONG_TELL(srcFile);
|
||||
unsigned long long file_size = (unsigned long long) info->compressedSize;
|
||||
ERROR_IF(file_position != file_size, info_truncated_input,
|
||||
"Error: seeked to position %llu, which is beyond file size of %llu\n",
|
||||
file_position,
|
||||
file_size);
|
||||
break; /* correct end of file => success */
|
||||
}
|
||||
ERROR_IF(feof(srcFile), info_not_zstd, "Error: reached end of file with incomplete frame");
|
||||
@@ -2332,20 +2477,28 @@ FIO_listFile(fileInfo_t* total, const char* inFileName, int displayLevel)
|
||||
fileInfo_t info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
{ InfoError const error = getFileInfo(&info, inFileName);
|
||||
if (error == info_frame_error) {
|
||||
/* display error, but provide output */
|
||||
DISPLAYLEVEL(1, "Error while parsing %s \n", inFileName);
|
||||
}
|
||||
else if (error == info_not_zstd) {
|
||||
DISPLAYOUT("File %s not compressed by zstd \n", inFileName);
|
||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||
return 1;
|
||||
}
|
||||
else if (error == info_file_error) {
|
||||
/* error occurred while opening the file */
|
||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||
return 1;
|
||||
switch (error) {
|
||||
case info_frame_error:
|
||||
/* display error, but provide output */
|
||||
DISPLAYLEVEL(1, "Error while parsing \"%s\" \n", inFileName);
|
||||
break;
|
||||
case info_not_zstd:
|
||||
DISPLAYOUT("File \"%s\" not compressed by zstd \n", inFileName);
|
||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||
return 1;
|
||||
case info_file_error:
|
||||
/* error occurred while opening the file */
|
||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||
return 1;
|
||||
case info_truncated_input:
|
||||
DISPLAYOUT("File \"%s\" is truncated \n", inFileName);
|
||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||
return 1;
|
||||
case info_success:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
displayInfo(inFileName, &info, displayLevel);
|
||||
*total = FIO_addFInfo(*total, info);
|
||||
assert(error == info_success || error == info_frame_error);
|
||||
|
||||
+39
-25
@@ -42,44 +42,56 @@ extern "C" {
|
||||
***************************************/
|
||||
typedef enum { FIO_zstdCompression, FIO_gzipCompression, FIO_xzCompression, FIO_lzmaCompression, FIO_lz4Compression } FIO_compressionType_t;
|
||||
|
||||
typedef struct FIO_prefs_s FIO_prefs_t;
|
||||
|
||||
FIO_prefs_t* FIO_createPreferences(void);
|
||||
void FIO_freePreferences(FIO_prefs_t* const prefs);
|
||||
|
||||
typedef struct FIO_display_prefs_s FIO_display_prefs_t;
|
||||
|
||||
/*-*************************************
|
||||
* Parameters
|
||||
***************************************/
|
||||
void FIO_setCompressionType(FIO_compressionType_t compressionType);
|
||||
void FIO_overwriteMode(void);
|
||||
void FIO_setAdaptiveMode(unsigned adapt);
|
||||
void FIO_setAdaptMin(int minCLevel);
|
||||
void FIO_setAdaptMax(int maxCLevel);
|
||||
void FIO_setBlockSize(unsigned blockSize);
|
||||
void FIO_setChecksumFlag(unsigned checksumFlag);
|
||||
void FIO_setDictIDFlag(unsigned dictIDFlag);
|
||||
void FIO_setLdmBucketSizeLog(unsigned ldmBucketSizeLog);
|
||||
void FIO_setLdmFlag(unsigned ldmFlag);
|
||||
void FIO_setLdmHashRateLog(unsigned ldmHashRateLog);
|
||||
void FIO_setLdmHashLog(unsigned ldmHashLog);
|
||||
void FIO_setLdmMinMatch(unsigned ldmMinMatch);
|
||||
void FIO_setMemLimit(unsigned memLimit);
|
||||
void FIO_setNbWorkers(unsigned nbWorkers);
|
||||
void FIO_setNotificationLevel(unsigned level);
|
||||
void FIO_setOverlapLog(unsigned overlapLog);
|
||||
void FIO_setRemoveSrcFile(unsigned flag);
|
||||
void FIO_setSparseWrite(unsigned sparse); /**< 0: no sparse; 1: disable on stdout; 2: always enabled */
|
||||
void FIO_setRsyncable(unsigned rsyncable);
|
||||
void FIO_setNoProgress(unsigned noProgress);
|
||||
void FIO_setCompressionType(FIO_prefs_t* const prefs, FIO_compressionType_t compressionType);
|
||||
void FIO_overwriteMode(FIO_prefs_t* const prefs);
|
||||
void FIO_setAdaptiveMode(FIO_prefs_t* const prefs, unsigned adapt);
|
||||
void FIO_setAdaptMin(FIO_prefs_t* const prefs, int minCLevel);
|
||||
void FIO_setAdaptMax(FIO_prefs_t* const prefs, int maxCLevel);
|
||||
void FIO_setBlockSize(FIO_prefs_t* const prefs, int blockSize);
|
||||
void FIO_setChecksumFlag(FIO_prefs_t* const prefs, int checksumFlag);
|
||||
void FIO_setDictIDFlag(FIO_prefs_t* const prefs, int dictIDFlag);
|
||||
void FIO_setLdmBucketSizeLog(FIO_prefs_t* const prefs, int ldmBucketSizeLog);
|
||||
void FIO_setLdmFlag(FIO_prefs_t* const prefs, unsigned ldmFlag);
|
||||
void FIO_setLdmHashRateLog(FIO_prefs_t* const prefs, int ldmHashRateLog);
|
||||
void FIO_setLdmHashLog(FIO_prefs_t* const prefs, int ldmHashLog);
|
||||
void FIO_setLdmMinMatch(FIO_prefs_t* const prefs, int ldmMinMatch);
|
||||
void FIO_setMemLimit(FIO_prefs_t* const prefs, unsigned memLimit);
|
||||
void FIO_setNbWorkers(FIO_prefs_t* const prefs, int nbWorkers);
|
||||
void FIO_setOverlapLog(FIO_prefs_t* const prefs, int overlapLog);
|
||||
void FIO_setRemoveSrcFile(FIO_prefs_t* const prefs, unsigned flag);
|
||||
void FIO_setSparseWrite(FIO_prefs_t* const prefs, unsigned sparse); /**< 0: no sparse; 1: disable on stdout; 2: always enabled */
|
||||
void FIO_setRsyncable(FIO_prefs_t* const prefs, int rsyncable);
|
||||
void FIO_setTargetCBlockSize(FIO_prefs_t* const prefs, size_t targetCBlockSize);
|
||||
void FIO_setLiteralCompressionMode(
|
||||
FIO_prefs_t* const prefs,
|
||||
ZSTD_literalCompressionMode_e mode);
|
||||
|
||||
void FIO_setNoProgress(unsigned noProgress);
|
||||
void FIO_setNotificationLevel(int level);
|
||||
|
||||
/*-*************************************
|
||||
* Single File functions
|
||||
***************************************/
|
||||
/** FIO_compressFilename() :
|
||||
@return : 0 == ok; 1 == pb with src file. */
|
||||
int FIO_compressFilename (const char* outfilename, const char* infilename, const char* dictFileName,
|
||||
int FIO_compressFilename (FIO_prefs_t* const prefs,
|
||||
const char* outfilename, const char* infilename, const char* dictFileName,
|
||||
int compressionLevel, ZSTD_compressionParameters comprParams);
|
||||
|
||||
/** FIO_decompressFilename() :
|
||||
@return : 0 == ok; 1 == pb with src file. */
|
||||
int FIO_decompressFilename (const char* outfilename, const char* infilename, const char* dictFileName);
|
||||
int FIO_decompressFilename (FIO_prefs_t* const prefs,
|
||||
const char* outfilename, const char* infilename, const char* dictFileName);
|
||||
|
||||
int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel);
|
||||
|
||||
@@ -89,14 +101,16 @@ int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int dis
|
||||
***************************************/
|
||||
/** FIO_compressMultipleFilenames() :
|
||||
@return : nb of missing files */
|
||||
int FIO_compressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles,
|
||||
int FIO_compressMultipleFilenames(FIO_prefs_t* const prefs,
|
||||
const char** srcNamesTable, unsigned nbFiles,
|
||||
const char* outFileName, const char* suffix,
|
||||
const char* dictFileName, int compressionLevel,
|
||||
ZSTD_compressionParameters comprParams);
|
||||
|
||||
/** FIO_decompressMultipleFilenames() :
|
||||
@return : nb of missing or skipped files */
|
||||
int FIO_decompressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles,
|
||||
int FIO_decompressMultipleFilenames(FIO_prefs_t* const prefs,
|
||||
const char** srcNamesTable, unsigned nbFiles,
|
||||
const char* outFileName,
|
||||
const char* dictFileName);
|
||||
|
||||
|
||||
+3
-2
@@ -87,8 +87,8 @@ extern "C" {
|
||||
* The following list of build macros tries to "guess" if target OS is likely unix-like, and therefore can #include <unistd.h>
|
||||
*/
|
||||
# elif !defined(_WIN32) \
|
||||
&& (defined(__unix__) || defined(__unix) \
|
||||
|| defined(__midipix__) || defined(__VMS) || defined(__HAIKU__))
|
||||
&& ( defined(__unix__) || defined(__unix) \
|
||||
|| defined(__midipix__) || defined(__VMS) || defined(__HAIKU__) )
|
||||
|
||||
# if defined(__linux__) || defined(__linux)
|
||||
# ifndef _POSIX_C_SOURCE
|
||||
@@ -108,6 +108,7 @@ extern "C" {
|
||||
|
||||
#endif /* PLATFORM_POSIX_VERSION */
|
||||
|
||||
|
||||
/*-*********************************************
|
||||
* Detect if isatty() and fileno() are available
|
||||
************************************************/
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2019-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
|
||||
/* === Dependencies === */
|
||||
|
||||
#include "timefn.h"
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Time functions
|
||||
******************************************/
|
||||
|
||||
#if defined(_WIN32) /* Windows */
|
||||
|
||||
#include <stdlib.h> /* abort */
|
||||
#include <stdio.h> /* perror */
|
||||
|
||||
UTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; }
|
||||
|
||||
PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
|
||||
{
|
||||
static LARGE_INTEGER ticksPerSecond;
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
if (!QueryPerformanceFrequency(&ticksPerSecond)) {
|
||||
perror("timefn::QueryPerformanceFrequency");
|
||||
abort();
|
||||
}
|
||||
init = 1;
|
||||
}
|
||||
return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
|
||||
}
|
||||
|
||||
PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
|
||||
{
|
||||
static LARGE_INTEGER ticksPerSecond;
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
if (!QueryPerformanceFrequency(&ticksPerSecond)) {
|
||||
perror("timefn::QueryPerformanceFrequency");
|
||||
abort();
|
||||
}
|
||||
init = 1;
|
||||
}
|
||||
return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); }
|
||||
|
||||
PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
|
||||
{
|
||||
static mach_timebase_info_data_t rate;
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
mach_timebase_info(&rate);
|
||||
init = 1;
|
||||
}
|
||||
return (((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom))/1000ULL;
|
||||
}
|
||||
|
||||
PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
|
||||
{
|
||||
static mach_timebase_info_data_t rate;
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
mach_timebase_info(&rate);
|
||||
init = 1;
|
||||
}
|
||||
return ((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \
|
||||
&& defined(TIME_UTC) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */
|
||||
|
||||
#include <stdlib.h> /* abort */
|
||||
#include <stdio.h> /* perror */
|
||||
|
||||
UTIL_time_t UTIL_getTime(void)
|
||||
{
|
||||
/* time must be initialized, othersize it may fail msan test.
|
||||
* No good reason, likely a limitation of timespec_get() for some target */
|
||||
UTIL_time_t time = UTIL_TIME_INITIALIZER;
|
||||
if (timespec_get(&time, TIME_UTC) != TIME_UTC) {
|
||||
perror("timefn::timespec_get");
|
||||
abort();
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
static UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end)
|
||||
{
|
||||
UTIL_time_t diff;
|
||||
if (end.tv_nsec < begin.tv_nsec) {
|
||||
diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec;
|
||||
diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec;
|
||||
} else {
|
||||
diff.tv_sec = end.tv_sec - begin.tv_sec;
|
||||
diff.tv_nsec = end.tv_nsec - begin.tv_nsec;
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
PTime UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end)
|
||||
{
|
||||
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
|
||||
PTime micro = 0;
|
||||
micro += 1000000ULL * diff.tv_sec;
|
||||
micro += diff.tv_nsec / 1000ULL;
|
||||
return micro;
|
||||
}
|
||||
|
||||
PTime UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end)
|
||||
{
|
||||
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
|
||||
PTime nano = 0;
|
||||
nano += 1000000000ULL * diff.tv_sec;
|
||||
nano += diff.tv_nsec;
|
||||
return nano;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else /* relies on standard C90 (note : clock_t measurements can be wrong when using multi-threading) */
|
||||
|
||||
UTIL_time_t UTIL_getTime(void) { return clock(); }
|
||||
PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
|
||||
PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* returns time span in microseconds */
|
||||
PTime UTIL_clockSpanMicro(UTIL_time_t clockStart )
|
||||
{
|
||||
UTIL_time_t const clockEnd = UTIL_getTime();
|
||||
return UTIL_getSpanTimeMicro(clockStart, clockEnd);
|
||||
}
|
||||
|
||||
/* returns time span in microseconds */
|
||||
PTime UTIL_clockSpanNano(UTIL_time_t clockStart )
|
||||
{
|
||||
UTIL_time_t const clockEnd = UTIL_getTime();
|
||||
return UTIL_getSpanTimeNano(clockStart, clockEnd);
|
||||
}
|
||||
|
||||
void UTIL_waitForNextTick(void)
|
||||
{
|
||||
UTIL_time_t const clockStart = UTIL_getTime();
|
||||
UTIL_time_t clockEnd;
|
||||
do {
|
||||
clockEnd = UTIL_getTime();
|
||||
} while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#ifndef TIME_FN_H_MODULE_287987
|
||||
#define TIME_FN_H_MODULE_287987
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Dependencies
|
||||
******************************************/
|
||||
#include <sys/types.h> /* utime */
|
||||
#if defined(_MSC_VER)
|
||||
# include <sys/utime.h> /* utime */
|
||||
#else
|
||||
# include <utime.h> /* utime */
|
||||
#endif
|
||||
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
|
||||
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Local Types
|
||||
******************************************/
|
||||
|
||||
#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
|
||||
# include <stdint.h>
|
||||
typedef uint64_t PTime; /* Precise Time */
|
||||
#else
|
||||
typedef unsigned long long PTime; /* does not support compilers without long long support */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Time functions
|
||||
******************************************/
|
||||
#if defined(_WIN32) /* Windows */
|
||||
|
||||
#include <Windows.h> /* LARGE_INTEGER */
|
||||
typedef LARGE_INTEGER UTIL_time_t;
|
||||
#define UTIL_TIME_INITIALIZER { { 0, 0 } }
|
||||
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
#include <mach/mach_time.h>
|
||||
typedef PTime UTIL_time_t;
|
||||
#define UTIL_TIME_INITIALIZER 0
|
||||
|
||||
#elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \
|
||||
&& defined(TIME_UTC) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */
|
||||
|
||||
typedef struct timespec UTIL_time_t;
|
||||
#define UTIL_TIME_INITIALIZER { 0, 0 }
|
||||
|
||||
#else /* relies on standard C90 (note : clock_t measurements can be wrong when using multi-threading) */
|
||||
|
||||
typedef clock_t UTIL_time_t;
|
||||
#define UTIL_TIME_INITIALIZER 0
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
UTIL_time_t UTIL_getTime(void);
|
||||
PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd);
|
||||
PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd);
|
||||
|
||||
#define SEC_TO_MICRO ((PTime)1000000)
|
||||
PTime UTIL_clockSpanMicro(UTIL_time_t clockStart);
|
||||
PTime UTIL_clockSpanNano(UTIL_time_t clockStart);
|
||||
|
||||
void UTIL_waitForNextTick(void);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TIME_FN_H_MODULE_287987 */
|
||||
+56
-141
@@ -87,20 +87,31 @@ U32 UTIL_isDirectory(const char* infilename)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UTIL_isSameFile(const char* file1, const char* file2)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
/* note : Visual does not support file identification by inode.
|
||||
* The following work-around is limited to detecting exact name repetition only,
|
||||
* aka `filename` is considered different from `subdir/../filename` */
|
||||
return !strcmp(file1, file2);
|
||||
#else
|
||||
stat_t file1Stat;
|
||||
stat_t file2Stat;
|
||||
return UTIL_getFileStat(file1, &file1Stat)
|
||||
&& UTIL_getFileStat(file2, &file2Stat)
|
||||
&& (file1Stat.st_dev == file2Stat.st_dev)
|
||||
&& (file1Stat.st_ino == file2Stat.st_ino);
|
||||
#endif
|
||||
}
|
||||
|
||||
U32 UTIL_isLink(const char* infilename)
|
||||
{
|
||||
/* macro guards, as defined in : https://linux.die.net/man/2/lstat */
|
||||
#ifndef __STRICT_ANSI__
|
||||
#if defined(_BSD_SOURCE) \
|
||||
|| (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|
||||
|| (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) \
|
||||
|| (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \
|
||||
|| (defined(__APPLE__) && defined(__MACH__))
|
||||
#if PLATFORM_POSIX_VERSION >= 200112L
|
||||
int r;
|
||||
stat_t statbuf;
|
||||
r = lstat(infilename, &statbuf);
|
||||
if (!r && S_ISLNK(statbuf.st_mode)) return 1;
|
||||
#endif
|
||||
#endif
|
||||
(void)infilename;
|
||||
return 0;
|
||||
@@ -333,146 +344,18 @@ UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
|
||||
return fileTable;
|
||||
}
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Console log
|
||||
******************************************/
|
||||
int g_utilDisplayLevel;
|
||||
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Time functions
|
||||
* count the number of physical cores
|
||||
******************************************/
|
||||
#if defined(_WIN32) /* Windows */
|
||||
|
||||
UTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; }
|
||||
|
||||
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
|
||||
{
|
||||
static LARGE_INTEGER ticksPerSecond;
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
if (!QueryPerformanceFrequency(&ticksPerSecond))
|
||||
UTIL_DISPLAYLEVEL(1, "ERROR: QueryPerformanceFrequency() failure\n");
|
||||
init = 1;
|
||||
}
|
||||
return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
|
||||
}
|
||||
|
||||
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
|
||||
{
|
||||
static LARGE_INTEGER ticksPerSecond;
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
if (!QueryPerformanceFrequency(&ticksPerSecond))
|
||||
UTIL_DISPLAYLEVEL(1, "ERROR: QueryPerformanceFrequency() failure\n");
|
||||
init = 1;
|
||||
}
|
||||
return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); }
|
||||
|
||||
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
|
||||
{
|
||||
static mach_timebase_info_data_t rate;
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
mach_timebase_info(&rate);
|
||||
init = 1;
|
||||
}
|
||||
return (((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom))/1000ULL;
|
||||
}
|
||||
|
||||
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
|
||||
{
|
||||
static mach_timebase_info_data_t rate;
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
mach_timebase_info(&rate);
|
||||
init = 1;
|
||||
}
|
||||
return ((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom);
|
||||
}
|
||||
|
||||
#elif (PLATFORM_POSIX_VERSION >= 200112L) \
|
||||
&& (defined(__UCLIBC__) \
|
||||
|| (defined(__GLIBC__) \
|
||||
&& ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) \
|
||||
|| (__GLIBC__ > 2))))
|
||||
|
||||
UTIL_time_t UTIL_getTime(void)
|
||||
{
|
||||
UTIL_time_t time;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &time))
|
||||
UTIL_DISPLAYLEVEL(1, "ERROR: Failed to get time\n"); /* we could also exit() */
|
||||
return time;
|
||||
}
|
||||
|
||||
UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end)
|
||||
{
|
||||
UTIL_time_t diff;
|
||||
if (end.tv_nsec < begin.tv_nsec) {
|
||||
diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec;
|
||||
diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec;
|
||||
} else {
|
||||
diff.tv_sec = end.tv_sec - begin.tv_sec;
|
||||
diff.tv_nsec = end.tv_nsec - begin.tv_nsec;
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
U64 UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end)
|
||||
{
|
||||
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
|
||||
U64 micro = 0;
|
||||
micro += 1000000ULL * diff.tv_sec;
|
||||
micro += diff.tv_nsec / 1000ULL;
|
||||
return micro;
|
||||
}
|
||||
|
||||
U64 UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end)
|
||||
{
|
||||
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
|
||||
U64 nano = 0;
|
||||
nano += 1000000000ULL * diff.tv_sec;
|
||||
nano += diff.tv_nsec;
|
||||
return nano;
|
||||
}
|
||||
|
||||
#else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */
|
||||
|
||||
UTIL_time_t UTIL_getTime(void) { return clock(); }
|
||||
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
|
||||
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
|
||||
|
||||
#endif
|
||||
|
||||
/* returns time span in microseconds */
|
||||
U64 UTIL_clockSpanMicro(UTIL_time_t clockStart )
|
||||
{
|
||||
UTIL_time_t const clockEnd = UTIL_getTime();
|
||||
return UTIL_getSpanTimeMicro(clockStart, clockEnd);
|
||||
}
|
||||
|
||||
/* returns time span in microseconds */
|
||||
U64 UTIL_clockSpanNano(UTIL_time_t clockStart )
|
||||
{
|
||||
UTIL_time_t const clockEnd = UTIL_getTime();
|
||||
return UTIL_getSpanTimeNano(clockStart, clockEnd);
|
||||
}
|
||||
|
||||
void UTIL_waitForNextTick(void)
|
||||
{
|
||||
UTIL_time_t const clockStart = UTIL_getTime();
|
||||
UTIL_time_t clockEnd;
|
||||
do {
|
||||
clockEnd = UTIL_getTime();
|
||||
} while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0);
|
||||
}
|
||||
|
||||
/* count the number of physical cores */
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
@@ -640,10 +523,42 @@ failed:
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#elif defined(__FreeBSD__)
|
||||
|
||||
/* Use apple-provided syscall
|
||||
* see: man 3 sysctl */
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
/* Use physical core sysctl when available
|
||||
* see: man 4 smp, man 3 sysctl */
|
||||
int UTIL_countPhysicalCores(void)
|
||||
{
|
||||
static int numPhysicalCores = 0; /* freebsd sysctl is native int sized */
|
||||
if (numPhysicalCores != 0) return numPhysicalCores;
|
||||
|
||||
#if __FreeBSD_version >= 1300008
|
||||
{ size_t size = sizeof(numPhysicalCores);
|
||||
int ret = sysctlbyname("kern.smp.cores", &numPhysicalCores, &size, NULL, 0);
|
||||
if (ret == 0) return numPhysicalCores;
|
||||
if (errno != ENOENT) {
|
||||
perror("zstd: can't get number of physical cpus");
|
||||
exit(1);
|
||||
}
|
||||
/* sysctl not present, fall through to older sysconf method */
|
||||
}
|
||||
#endif
|
||||
|
||||
numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (numPhysicalCores == -1) {
|
||||
/* value not queryable, fall back on 1 */
|
||||
numPhysicalCores = 1;
|
||||
}
|
||||
return numPhysicalCores;
|
||||
}
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
|
||||
/* Use POSIX sysconf
|
||||
* see: man 3 sysconf */
|
||||
int UTIL_countPhysicalCores(void)
|
||||
{
|
||||
static int numPhysicalCores = 0;
|
||||
|
||||
+1
-46
@@ -112,52 +112,6 @@ extern int g_utilDisplayLevel;
|
||||
#define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } }
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Time functions
|
||||
******************************************/
|
||||
#if defined(_WIN32) /* Windows */
|
||||
|
||||
#define UTIL_TIME_INITIALIZER { { 0, 0 } }
|
||||
typedef LARGE_INTEGER UTIL_time_t;
|
||||
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
#include <mach/mach_time.h>
|
||||
#define UTIL_TIME_INITIALIZER 0
|
||||
typedef U64 UTIL_time_t;
|
||||
|
||||
#elif (PLATFORM_POSIX_VERSION >= 200112L) \
|
||||
&& (defined(__UCLIBC__) \
|
||||
|| (defined(__GLIBC__) \
|
||||
&& ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) \
|
||||
|| (__GLIBC__ > 2))))
|
||||
|
||||
#define UTIL_TIME_INITIALIZER { 0, 0 }
|
||||
typedef struct timespec UTIL_freq_t;
|
||||
typedef struct timespec UTIL_time_t;
|
||||
|
||||
UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end);
|
||||
|
||||
#else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */
|
||||
|
||||
typedef clock_t UTIL_time_t;
|
||||
#define UTIL_TIME_INITIALIZER 0
|
||||
|
||||
#endif
|
||||
|
||||
UTIL_time_t UTIL_getTime(void);
|
||||
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd);
|
||||
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd);
|
||||
|
||||
#define SEC_TO_MICRO 1000000
|
||||
|
||||
/* returns time span in microseconds */
|
||||
U64 UTIL_clockSpanMicro(UTIL_time_t clockStart);
|
||||
|
||||
/* returns time span in microseconds */
|
||||
U64 UTIL_clockSpanNano(UTIL_time_t clockStart);
|
||||
void UTIL_waitForNextTick(void);
|
||||
|
||||
/*-****************************************
|
||||
* File functions
|
||||
******************************************/
|
||||
@@ -174,6 +128,7 @@ int UTIL_isRegularFile(const char* infilename);
|
||||
int UTIL_setFileStat(const char* filename, stat_t* statbuf);
|
||||
U32 UTIL_isDirectory(const char* infilename);
|
||||
int UTIL_getFileStat(const char* infilename, stat_t* statbuf);
|
||||
int UTIL_isSameFile(const char* file1, const char* file2);
|
||||
|
||||
U32 UTIL_isLink(const char* infilename);
|
||||
#define UTIL_FILESIZE_UNKNOWN ((U64)(-1))
|
||||
|
||||
+6
-2
@@ -1,5 +1,5 @@
|
||||
.
|
||||
.TH "ZSTD" "1" "December 2018" "zstd 1.3.8" "User Commands"
|
||||
.TH "ZSTD" "1" "July 2019" "zstd 1.4.1" "User Commands"
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files
|
||||
@@ -164,7 +164,7 @@ keep source file(s) after successful compression or decompression\. This is the
|
||||
.
|
||||
.TP
|
||||
\fB\-r\fR
|
||||
operate recursively on dictionaries
|
||||
operate recursively on directories
|
||||
.
|
||||
.TP
|
||||
\fB\-\-format=FORMAT\fR
|
||||
@@ -187,6 +187,10 @@ verbose mode
|
||||
suppress warnings, interactivity, and notifications\. specify twice to suppress errors too\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-no\-progress\fR
|
||||
do not display the progress bar, but keep all other messages\.
|
||||
.
|
||||
.TP
|
||||
\fB\-C\fR, \fB\-\-[no\-]check\fR
|
||||
add integrity check computed from uncompressed data (default: enabled)
|
||||
.
|
||||
|
||||
+1
-1
@@ -178,7 +178,7 @@ the last one takes effect.
|
||||
keep source file(s) after successful compression or decompression.
|
||||
This is the default behavior.
|
||||
* `-r`:
|
||||
operate recursively on dictionaries
|
||||
operate recursively on directories
|
||||
* `--format=FORMAT`:
|
||||
compress and decompress in other formats. If compiled with
|
||||
support, zstd can compress to or decompress from other compression algorithm
|
||||
|
||||
+106
-57
@@ -141,6 +141,7 @@ static int usage_advanced(const char* programName)
|
||||
DISPLAY( "--long[=#]: enable long distance matching with given window log (default: %u)\n", g_defaultMaxWindowLog);
|
||||
DISPLAY( "--fast[=#]: switch to ultra fast compression level (default: %u)\n", 1);
|
||||
DISPLAY( "--adapt : dynamically adapt compression level to I/O conditions \n");
|
||||
DISPLAY( "--target-compressed-block-size=# : make compressed block near targeted size \n");
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
DISPLAY( " -T# : spawns # compression threads (default: 1, 0==# cores) \n");
|
||||
DISPLAY( " -B# : select size of each job (default: 0==automatic) \n");
|
||||
@@ -148,6 +149,7 @@ static int usage_advanced(const char* programName)
|
||||
#endif
|
||||
DISPLAY( "--no-dictID : don't write dictID into header (dictionary compression)\n");
|
||||
DISPLAY( "--[no-]check : integrity check (default: enabled) \n");
|
||||
DISPLAY( "--[no-]compress-literals : force (un)compressed literals \n");
|
||||
#endif
|
||||
#ifdef UTIL_HAS_CREATEFILELIST
|
||||
DISPLAY( " -r : operate recursively on directories \n");
|
||||
@@ -178,8 +180,8 @@ static int usage_advanced(const char* programName)
|
||||
DISPLAY( "\n");
|
||||
DISPLAY( "Dictionary builder : \n");
|
||||
DISPLAY( "--train ## : create a dictionary from a training set of files \n");
|
||||
DISPLAY( "--train-cover[=k=#,d=#,steps=#,split=#] : use the cover algorithm with optional args\n");
|
||||
DISPLAY( "--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#] : use the fast cover algorithm with optional args\n");
|
||||
DISPLAY( "--train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args\n");
|
||||
DISPLAY( "--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args\n");
|
||||
DISPLAY( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u)\n", g_defaultSelectivityLevel);
|
||||
DISPLAY( " -o file : `file` is dictionary name (default: %s) \n", g_defaultDictName);
|
||||
DISPLAY( "--maxdict=# : limit dictionary to specified size (default: %u) \n", g_defaultMaxDictSize);
|
||||
@@ -241,18 +243,20 @@ static void errorOut(const char* msg)
|
||||
* @return 1 if an overflow error occurs */
|
||||
static int readU32FromCharChecked(const char** stringPtr, unsigned* value)
|
||||
{
|
||||
static unsigned const max = (((unsigned)(-1)) / 10) - 1;
|
||||
unsigned result = 0;
|
||||
while ((**stringPtr >='0') && (**stringPtr <='9')) {
|
||||
if (result > max) return 1; // overflow error
|
||||
result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
|
||||
unsigned const max = (((unsigned)(-1)) / 10) - 1;
|
||||
if (result > max) return 1; /* overflow error */
|
||||
result *= 10;
|
||||
result += (unsigned)(**stringPtr - '0');
|
||||
(*stringPtr)++ ;
|
||||
}
|
||||
if ((**stringPtr=='K') || (**stringPtr=='M')) {
|
||||
unsigned const maxK = ((unsigned)(-1)) >> 10;
|
||||
if (result > maxK) return 1; // overflow error
|
||||
if (result > maxK) return 1; /* overflow error */
|
||||
result <<= 10;
|
||||
if (**stringPtr=='M') {
|
||||
if (result > maxK) return 1; // overflow error
|
||||
if (result > maxK) return 1; /* overflow error */
|
||||
result <<= 10;
|
||||
}
|
||||
(*stringPtr)++; /* skip `K` or `M` */
|
||||
@@ -296,6 +300,7 @@ static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
|
||||
* @return 1 means that cover parameters were correct
|
||||
* @return 0 in case of malformed parameters
|
||||
*/
|
||||
static const unsigned kDefaultRegression = 1;
|
||||
static unsigned parseCoverParameters(const char* stringPtr, ZDICT_cover_params_t* params)
|
||||
{
|
||||
memset(params, 0, sizeof(*params));
|
||||
@@ -308,10 +313,23 @@ static unsigned parseCoverParameters(const char* stringPtr, ZDICT_cover_params_t
|
||||
params->splitPoint = (double)splitPercentage / 100.0;
|
||||
if (stringPtr[0]==',') { stringPtr++; continue; } else break;
|
||||
}
|
||||
if (longCommandWArg(&stringPtr, "shrink")) {
|
||||
params->shrinkDictMaxRegression = kDefaultRegression;
|
||||
params->shrinkDict = 1;
|
||||
if (stringPtr[0]=='=') {
|
||||
stringPtr++;
|
||||
params->shrinkDictMaxRegression = readU32FromChar(&stringPtr);
|
||||
}
|
||||
if (stringPtr[0]==',') {
|
||||
stringPtr++;
|
||||
continue;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (stringPtr[0] != 0) return 0;
|
||||
DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nsteps=%u\nsplit=%u\n", params->k, params->d, params->steps, (unsigned)(params->splitPoint * 100));
|
||||
DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nsteps=%u\nsplit=%u\nshrink%u\n", params->k, params->d, params->steps, (unsigned)(params->splitPoint * 100), params->shrinkDictMaxRegression);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -335,16 +353,29 @@ static unsigned parseFastCoverParameters(const char* stringPtr, ZDICT_fastCover_
|
||||
params->splitPoint = (double)splitPercentage / 100.0;
|
||||
if (stringPtr[0]==',') { stringPtr++; continue; } else break;
|
||||
}
|
||||
if (longCommandWArg(&stringPtr, "shrink")) {
|
||||
params->shrinkDictMaxRegression = kDefaultRegression;
|
||||
params->shrinkDict = 1;
|
||||
if (stringPtr[0]=='=') {
|
||||
stringPtr++;
|
||||
params->shrinkDictMaxRegression = readU32FromChar(&stringPtr);
|
||||
}
|
||||
if (stringPtr[0]==',') {
|
||||
stringPtr++;
|
||||
continue;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (stringPtr[0] != 0) return 0;
|
||||
DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nf=%u\nsteps=%u\nsplit=%u\naccel=%u\n", params->k, params->d, params->f, params->steps, (unsigned)(params->splitPoint * 100), params->accel);
|
||||
DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nf=%u\nsteps=%u\nsplit=%u\naccel=%u\nshrink=%u\n", params->k, params->d, params->f, params->steps, (unsigned)(params->splitPoint * 100), params->accel, params->shrinkDictMaxRegression);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* parseLegacyParameters() :
|
||||
* reads legacy dictioanry builter parameters from *stringPtr (e.g. "--train-legacy=selectivity=8") into *selectivity
|
||||
* reads legacy dictionary builder parameters from *stringPtr (e.g. "--train-legacy=selectivity=8") into *selectivity
|
||||
* @return 1 means that legacy dictionary builder parameters were correct
|
||||
* @return 0 in case of malformed parameters
|
||||
*/
|
||||
@@ -364,6 +395,8 @@ static ZDICT_cover_params_t defaultCoverParams(void)
|
||||
params.d = 8;
|
||||
params.steps = 4;
|
||||
params.splitPoint = 1.0;
|
||||
params.shrinkDict = 0;
|
||||
params.shrinkDictMaxRegression = kDefaultRegression;
|
||||
return params;
|
||||
}
|
||||
|
||||
@@ -376,6 +409,8 @@ static ZDICT_fastCover_params_t defaultFastCoverParams(void)
|
||||
params.steps = 4;
|
||||
params.splitPoint = 0.75; /* different from default splitPoint of cover */
|
||||
params.accel = DEFAULT_ACCEL;
|
||||
params.shrinkDict = 0;
|
||||
params.shrinkDictMaxRegression = kDefaultRegression;
|
||||
return params;
|
||||
}
|
||||
#endif
|
||||
@@ -483,7 +518,7 @@ static int init_cLevel(void) {
|
||||
|
||||
if ((*ptr>='0') && (*ptr<='9')) {
|
||||
unsigned absLevel;
|
||||
if (readU32FromCharChecked(&ptr, &absLevel)) {
|
||||
if (readU32FromCharChecked(&ptr, &absLevel)) {
|
||||
DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: numeric value too large\n", ENV_CLEVEL, env);
|
||||
return ZSTDCLI_CLEVEL_DEFAULT;
|
||||
} else if (*ptr == 0) {
|
||||
@@ -536,6 +571,8 @@ int main(int argCount, const char* argv[])
|
||||
double compressibility = 0.5;
|
||||
unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */
|
||||
size_t blockSize = 0;
|
||||
|
||||
FIO_prefs_t* const prefs = FIO_createPreferences();
|
||||
zstd_operation_mode operation = zom_compress;
|
||||
ZSTD_compressionParameters compressionParams;
|
||||
int cLevel;
|
||||
@@ -550,6 +587,7 @@ int main(int argCount, const char* argv[])
|
||||
const char* suffix = ZSTD_EXTENSION;
|
||||
unsigned maxDictSize = g_defaultMaxDictSize;
|
||||
unsigned dictID = 0;
|
||||
size_t targetCBlockSize = 0;
|
||||
int dictCLevel = g_defaultDictCLevel;
|
||||
unsigned dictSelect = g_defaultSelectivityLevel;
|
||||
#ifdef UTIL_HAS_CREATEFILELIST
|
||||
@@ -565,6 +603,7 @@ int main(int argCount, const char* argv[])
|
||||
#ifndef ZSTD_NOBENCH
|
||||
BMK_advancedParams_t benchParams = BMK_initAdvancedParams();
|
||||
#endif
|
||||
ZSTD_literalCompressionMode_e literalCompressionMode = ZSTD_lcm_auto;
|
||||
|
||||
|
||||
/* init */
|
||||
@@ -582,17 +621,17 @@ int main(int argCount, const char* argv[])
|
||||
/* preset behaviors */
|
||||
if (exeNameMatch(programName, ZSTD_ZSTDMT)) nbWorkers=0, singleThread=0;
|
||||
if (exeNameMatch(programName, ZSTD_UNZSTD)) operation=zom_decompress;
|
||||
if (exeNameMatch(programName, ZSTD_CAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; } /* supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_ZCAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; } /* behave like zcat, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_GZ)) { suffix = GZ_EXTENSION; FIO_setCompressionType(FIO_gzipCompression); FIO_setRemoveSrcFile(1); } /* behave like gzip */
|
||||
if (exeNameMatch(programName, ZSTD_GUNZIP)) { operation=zom_decompress; FIO_setRemoveSrcFile(1); } /* behave like gunzip, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_GZCAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; } /* behave like gzcat, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; FIO_setCompressionType(FIO_lzmaCompression); FIO_setRemoveSrcFile(1); } /* behave like lzma */
|
||||
if (exeNameMatch(programName, ZSTD_UNLZMA)) { operation=zom_decompress; FIO_setCompressionType(FIO_lzmaCompression); FIO_setRemoveSrcFile(1); } /* behave like unlzma, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; FIO_setCompressionType(FIO_xzCompression); FIO_setRemoveSrcFile(1); } /* behave like xz */
|
||||
if (exeNameMatch(programName, ZSTD_UNXZ)) { operation=zom_decompress; FIO_setCompressionType(FIO_xzCompression); FIO_setRemoveSrcFile(1); } /* behave like unxz, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_LZ4)) { suffix = LZ4_EXTENSION; FIO_setCompressionType(FIO_lz4Compression); } /* behave like lz4 */
|
||||
if (exeNameMatch(programName, ZSTD_UNLZ4)) { operation=zom_decompress; FIO_setCompressionType(FIO_lz4Compression); } /* behave like unlz4, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_CAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; outFileName=stdoutmark; g_displayLevel=1; } /* supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_ZCAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; outFileName=stdoutmark; g_displayLevel=1; } /* behave like zcat, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_GZ)) { suffix = GZ_EXTENSION; FIO_setCompressionType(prefs, FIO_gzipCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like gzip */
|
||||
if (exeNameMatch(programName, ZSTD_GUNZIP)) { operation=zom_decompress; FIO_setRemoveSrcFile(prefs, 1); } /* behave like gunzip, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_GZCAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; outFileName=stdoutmark; g_displayLevel=1; } /* behave like gzcat, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; FIO_setCompressionType(prefs, FIO_lzmaCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like lzma */
|
||||
if (exeNameMatch(programName, ZSTD_UNLZMA)) { operation=zom_decompress; FIO_setCompressionType(prefs, FIO_lzmaCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like unlzma, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; FIO_setCompressionType(prefs, FIO_xzCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like xz */
|
||||
if (exeNameMatch(programName, ZSTD_UNXZ)) { operation=zom_decompress; FIO_setCompressionType(prefs, FIO_xzCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like unxz, also supports multiple formats */
|
||||
if (exeNameMatch(programName, ZSTD_LZ4)) { suffix = LZ4_EXTENSION; FIO_setCompressionType(prefs, FIO_lz4Compression); } /* behave like lz4 */
|
||||
if (exeNameMatch(programName, ZSTD_UNLZ4)) { operation=zom_decompress; FIO_setCompressionType(prefs, FIO_lz4Compression); } /* behave like unlz4, also supports multiple formats */
|
||||
memset(&compressionParams, 0, sizeof(compressionParams));
|
||||
|
||||
/* init crash handler */
|
||||
@@ -623,40 +662,42 @@ int main(int argCount, const char* argv[])
|
||||
if (!strcmp(argument, "--compress")) { operation=zom_compress; continue; }
|
||||
if (!strcmp(argument, "--decompress")) { operation=zom_decompress; continue; }
|
||||
if (!strcmp(argument, "--uncompress")) { operation=zom_decompress; continue; }
|
||||
if (!strcmp(argument, "--force")) { FIO_overwriteMode(); forceStdout=1; followLinks=1; continue; }
|
||||
if (!strcmp(argument, "--force")) { FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; continue; }
|
||||
if (!strcmp(argument, "--version")) { g_displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); }
|
||||
if (!strcmp(argument, "--help")) { g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); }
|
||||
if (!strcmp(argument, "--verbose")) { g_displayLevel++; continue; }
|
||||
if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; }
|
||||
if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; g_displayLevel-=(g_displayLevel==2); continue; }
|
||||
if (!strcmp(argument, "--ultra")) { ultra=1; continue; }
|
||||
if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(2); continue; }
|
||||
if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(0); continue; }
|
||||
if (!strcmp(argument, "--sparse")) { FIO_setSparseWrite(2); continue; }
|
||||
if (!strcmp(argument, "--no-sparse")) { FIO_setSparseWrite(0); continue; }
|
||||
if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(prefs, 2); continue; }
|
||||
if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(prefs, 0); continue; }
|
||||
if (!strcmp(argument, "--sparse")) { FIO_setSparseWrite(prefs, 2); continue; }
|
||||
if (!strcmp(argument, "--no-sparse")) { FIO_setSparseWrite(prefs, 0); continue; }
|
||||
if (!strcmp(argument, "--test")) { operation=zom_test; continue; }
|
||||
if (!strcmp(argument, "--train")) { operation=zom_train; if (outFileName==NULL) outFileName=g_defaultDictName; continue; }
|
||||
if (!strcmp(argument, "--maxdict")) { nextArgumentIsMaxDict=1; lastCommand=1; continue; } /* kept available for compatibility with old syntax ; will be removed one day */
|
||||
if (!strcmp(argument, "--dictID")) { nextArgumentIsDictID=1; lastCommand=1; continue; } /* kept available for compatibility with old syntax ; will be removed one day */
|
||||
if (!strcmp(argument, "--no-dictID")) { FIO_setDictIDFlag(0); continue; }
|
||||
if (!strcmp(argument, "--keep")) { FIO_setRemoveSrcFile(0); continue; }
|
||||
if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(1); continue; }
|
||||
if (!strcmp(argument, "--no-dictID")) { FIO_setDictIDFlag(prefs, 0); continue; }
|
||||
if (!strcmp(argument, "--keep")) { FIO_setRemoveSrcFile(prefs, 0); continue; }
|
||||
if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(prefs, 1); continue; }
|
||||
if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; }
|
||||
if (!strcmp(argument, "--adapt")) { adapt = 1; continue; }
|
||||
if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) CLEAN_RETURN(badusage(programName)); continue; }
|
||||
if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; }
|
||||
if (!strcmp(argument, "--format=zstd")) { suffix = ZSTD_EXTENSION; FIO_setCompressionType(FIO_zstdCompression); continue; }
|
||||
if (!strcmp(argument, "--format=zstd")) { suffix = ZSTD_EXTENSION; FIO_setCompressionType(prefs, FIO_zstdCompression); continue; }
|
||||
#ifdef ZSTD_GZCOMPRESS
|
||||
if (!strcmp(argument, "--format=gzip")) { suffix = GZ_EXTENSION; FIO_setCompressionType(FIO_gzipCompression); continue; }
|
||||
if (!strcmp(argument, "--format=gzip")) { suffix = GZ_EXTENSION; FIO_setCompressionType(prefs, FIO_gzipCompression); continue; }
|
||||
#endif
|
||||
#ifdef ZSTD_LZMACOMPRESS
|
||||
if (!strcmp(argument, "--format=lzma")) { suffix = LZMA_EXTENSION; FIO_setCompressionType(FIO_lzmaCompression); continue; }
|
||||
if (!strcmp(argument, "--format=xz")) { suffix = XZ_EXTENSION; FIO_setCompressionType(FIO_xzCompression); continue; }
|
||||
if (!strcmp(argument, "--format=lzma")) { suffix = LZMA_EXTENSION; FIO_setCompressionType(prefs, FIO_lzmaCompression); continue; }
|
||||
if (!strcmp(argument, "--format=xz")) { suffix = XZ_EXTENSION; FIO_setCompressionType(prefs, FIO_xzCompression); continue; }
|
||||
#endif
|
||||
#ifdef ZSTD_LZ4COMPRESS
|
||||
if (!strcmp(argument, "--format=lz4")) { suffix = LZ4_EXTENSION; FIO_setCompressionType(FIO_lz4Compression); continue; }
|
||||
if (!strcmp(argument, "--format=lz4")) { suffix = LZ4_EXTENSION; FIO_setCompressionType(prefs, FIO_lz4Compression); continue; }
|
||||
#endif
|
||||
if (!strcmp(argument, "--rsyncable")) { rsyncable = 1; continue; }
|
||||
if (!strcmp(argument, "--compress-literals")) { literalCompressionMode = ZSTD_lcm_huffman; continue; }
|
||||
if (!strcmp(argument, "--no-compress-literals")) { literalCompressionMode = ZSTD_lcm_uncompressed; continue; }
|
||||
if (!strcmp(argument, "--no-progress")) { FIO_setNoProgress(1); continue; }
|
||||
|
||||
/* long commands with arguments */
|
||||
@@ -703,6 +744,7 @@ int main(int argCount, const char* argv[])
|
||||
if (longCommandWArg(&argument, "--maxdict=")) { maxDictSize = readU32FromChar(&argument); continue; }
|
||||
if (longCommandWArg(&argument, "--dictID=")) { dictID = readU32FromChar(&argument); continue; }
|
||||
if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) CLEAN_RETURN(badusage(programName)); continue; }
|
||||
if (longCommandWArg(&argument, "--target-compressed-block-size=")) { targetCBlockSize = readU32FromChar(&argument); continue; }
|
||||
if (longCommandWArg(&argument, "--long")) {
|
||||
unsigned ldmWindowLog = 0;
|
||||
ldmFlag = 1;
|
||||
@@ -784,7 +826,7 @@ int main(int argCount, const char* argv[])
|
||||
case 'D': nextEntryIsDictionary = 1; lastCommand = 1; argument++; break;
|
||||
|
||||
/* Overwrite */
|
||||
case 'f': FIO_overwriteMode(); forceStdout=1; followLinks=1; argument++; break;
|
||||
case 'f': FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; argument++; break;
|
||||
|
||||
/* Verbose mode */
|
||||
case 'v': g_displayLevel++; argument++; break;
|
||||
@@ -793,10 +835,10 @@ int main(int argCount, const char* argv[])
|
||||
case 'q': g_displayLevel--; argument++; break;
|
||||
|
||||
/* keep source file (default) */
|
||||
case 'k': FIO_setRemoveSrcFile(0); argument++; break;
|
||||
case 'k': FIO_setRemoveSrcFile(prefs, 0); argument++; break;
|
||||
|
||||
/* Checksum */
|
||||
case 'C': FIO_setChecksumFlag(2); argument++; break;
|
||||
case 'C': FIO_setChecksumFlag(prefs, 2); argument++; break;
|
||||
|
||||
/* test compressed file */
|
||||
case 't': operation=zom_test; argument++; break;
|
||||
@@ -949,6 +991,8 @@ int main(int argCount, const char* argv[])
|
||||
filenameTable[fileNamesNb++] = filenameTable[u];
|
||||
}
|
||||
}
|
||||
if (fileNamesNb == 0 && filenameIdx > 0)
|
||||
CLEAN_RETURN(1);
|
||||
filenameIdx = fileNamesNb;
|
||||
}
|
||||
if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
|
||||
@@ -991,6 +1035,7 @@ int main(int argCount, const char* argv[])
|
||||
if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) {
|
||||
benchParams.ldmHashRateLog = g_ldmHashRateLog;
|
||||
}
|
||||
benchParams.literalCompressionMode = literalCompressionMode;
|
||||
|
||||
if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
|
||||
if (cLevelLast > ZSTD_maxCLevel()) cLevelLast = ZSTD_maxCLevel();
|
||||
@@ -1057,7 +1102,7 @@ int main(int argCount, const char* argv[])
|
||||
}
|
||||
|
||||
#ifndef ZSTD_NODECOMPRESS
|
||||
if (operation==zom_test) { outFileName=nulmark; FIO_setRemoveSrcFile(0); } /* test mode */
|
||||
if (operation==zom_test) { outFileName=nulmark; FIO_setRemoveSrcFile(prefs, 0); } /* test mode */
|
||||
#endif
|
||||
|
||||
/* No input filename ==> use stdin and stdout */
|
||||
@@ -1092,27 +1137,29 @@ int main(int argCount, const char* argv[])
|
||||
FIO_setNotificationLevel(g_displayLevel);
|
||||
if (operation==zom_compress) {
|
||||
#ifndef ZSTD_NOCOMPRESS
|
||||
FIO_setNbWorkers(nbWorkers);
|
||||
FIO_setBlockSize((U32)blockSize);
|
||||
if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(g_overlapLog);
|
||||
FIO_setLdmFlag(ldmFlag);
|
||||
FIO_setLdmHashLog(g_ldmHashLog);
|
||||
FIO_setLdmMinMatch(g_ldmMinMatch);
|
||||
if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) FIO_setLdmBucketSizeLog(g_ldmBucketSizeLog);
|
||||
if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) FIO_setLdmHashRateLog(g_ldmHashRateLog);
|
||||
FIO_setAdaptiveMode(adapt);
|
||||
FIO_setAdaptMin(adaptMin);
|
||||
FIO_setAdaptMax(adaptMax);
|
||||
FIO_setRsyncable(rsyncable);
|
||||
FIO_setNbWorkers(prefs, nbWorkers);
|
||||
FIO_setBlockSize(prefs, (U32)blockSize);
|
||||
if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(prefs, g_overlapLog);
|
||||
FIO_setLdmFlag(prefs, ldmFlag);
|
||||
FIO_setLdmHashLog(prefs, g_ldmHashLog);
|
||||
FIO_setLdmMinMatch(prefs, g_ldmMinMatch);
|
||||
if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) FIO_setLdmBucketSizeLog(prefs, g_ldmBucketSizeLog);
|
||||
if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) FIO_setLdmHashRateLog(prefs, g_ldmHashRateLog);
|
||||
FIO_setAdaptiveMode(prefs, adapt);
|
||||
FIO_setAdaptMin(prefs, adaptMin);
|
||||
FIO_setAdaptMax(prefs, adaptMax);
|
||||
FIO_setRsyncable(prefs, rsyncable);
|
||||
FIO_setTargetCBlockSize(prefs, targetCBlockSize);
|
||||
FIO_setLiteralCompressionMode(prefs, literalCompressionMode);
|
||||
if (adaptMin > cLevel) cLevel = adaptMin;
|
||||
if (adaptMax < cLevel) cLevel = adaptMax;
|
||||
|
||||
if ((filenameIdx==1) && outFileName)
|
||||
operationResult = FIO_compressFilename(outFileName, filenameTable[0], dictFileName, cLevel, compressionParams);
|
||||
operationResult = FIO_compressFilename(prefs, outFileName, filenameTable[0], dictFileName, cLevel, compressionParams);
|
||||
else
|
||||
operationResult = FIO_compressMultipleFilenames(filenameTable, filenameIdx, outFileName, suffix, dictFileName, cLevel, compressionParams);
|
||||
operationResult = FIO_compressMultipleFilenames(prefs, filenameTable, filenameIdx, outFileName, suffix, dictFileName, cLevel, compressionParams);
|
||||
#else
|
||||
(void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; /* not used when ZSTD_NOCOMPRESS set */
|
||||
(void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; /* not used when ZSTD_NOCOMPRESS set */
|
||||
DISPLAY("Compression not supported \n");
|
||||
#endif
|
||||
} else { /* decompression or test */
|
||||
@@ -1124,17 +1171,19 @@ int main(int argCount, const char* argv[])
|
||||
memLimit = (U32)1 << (compressionParams.windowLog & 31);
|
||||
}
|
||||
}
|
||||
FIO_setMemLimit(memLimit);
|
||||
FIO_setMemLimit(prefs, memLimit);
|
||||
if (filenameIdx==1 && outFileName)
|
||||
operationResult = FIO_decompressFilename(outFileName, filenameTable[0], dictFileName);
|
||||
operationResult = FIO_decompressFilename(prefs, outFileName, filenameTable[0], dictFileName);
|
||||
else
|
||||
operationResult = FIO_decompressMultipleFilenames(filenameTable, filenameIdx, outFileName, dictFileName);
|
||||
operationResult = FIO_decompressMultipleFilenames(prefs, filenameTable, filenameIdx, outFileName, dictFileName);
|
||||
#else
|
||||
DISPLAY("Decompression not supported \n");
|
||||
#endif
|
||||
}
|
||||
|
||||
_end:
|
||||
FIO_freePreferences(prefs);
|
||||
|
||||
if (main_pause) waitEnter();
|
||||
#ifdef UTIL_HAS_CREATEFILELIST
|
||||
if (extendedFileList)
|
||||
|
||||
+17
-14
@@ -22,8 +22,8 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
grep=grep
|
||||
zcat=zstdcat
|
||||
grep=${GREP:-grep}
|
||||
zcat=${ZCAT:-zstdcat}
|
||||
|
||||
endofopts=0
|
||||
pattern_found=0
|
||||
@@ -31,12 +31,13 @@ grep_args=""
|
||||
hyphen=0
|
||||
silent=0
|
||||
|
||||
prg=$(basename "$0")
|
||||
prog=${0##*/}
|
||||
|
||||
# handle being called 'zegrep' or 'zfgrep'
|
||||
case "${prg}" in
|
||||
*zegrep) grep_args="-E";;
|
||||
*zfgrep) grep_args="-F";;
|
||||
case $prog in
|
||||
*egrep*) prog=zegrep; grep_args='-E';;
|
||||
*fgrep*) prog=zfgrep; grep_args='-F';;
|
||||
*) prog=zstdgrep;;
|
||||
esac
|
||||
|
||||
# skip all options and pass them on to grep taking care of options
|
||||
@@ -47,7 +48,7 @@ while [ "$#" -gt 0 ] && [ "${endofopts}" -eq 0 ]; do
|
||||
# from GNU grep-2.5.1 -- keep in sync!
|
||||
-[ABCDXdefm])
|
||||
if [ "$#" -lt 2 ]; then
|
||||
printf '%s: missing argument for %s flag\n' "${prg}" "$1" >&2
|
||||
printf '%s: missing argument for %s flag\n' "${prog}" "$1" >&2
|
||||
exit 1
|
||||
fi
|
||||
case "$1" in
|
||||
@@ -57,6 +58,9 @@ while [ "$#" -gt 0 ] && [ "${endofopts}" -eq 0 ]; do
|
||||
shift 2
|
||||
break
|
||||
;;
|
||||
-f)
|
||||
pattern_found=2
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
@@ -94,7 +98,7 @@ if [ "${pattern_found}" -lt 1 ]; then
|
||||
elif [ "${hyphen}" -gt 0 ]; then
|
||||
pattern="-"
|
||||
else
|
||||
printf '%s: missing pattern\n' "${prg}" >&2
|
||||
printf '%s: missing pattern\n' "${prog}" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
@@ -113,16 +117,15 @@ else
|
||||
if [ "${silent}" -lt 1 ] && [ "$#" -gt 1 ]; then
|
||||
grep_args="-H ${grep_args}"
|
||||
fi
|
||||
CUR_EXIT_CODE=0
|
||||
EXIT_CODE=1
|
||||
set -f
|
||||
while [ "$#" -gt 0 ]; do
|
||||
# shellcheck disable=SC2086
|
||||
"${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" -
|
||||
CUR_EXIT_CODE=$?
|
||||
if [ "${CUR_EXIT_CODE}" -eq 0 ] && [ "${EXIT_CODE}" -ne 1 ]; then
|
||||
EXIT_CODE=0
|
||||
if [ $pattern_found -eq 2 ]; then
|
||||
"${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- -
|
||||
else
|
||||
"${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" -
|
||||
fi
|
||||
[ "$?" -ne 0 ] && EXIT_CODE=1
|
||||
shift
|
||||
done
|
||||
set +f
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
.
|
||||
.TH "ZSTDGREP" "1" "December 2018" "zstd 1.3.8" "User Commands"
|
||||
.TH "ZSTDGREP" "1" "July 2019" "zstd 1.4.1" "User Commands"
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBzstdgrep\fR \- print lines matching a pattern in zstandard\-compressed files
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
.
|
||||
.TH "ZSTDLESS" "1" "December 2018" "zstd 1.3.8" "User Commands"
|
||||
.TH "ZSTDLESS" "1" "July 2019" "zstd 1.4.1" "User Commands"
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBzstdless\fR \- view zstandard\-compressed files
|
||||
|
||||
@@ -55,6 +55,7 @@ _*
|
||||
tmp*
|
||||
*.zst
|
||||
*.gz
|
||||
!gzip/hufts-segv.gz
|
||||
result
|
||||
out
|
||||
*.zstd
|
||||
|
||||
+31
-18
@@ -33,7 +33,7 @@ endif
|
||||
CFLAGS ?= -O3
|
||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||
-Wstrict-prototypes -Wundef -Wformat-security \
|
||||
-Wstrict-prototypes -Wundef \
|
||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||
-Wredundant-decls -Wmissing-prototypes
|
||||
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||
@@ -82,7 +82,7 @@ default: fullbench
|
||||
@echo $(ZSTDMT_OBJECTS)
|
||||
|
||||
all: fullbench fuzzer zstreamtest paramgrill datagen decodecorpus roundTripCrash \
|
||||
fullbench-lib
|
||||
fullbench-lib poolTests
|
||||
|
||||
all32: fullbench32 fuzzer32 zstreamtest32
|
||||
|
||||
@@ -132,18 +132,18 @@ fullbench fullbench32 : CPPFLAGS += $(MULTITHREAD_CPP)
|
||||
fullbench fullbench32 : LDFLAGS += $(MULTITHREAD_LD)
|
||||
fullbench fullbench32 : DEBUGFLAGS = -DNDEBUG # turn off assert() for speed measurements
|
||||
fullbench fullbench32 : $(ZSTD_FILES)
|
||||
fullbench fullbench32 : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c fullbench.c
|
||||
fullbench fullbench32 : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
fullbench-lib : CPPFLAGS += -DXXH_NAMESPACE=ZSTD_
|
||||
fullbench-lib : zstd-staticLib
|
||||
fullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c fullbench.c
|
||||
fullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c
|
||||
$(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) $(ZSTDDIR)/libzstd.a
|
||||
|
||||
# note : broken : requires unavailable symbols
|
||||
fullbench-dll : zstd-dll
|
||||
fullbench-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd
|
||||
fullbench-dll: $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c fullbench.c
|
||||
fullbench-dll: $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c $(PRGDIR)/timefn.c fullbench.c
|
||||
# $(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) -DZSTD_DLL_IMPORT=1 $(ZSTDDIR)/dll/libzstd.dll
|
||||
$(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT)
|
||||
|
||||
@@ -152,32 +152,32 @@ fuzzer : LDFLAGS += $(MULTITHREAD_LD)
|
||||
fuzzer32: CFLAGS += -m32
|
||||
fuzzer : $(ZSTDMT_OBJECTS)
|
||||
fuzzer32: $(ZSTD_FILES)
|
||||
fuzzer fuzzer32 : $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/datagen.c fuzzer.c
|
||||
fuzzer fuzzer32 : $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
fuzzer-dll : zstd-dll
|
||||
fuzzer-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd
|
||||
fuzzer-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/datagen.c fuzzer.c
|
||||
fuzzer-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)
|
||||
|
||||
zbufftest : CPPFLAGS += -I$(ZSTDDIR)/deprecated
|
||||
zbufftest : CFLAGS += -Wno-deprecated-declarations # required to silence deprecation warnings
|
||||
zbufftest : $(ZSTD_OBJECTS) $(ZBUFF_FILES) $(PRGDIR)/util.c $(PRGDIR)/datagen.c zbufftest.c
|
||||
zbufftest : $(ZSTD_OBJECTS) $(ZBUFF_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c zbufftest.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
zbufftest32 : CPPFLAGS += -I$(ZSTDDIR)/deprecated
|
||||
zbufftest32 : CFLAGS += -Wno-deprecated-declarations -m32
|
||||
zbufftest32 : $(ZSTD_FILES) $(ZBUFF_FILES) $(PRGDIR)/util.c $(PRGDIR)/datagen.c zbufftest.c
|
||||
zbufftest32 : $(ZSTD_FILES) $(ZBUFF_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c zbufftest.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
zbufftest-dll : zstd-dll
|
||||
zbufftest-dll : CPPFLAGS += -I$(ZSTDDIR)/deprecated
|
||||
zbufftest-dll : CFLAGS += -Wno-deprecated-declarations # required to silence deprecation warnings
|
||||
zbufftest-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd
|
||||
zbufftest-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/datagen.c zbufftest.c
|
||||
zbufftest-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c zbufftest.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)
|
||||
|
||||
ZSTREAM_LOCAL_FILES := $(PRGDIR)/datagen.c $(PRGDIR)/util.c seqgen.c zstreamtest.c
|
||||
ZSTREAM_LOCAL_FILES := $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c seqgen.c zstreamtest.c
|
||||
ZSTREAM_PROPER_FILES := $(ZDICT_FILES) $(ZSTREAM_LOCAL_FILES)
|
||||
ZSTREAMFILES := $(ZSTD_FILES) $(ZSTREAM_PROPER_FILES)
|
||||
zstreamtest32 : CFLAGS += -m32
|
||||
@@ -203,7 +203,7 @@ zstreamtest-dll : $(ZSTREAM_LOCAL_FILES)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)
|
||||
|
||||
paramgrill : DEBUGFLAGS = # turn off assert() by default for speed measurements
|
||||
paramgrill : $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/benchfn.c $(PRGDIR)/benchzstd.c $(PRGDIR)/datagen.c paramgrill.c
|
||||
paramgrill : $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c $(PRGDIR)/benchzstd.c $(PRGDIR)/datagen.c paramgrill.c
|
||||
$(CC) $(FLAGS) $^ -lm -o $@$(EXT)
|
||||
|
||||
datagen : $(PRGDIR)/datagen.c datagencli.c
|
||||
@@ -215,6 +215,9 @@ roundTripCrash : $(ZSTD_OBJECTS) roundTripCrash.c
|
||||
longmatch : $(ZSTD_OBJECTS) longmatch.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
bigdict: $(ZSTDMT_OBJECTS) $(PRGDIR)/datagen.c bigdict.c
|
||||
$(CC) $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT)
|
||||
|
||||
invalidDictionaries : $(ZSTD_OBJECTS) invalidDictionaries.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
@@ -222,7 +225,7 @@ legacy : CPPFLAGS += -I$(ZSTDDIR)/legacy -DZSTD_LEGACY_SUPPORT=4
|
||||
legacy : $(ZSTD_FILES) $(wildcard $(ZSTDDIR)/legacy/*.c) legacy.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
decodecorpus : $(filter-out zstdc_zstd_compress.o, $(ZSTD_OBJECTS)) $(ZDICT_FILES) $(PRGDIR)/util.c decodecorpus.c
|
||||
decodecorpus : $(filter-out zstdc_zstd_compress.o, $(ZSTD_OBJECTS)) $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c decodecorpus.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT) -lm
|
||||
|
||||
symbols : symbols.c zstd-dll
|
||||
@@ -233,7 +236,7 @@ else
|
||||
$(CC) $(FLAGS) $< -o $@$(EXT) -Wl,-rpath=$(ZSTDDIR) $(ZSTDDIR)/libzstd.so # broken on Mac
|
||||
endif
|
||||
|
||||
poolTests : $(PRGDIR)/util.c poolTests.c $(ZSTDDIR)/common/pool.c $(ZSTDDIR)/common/threading.c $(ZSTDDIR)/common/zstd_common.c $(ZSTDDIR)/common/error_private.c
|
||||
poolTests : $(PRGDIR)/util.c $(PRGDIR)/timefn.c poolTests.c $(ZSTDDIR)/common/pool.c $(ZSTDDIR)/common/threading.c $(ZSTDDIR)/common/zstd_common.c $(ZSTDDIR)/common/error_private.c
|
||||
$(CC) $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT)
|
||||
|
||||
.PHONY: versionsTest
|
||||
@@ -247,7 +250,7 @@ clean:
|
||||
$(MAKE) -C $(ZSTDDIR) clean
|
||||
$(MAKE) -C $(PRGDIR) clean
|
||||
@$(RM) -fR $(TESTARTEFACT)
|
||||
@$(RM) -f core *.o tmp* result* *.gcda dictionary *.zst \
|
||||
@$(RM) -f core *.o tmp* *.tmp result* *.gcda dictionary *.zst \
|
||||
$(PRGDIR)/zstd$(EXT) $(PRGDIR)/zstd32$(EXT) \
|
||||
fullbench$(EXT) fullbench32$(EXT) \
|
||||
fullbench-lib$(EXT) fullbench-dll$(EXT) \
|
||||
@@ -256,7 +259,7 @@ clean:
|
||||
zstreamtest$(EXT) zstreamtest32$(EXT) \
|
||||
datagen$(EXT) paramgrill$(EXT) roundTripCrash$(EXT) longmatch$(EXT) \
|
||||
symbols$(EXT) invalidDictionaries$(EXT) legacy$(EXT) poolTests$(EXT) \
|
||||
decodecorpus$(EXT) checkTag$(EXT)
|
||||
decodecorpus$(EXT) checkTag$(EXT) bigdict$(EXT)
|
||||
@echo Cleaning completed
|
||||
|
||||
|
||||
@@ -353,8 +356,15 @@ test-gzstd: gzstd
|
||||
$(RM) *.gz *.zst README2.md gz_zstd zstd_gz hello.txt
|
||||
|
||||
test-zstdgrep: gzstd
|
||||
@echo a | $(PRGDIR)/zstd | $(PRGDIR)/zstdgrep a
|
||||
@echo a | $(PRGDIR)/zstd | $(PRGDIR)/zstdgrep b && return 1 || return 0
|
||||
-[ -f /tmp/zstdcat ] || ln -s $(PWD)/$(PRGDIR)/zstd /tmp/zstdcat
|
||||
echo a | $(PRGDIR)/zstd | env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep a
|
||||
echo a | $(PRGDIR)/zstd | env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep b && return 1 || return 0
|
||||
-echo 'hello world' > test.txt && $(PRGDIR)/zstd test.txt
|
||||
env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep hello test.txt.zst
|
||||
env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep weird test.txt.zst && return 1 || return 0
|
||||
-echo 'hello' > pattern.txt
|
||||
env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep -f pattern.txt test.txt.zst
|
||||
$(RM) test.txt test.txt.zst pattern.txt
|
||||
|
||||
test-fullbench: fullbench datagen
|
||||
$(QEMU_SYS) ./fullbench -i1
|
||||
@@ -390,6 +400,9 @@ test-zstream32: zstreamtest32
|
||||
test-longmatch: longmatch
|
||||
$(QEMU_SYS) ./longmatch
|
||||
|
||||
test-bigdict: bigdict
|
||||
$(QEMU_SYS) ./bigdict
|
||||
|
||||
test-invalidDictionaries: invalidDictionaries
|
||||
$(QEMU_SYS) ./invalidDictionaries
|
||||
|
||||
|
||||
+2
-2
@@ -72,7 +72,7 @@ Command line tool to generate test .zst files.
|
||||
|
||||
This tool will generate .zst files with checksums,
|
||||
as well as optionally output the corresponding correct uncompressed data for
|
||||
extra verfication.
|
||||
extra verification.
|
||||
|
||||
Example:
|
||||
```
|
||||
@@ -123,7 +123,7 @@ Full list of arguments
|
||||
Higher values will make optimizer run longer, more chances to find better solution.
|
||||
memLog : Limits the log of the size of each memotable (1 per strategy). Will use hash tables when state space is larger than max size.
|
||||
Setting memLog = 0 turns off memoization
|
||||
--display= : specifiy which parameters are included in the output
|
||||
--display= : specify which parameters are included in the output
|
||||
can use all --zstd parameter names and 'cParams' as a shorthand for all parameters used in ZSTD_compressionParameters
|
||||
(Default: display all params available)
|
||||
-P# : generated sample compressibility (when no file is provided)
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2017-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "datagen.h"
|
||||
#include "mem.h"
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
#include "zstd.h"
|
||||
|
||||
static int
|
||||
compress(ZSTD_CCtx* cctx, ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
void const* src, size_t srcSize,
|
||||
void* roundtrip, ZSTD_EndDirective end)
|
||||
{
|
||||
ZSTD_inBuffer in = {src, srcSize, 0};
|
||||
ZSTD_outBuffer out = {dst, dstCapacity, 0};
|
||||
int ended = 0;
|
||||
|
||||
while (!ended && (in.pos < in.size || out.pos > 0)) {
|
||||
size_t rc;
|
||||
out.pos = 0;
|
||||
rc = ZSTD_compressStream2(cctx, &out, &in, end);
|
||||
if (ZSTD_isError(rc))
|
||||
return 1;
|
||||
if (end == ZSTD_e_end && rc == 0)
|
||||
ended = 1;
|
||||
{
|
||||
ZSTD_inBuffer rtIn = {dst, out.pos, 0};
|
||||
ZSTD_outBuffer rtOut = {roundtrip, srcSize, 0};
|
||||
rc = 1;
|
||||
while (rtIn.pos < rtIn.size || rtOut.pos > 0) {
|
||||
rtOut.pos = 0;
|
||||
rc = ZSTD_decompressStream(dctx, &rtOut, &rtIn);
|
||||
if (ZSTD_isError(rc)) {
|
||||
fprintf(stderr, "Decompression error: %s\n", ZSTD_getErrorName(rc));
|
||||
return 1;
|
||||
}
|
||||
if (rc == 0)
|
||||
break;
|
||||
}
|
||||
if (ended && rc != 0) {
|
||||
fprintf(stderr, "Frame not finished!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
const size_t dataSize = (size_t)1 << 30;
|
||||
const size_t outSize = ZSTD_compressBound(dataSize);
|
||||
const size_t bufferSize = (size_t)1 << 31;
|
||||
char* buffer = (char*)malloc(bufferSize);
|
||||
void* out = malloc(outSize);
|
||||
void* roundtrip = malloc(dataSize);
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
if (!buffer || !out || !roundtrip || !cctx || !dctx) {
|
||||
fprintf(stderr, "Allocation failure\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 31)))
|
||||
return 1;
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1)))
|
||||
return 1;
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_overlapLog, 9)))
|
||||
return 1;
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)))
|
||||
return 1;
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, ZSTD_btopt)))
|
||||
return 1;
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetLength, 7)))
|
||||
return 1;
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 7)))
|
||||
return 1;
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_searchLog, 1)))
|
||||
return 1;
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 10)))
|
||||
return 1;
|
||||
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_chainLog, 10)))
|
||||
return 1;
|
||||
|
||||
if (ZSTD_isError(ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 31)))
|
||||
return 1;
|
||||
|
||||
RDG_genBuffer(buffer, bufferSize, 1.0, 0.0, 0xbeefcafe);
|
||||
|
||||
/* Compress 30 GB */
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 10; ++i) {
|
||||
fprintf(stderr, "Compressing 1 GB\n");
|
||||
if (compress(cctx, dctx, out, outSize, buffer, dataSize, roundtrip, ZSTD_e_continue))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Compressing 1 GB\n");
|
||||
if (compress(cctx, dctx, out, outSize, buffer, dataSize, roundtrip, ZSTD_e_end))
|
||||
return 1;
|
||||
|
||||
fprintf(stderr, "Success!\n");
|
||||
|
||||
free(roundtrip);
|
||||
free(out);
|
||||
free(buffer);
|
||||
ZSTD_freeDCtx(dctx);
|
||||
ZSTD_freeCCtx(cctx);
|
||||
return 0;
|
||||
}
|
||||
+21
-18
@@ -16,6 +16,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "timefn.h" /* UTIL_clockSpanMicro, SEC_TO_MICRO, UTIL_TIME_INITIALIZER */
|
||||
#include "zstd.h"
|
||||
#include "zstd_internal.h"
|
||||
#include "mem.h"
|
||||
@@ -513,7 +514,7 @@ static size_t writeLiteralsBlockCompressed(U32* seed, frame_t* frame, size_t con
|
||||
if ((RAND(seed) & 3) || !frame->stats.hufInit) {
|
||||
do {
|
||||
if (RAND(seed) & 3) {
|
||||
/* add 10 to ensure some compressability */
|
||||
/* add 10 to ensure some compressibility */
|
||||
double const weight = ((RAND(seed) % 90) + 10) / 100.0;
|
||||
|
||||
DISPLAYLEVEL(5, " distribution weight: %d%%\n",
|
||||
@@ -839,16 +840,16 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr,
|
||||
{ unsigned max = MaxLL;
|
||||
size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, WKSP, sizeof(WKSP)); /* cannot fail */
|
||||
assert(!HIST_isError(mostFrequent));
|
||||
if (mostFrequent == nbSeq) {
|
||||
/* do RLE if we have the chance */
|
||||
*op++ = llCodeTable[0];
|
||||
FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
|
||||
LLtype = set_rle;
|
||||
} else if (frame->stats.fseInit && !(RAND(seed) & 3) &&
|
||||
if (frame->stats.fseInit && !(RAND(seed) & 3) &&
|
||||
isSymbolSubset(llCodeTable, nbSeq,
|
||||
frame->stats.litlengthSymbolSet, 35)) {
|
||||
/* maybe do repeat mode if we're allowed to */
|
||||
LLtype = set_repeat;
|
||||
} else if (mostFrequent == nbSeq) {
|
||||
/* do RLE if we have the chance */
|
||||
*op++ = llCodeTable[0];
|
||||
FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
|
||||
LLtype = set_rle;
|
||||
} else if (!(RAND(seed) & 3)) {
|
||||
/* maybe use the default distribution */
|
||||
FSE_buildCTable_wksp(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));
|
||||
@@ -871,14 +872,14 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr,
|
||||
{ unsigned max = MaxOff;
|
||||
size_t const mostFrequent = HIST_countFast_wksp(count, &max, ofCodeTable, nbSeq, WKSP, sizeof(WKSP)); /* cannot fail */
|
||||
assert(!HIST_isError(mostFrequent));
|
||||
if (mostFrequent == nbSeq) {
|
||||
*op++ = ofCodeTable[0];
|
||||
FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
|
||||
Offtype = set_rle;
|
||||
} else if (frame->stats.fseInit && !(RAND(seed) & 3) &&
|
||||
if (frame->stats.fseInit && !(RAND(seed) & 3) &&
|
||||
isSymbolSubset(ofCodeTable, nbSeq,
|
||||
frame->stats.offsetSymbolSet, 28)) {
|
||||
Offtype = set_repeat;
|
||||
} else if (mostFrequent == nbSeq) {
|
||||
*op++ = ofCodeTable[0];
|
||||
FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
|
||||
Offtype = set_rle;
|
||||
} else if (!(RAND(seed) & 3)) {
|
||||
FSE_buildCTable_wksp(CTable_OffsetBits, OF_defaultNorm, DefaultMaxOff, OF_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));
|
||||
Offtype = set_basic;
|
||||
@@ -899,14 +900,14 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr,
|
||||
{ unsigned max = MaxML;
|
||||
size_t const mostFrequent = HIST_countFast_wksp(count, &max, mlCodeTable, nbSeq, WKSP, sizeof(WKSP)); /* cannot fail */
|
||||
assert(!HIST_isError(mostFrequent));
|
||||
if (mostFrequent == nbSeq) {
|
||||
*op++ = *mlCodeTable;
|
||||
FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
|
||||
MLtype = set_rle;
|
||||
} else if (frame->stats.fseInit && !(RAND(seed) & 3) &&
|
||||
if (frame->stats.fseInit && !(RAND(seed) & 3) &&
|
||||
isSymbolSubset(mlCodeTable, nbSeq,
|
||||
frame->stats.matchlengthSymbolSet, 52)) {
|
||||
MLtype = set_repeat;
|
||||
} else if (mostFrequent == nbSeq) {
|
||||
*op++ = *mlCodeTable;
|
||||
FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
|
||||
MLtype = set_rle;
|
||||
} else if (!(RAND(seed) & 3)) {
|
||||
/* sometimes do default distribution */
|
||||
FSE_buildCTable_wksp(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));
|
||||
@@ -938,7 +939,9 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr,
|
||||
FSE_CState_t stateOffsetBits;
|
||||
FSE_CState_t stateLitLength;
|
||||
|
||||
CHECK_E(BIT_initCStream(&blockStream, op, oend-op), dstSize_tooSmall); /* not enough space remaining */
|
||||
RETURN_ERROR_IF(
|
||||
ERR_isError(BIT_initCStream(&blockStream, op, oend-op)),
|
||||
dstSize_tooSmall, "not enough space remaining");
|
||||
|
||||
/* first symbols */
|
||||
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
|
||||
|
||||
+138
-104
@@ -15,8 +15,9 @@
|
||||
#include "util.h" /* Compiler options, UTIL_GetFileSize */
|
||||
#include <stdlib.h> /* malloc */
|
||||
#include <stdio.h> /* fprintf, fopen, ftello64 */
|
||||
#include <assert.h> /* assert */
|
||||
#include <assert.h>
|
||||
|
||||
#include "timefn.h" /* UTIL_clockSpanNano, UTIL_getTime */
|
||||
#include "mem.h" /* U32 */
|
||||
#ifndef ZSTD_DLL_IMPORT
|
||||
#include "zstd_internal.h" /* ZSTD_decodeSeqHeaders, ZSTD_blockHeaderSize, blockType_e, KB, MB */
|
||||
@@ -30,8 +31,8 @@
|
||||
#include "zstd.h" /* ZSTD_versionString */
|
||||
#include "util.h" /* time functions */
|
||||
#include "datagen.h"
|
||||
#include "benchfn.h" /* CustomBench*/
|
||||
#include "benchzstd.h" /* MB_UNIT */
|
||||
#include "benchfn.h" /* CustomBench */
|
||||
#include "benchzstd.h" /* MB_UNIT */
|
||||
|
||||
|
||||
/*_************************************
|
||||
@@ -50,7 +51,7 @@
|
||||
#define DEFAULT_CLEVEL 1
|
||||
|
||||
#define COMPRESSIBILITY_DEFAULT 0.50
|
||||
static const size_t g_sampleSize = 10000000;
|
||||
static const size_t kSampleSizeDefault = 10000000;
|
||||
|
||||
#define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */
|
||||
|
||||
@@ -60,18 +61,12 @@ static const size_t g_sampleSize = 10000000;
|
||||
**************************************/
|
||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||
|
||||
#define CONTROL(c) { if (!(c)) { abort(); } } /* like assert(), but cannot be disabled */
|
||||
|
||||
/*_************************************
|
||||
* Benchmark Parameters
|
||||
**************************************/
|
||||
static unsigned g_nbIterations = NBLOOPS;
|
||||
static double g_compressibility = COMPRESSIBILITY_DEFAULT;
|
||||
|
||||
static void BMK_SetNbIterations(unsigned nbLoops)
|
||||
{
|
||||
g_nbIterations = nbLoops;
|
||||
DISPLAY("- %i iterations -\n", g_nbIterations);
|
||||
}
|
||||
|
||||
|
||||
/*_*******************************************************
|
||||
@@ -105,12 +100,12 @@ static ZSTD_CCtx* g_zcc = NULL;
|
||||
static size_t
|
||||
local_ZSTD_compress(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstSize,
|
||||
void* buff2)
|
||||
void* payload)
|
||||
{
|
||||
ZSTD_parameters p;
|
||||
ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 };
|
||||
p.fParams = f;
|
||||
p.cParams = *(ZSTD_compressionParameters*)buff2;
|
||||
p.cParams = *(ZSTD_compressionParameters*)payload;
|
||||
return ZSTD_compress_advanced (g_zcc, dst, dstSize, src, srcSize, NULL ,0, p);
|
||||
//return ZSTD_compress(dst, dstSize, src, srcSize, cLevel);
|
||||
}
|
||||
@@ -131,7 +126,7 @@ extern size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* ctx, const void* src, size_t s
|
||||
static size_t local_ZSTD_decodeLiteralsBlock(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2)
|
||||
{
|
||||
(void)src; (void)srcSize; (void)dst; (void)dstSize;
|
||||
return ZSTD_decodeLiteralsBlock((ZSTD_DCtx*)g_zdc, buff2, g_cSize);
|
||||
return ZSTD_decodeLiteralsBlock(g_zdc, buff2, g_cSize);
|
||||
}
|
||||
|
||||
static size_t local_ZSTD_decodeSeqHeaders(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2)
|
||||
@@ -146,14 +141,14 @@ static ZSTD_CStream* g_cstream= NULL;
|
||||
static size_t
|
||||
local_ZSTD_compressStream(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* buff2)
|
||||
void* payload)
|
||||
{
|
||||
ZSTD_outBuffer buffOut;
|
||||
ZSTD_inBuffer buffIn;
|
||||
ZSTD_parameters p;
|
||||
ZSTD_frameParameters f = {1 /* contentSizeHeader*/, 0, 0};
|
||||
p.fParams = f;
|
||||
p.cParams = *(ZSTD_compressionParameters*)buff2;
|
||||
p.cParams = *(ZSTD_compressionParameters*)payload;
|
||||
ZSTD_initCStream_advanced(g_cstream, NULL, 0, p, ZSTD_CONTENTSIZE_UNKNOWN);
|
||||
buffOut.dst = dst;
|
||||
buffOut.size = dstCapacity;
|
||||
@@ -166,23 +161,39 @@ local_ZSTD_compressStream(const void* src, size_t srcSize,
|
||||
return buffOut.pos;
|
||||
}
|
||||
|
||||
static size_t
|
||||
local_ZSTD_compressStream_freshCCtx(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* payload)
|
||||
{
|
||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
size_t r;
|
||||
assert(cctx != NULL);
|
||||
|
||||
r = local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, payload);
|
||||
|
||||
ZSTD_freeCCtx(cctx);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static size_t
|
||||
local_ZSTD_compress_generic_end(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* buff2)
|
||||
void* payload)
|
||||
{
|
||||
(void)buff2;
|
||||
(void)payload;
|
||||
return ZSTD_compress2(g_cstream, dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
static size_t
|
||||
local_ZSTD_compress_generic_continue(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* buff2)
|
||||
void* payload)
|
||||
{
|
||||
ZSTD_outBuffer buffOut;
|
||||
ZSTD_inBuffer buffIn;
|
||||
(void)buff2;
|
||||
(void)payload;
|
||||
buffOut.dst = dst;
|
||||
buffOut.size = dstCapacity;
|
||||
buffOut.pos = 0;
|
||||
@@ -197,9 +208,9 @@ local_ZSTD_compress_generic_continue(const void* src, size_t srcSize,
|
||||
static size_t
|
||||
local_ZSTD_compress_generic_T2_end(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* buff2)
|
||||
void* payload)
|
||||
{
|
||||
(void)buff2;
|
||||
(void)payload;
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_nbWorkers, 2);
|
||||
return ZSTD_compress2(g_cstream, dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
@@ -207,11 +218,11 @@ local_ZSTD_compress_generic_T2_end(const void* src, size_t srcSize,
|
||||
static size_t
|
||||
local_ZSTD_compress_generic_T2_continue(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* buff2)
|
||||
void* payload)
|
||||
{
|
||||
ZSTD_outBuffer buffOut;
|
||||
ZSTD_inBuffer buffIn;
|
||||
(void)buff2;
|
||||
(void)payload;
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_nbWorkers, 2);
|
||||
buffOut.dst = dst;
|
||||
buffOut.size = dstCapacity;
|
||||
@@ -247,27 +258,28 @@ local_ZSTD_decompressStream(const void* src, size_t srcSize,
|
||||
#ifndef ZSTD_DLL_IMPORT
|
||||
static size_t local_ZSTD_compressContinue(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* buff2)
|
||||
void* payload)
|
||||
{
|
||||
ZSTD_parameters p;
|
||||
ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 };
|
||||
p.fParams = f;
|
||||
p.cParams = *(ZSTD_compressionParameters*)buff2;
|
||||
p.cParams = *(ZSTD_compressionParameters*)payload;
|
||||
ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize);
|
||||
return ZSTD_compressEnd(g_zcc, dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
#define FIRST_BLOCK_SIZE 8
|
||||
static size_t local_ZSTD_compressContinue_extDict(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* buff2)
|
||||
static size_t
|
||||
local_ZSTD_compressContinue_extDict(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* payload)
|
||||
{
|
||||
BYTE firstBlockBuf[FIRST_BLOCK_SIZE];
|
||||
|
||||
ZSTD_parameters p;
|
||||
ZSTD_frameParameters f = { 1, 0, 0 };
|
||||
ZSTD_frameParameters const f = { 1, 0, 0 };
|
||||
p.fParams = f;
|
||||
p.cParams = *(ZSTD_compressionParameters*)buff2;
|
||||
p.cParams = *(ZSTD_compressionParameters*)payload;
|
||||
ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize);
|
||||
memcpy(firstBlockBuf, src, FIRST_BLOCK_SIZE);
|
||||
|
||||
@@ -316,14 +328,14 @@ static size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize,
|
||||
/*_*******************************************************
|
||||
* Bench functions
|
||||
*********************************************************/
|
||||
static size_t benchMem(unsigned benchNb,
|
||||
const void* src, size_t srcSize,
|
||||
int cLevel, ZSTD_compressionParameters cparams)
|
||||
static int benchMem(unsigned benchNb,
|
||||
const void* src, size_t srcSize,
|
||||
int cLevel, ZSTD_compressionParameters cparams)
|
||||
{
|
||||
size_t dstBuffSize = ZSTD_compressBound(srcSize);
|
||||
BYTE* dstBuff;
|
||||
void* dstBuff2;
|
||||
void* buff2;
|
||||
void* payload;
|
||||
const char* benchName;
|
||||
BMK_benchFn_t benchFunction;
|
||||
int errorcode = 0;
|
||||
@@ -360,6 +372,9 @@ static size_t benchMem(unsigned benchNb,
|
||||
case 42:
|
||||
benchFunction = local_ZSTD_decompressStream; benchName = "decompressStream";
|
||||
break;
|
||||
case 43:
|
||||
benchFunction = local_ZSTD_compressStream_freshCCtx; benchName = "compressStream_freshCCtx";
|
||||
break;
|
||||
case 51:
|
||||
benchFunction = local_ZSTD_compress_generic_continue; benchName = "compress_generic, continue";
|
||||
break;
|
||||
@@ -384,7 +399,7 @@ static size_t benchMem(unsigned benchNb,
|
||||
free(dstBuff); free(dstBuff2);
|
||||
return 12;
|
||||
}
|
||||
buff2 = dstBuff2;
|
||||
payload = dstBuff2;
|
||||
if (g_zcc==NULL) g_zcc = ZSTD_createCCtx();
|
||||
if (g_zdc==NULL) g_zdc = ZSTD_createDCtx();
|
||||
if (g_cstream==NULL) g_cstream = ZSTD_createCStream();
|
||||
@@ -395,83 +410,88 @@ static size_t benchMem(unsigned benchNb,
|
||||
cparams->minMatch, cparams->targetLength, cparams->strategy); */
|
||||
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_windowLog, cparams.windowLog);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_hashLog, cparams.hashLog);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_chainLog, cparams.chainLog);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_searchLog, cparams.searchLog);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_minMatch, cparams.minMatch);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_targetLength, cparams.targetLength);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_windowLog, (int)cparams.windowLog);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_hashLog, (int)cparams.hashLog);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_chainLog, (int)cparams.chainLog);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_searchLog, (int)cparams.searchLog);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_minMatch, (int)cparams.minMatch);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_targetLength, (int)cparams.targetLength);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_strategy, cparams.strategy);
|
||||
|
||||
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_compressionLevel, cLevel);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_windowLog, cparams.windowLog);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_hashLog, cparams.hashLog);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_chainLog, cparams.chainLog);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_searchLog, cparams.searchLog);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_minMatch, cparams.minMatch);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_targetLength, cparams.targetLength);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_windowLog, (int)cparams.windowLog);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_hashLog, (int)cparams.hashLog);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_chainLog, (int)cparams.chainLog);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_searchLog, (int)cparams.searchLog);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_minMatch, (int)cparams.minMatch);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_targetLength, (int)cparams.targetLength);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_strategy, cparams.strategy);
|
||||
|
||||
/* Preparation */
|
||||
switch(benchNb)
|
||||
{
|
||||
case 1:
|
||||
buff2 = &cparams;
|
||||
payload = &cparams;
|
||||
break;
|
||||
case 2:
|
||||
g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel);
|
||||
g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel);
|
||||
break;
|
||||
#ifndef ZSTD_DLL_IMPORT
|
||||
case 11:
|
||||
buff2 = &cparams;
|
||||
payload = &cparams;
|
||||
break;
|
||||
case 12:
|
||||
buff2 = &cparams;
|
||||
payload = &cparams;
|
||||
break;
|
||||
case 13 :
|
||||
g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel);
|
||||
g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel);
|
||||
break;
|
||||
case 31: /* ZSTD_decodeLiteralsBlock */
|
||||
{ blockProperties_t bp;
|
||||
ZSTD_frameHeader zfp;
|
||||
size_t frameHeaderSize, skippedSize;
|
||||
case 31: /* ZSTD_decodeLiteralsBlock : starts literals block in dstBuff2 */
|
||||
{ size_t frameHeaderSize;
|
||||
g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel);
|
||||
frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_FRAMEHEADERSIZE_MIN);
|
||||
if (frameHeaderSize==0) frameHeaderSize = ZSTD_FRAMEHEADERSIZE_MIN;
|
||||
ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */
|
||||
if (bp.blockType != bt_compressed) {
|
||||
DISPLAY("ZSTD_decodeLiteralsBlock : impossible to test on this sample (not compressible)\n");
|
||||
goto _cleanOut;
|
||||
frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX);
|
||||
CONTROL(!ZSTD_isError(frameHeaderSize));
|
||||
/* check block is compressible, hence contains a literals section */
|
||||
{ blockProperties_t bp;
|
||||
ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */
|
||||
if (bp.blockType != bt_compressed) {
|
||||
DISPLAY("ZSTD_decodeLiteralsBlock : impossible to test on this sample (not compressible)\n");
|
||||
goto _cleanOut;
|
||||
} }
|
||||
{ size_t const skippedSize = frameHeaderSize + ZSTD_blockHeaderSize;
|
||||
memcpy(dstBuff2, dstBuff+skippedSize, g_cSize-skippedSize);
|
||||
}
|
||||
skippedSize = frameHeaderSize + ZSTD_blockHeaderSize;
|
||||
memcpy(buff2, dstBuff+skippedSize, g_cSize-skippedSize);
|
||||
srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */
|
||||
ZSTD_decompressBegin(g_zdc);
|
||||
break;
|
||||
}
|
||||
case 32: /* ZSTD_decodeSeqHeaders */
|
||||
{ blockProperties_t bp;
|
||||
ZSTD_frameHeader zfp;
|
||||
const BYTE* ip = dstBuff;
|
||||
const BYTE* iend;
|
||||
size_t frameHeaderSize, cBlockSize;
|
||||
ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); /* it would be better to use direct block compression here */
|
||||
g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel);
|
||||
frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_FRAMEHEADERSIZE_MIN);
|
||||
if (frameHeaderSize==0) frameHeaderSize = ZSTD_FRAMEHEADERSIZE_MIN;
|
||||
ip += frameHeaderSize; /* Skip frame Header */
|
||||
cBlockSize = ZSTD_getcBlockSize(ip, dstBuffSize, &bp); /* Get 1st block type */
|
||||
if (bp.blockType != bt_compressed) {
|
||||
DISPLAY("ZSTD_decodeSeqHeaders : impossible to test on this sample (not compressible)\n");
|
||||
goto _cleanOut;
|
||||
{ size_t const cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel);
|
||||
CONTROL(cSize > ZSTD_FRAMEHEADERSIZE_PREFIX);
|
||||
}
|
||||
iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */
|
||||
ip += ZSTD_blockHeaderSize; /* skip block header */
|
||||
/* Skip frame Header */
|
||||
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX);
|
||||
CONTROL(!ZSTD_isError(frameHeaderSize));
|
||||
ip += frameHeaderSize;
|
||||
}
|
||||
/* Find end of block */
|
||||
{ size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstBuffSize, &bp); /* Get 1st block type */
|
||||
if (bp.blockType != bt_compressed) {
|
||||
DISPLAY("ZSTD_decodeSeqHeaders : impossible to test on this sample (not compressible)\n");
|
||||
goto _cleanOut;
|
||||
}
|
||||
iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */
|
||||
}
|
||||
ip += ZSTD_blockHeaderSize; /* skip block header */
|
||||
ZSTD_decompressBegin(g_zdc);
|
||||
ip += ZSTD_decodeLiteralsBlock(g_zdc, ip, iend-ip); /* skip literal segment */
|
||||
g_cSize = iend-ip;
|
||||
memcpy(buff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */
|
||||
CONTROL(iend > ip);
|
||||
ip += ZSTD_decodeLiteralsBlock(g_zdc, ip, (size_t)(iend-ip)); /* skip literal segment */
|
||||
g_cSize = (size_t)(iend-ip);
|
||||
memcpy(dstBuff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */
|
||||
srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */
|
||||
break;
|
||||
}
|
||||
@@ -480,10 +500,13 @@ static size_t benchMem(unsigned benchNb,
|
||||
goto _cleanOut;
|
||||
#endif
|
||||
case 41 :
|
||||
buff2 = &cparams;
|
||||
payload = &cparams;
|
||||
break;
|
||||
case 42 :
|
||||
g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel);
|
||||
g_cSize = ZSTD_compress(payload, dstBuffSize, src, srcSize, cLevel);
|
||||
break;
|
||||
case 43 :
|
||||
payload = &cparams;
|
||||
break;
|
||||
|
||||
/* test functions */
|
||||
@@ -501,11 +524,11 @@ static size_t benchMem(unsigned benchNb,
|
||||
BMK_benchParams_t bp;
|
||||
BMK_runTime_t bestResult;
|
||||
bestResult.sumOfReturn = 0;
|
||||
bestResult.nanoSecPerRun = (unsigned long long)(-1LL);
|
||||
assert(tfs != NULL);
|
||||
bestResult.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000; /* hopefully large enough : must be larger than any potential measurement */
|
||||
CONTROL(tfs != NULL);
|
||||
|
||||
bp.benchFn = benchFunction;
|
||||
bp.benchPayload = buff2;
|
||||
bp.benchPayload = payload;
|
||||
bp.initFn = NULL;
|
||||
bp.initPayload = NULL;
|
||||
bp.errorFn = ZSTD_isError;
|
||||
@@ -553,21 +576,19 @@ _cleanOut:
|
||||
|
||||
|
||||
static int benchSample(U32 benchNb,
|
||||
size_t benchedSize, double compressibility,
|
||||
int cLevel, ZSTD_compressionParameters cparams)
|
||||
{
|
||||
size_t const benchedSize = g_sampleSize;
|
||||
const char* const name = "Sample 10MiB";
|
||||
|
||||
/* Allocation */
|
||||
void* const origBuff = malloc(benchedSize);
|
||||
if (!origBuff) { DISPLAY("\nError: not enough memory!\n"); return 12; }
|
||||
|
||||
/* Fill buffer */
|
||||
RDG_genBuffer(origBuff, benchedSize, g_compressibility, 0.0, 0);
|
||||
RDG_genBuffer(origBuff, benchedSize, compressibility, 0.0, 0);
|
||||
|
||||
/* bench */
|
||||
DISPLAY("\r%70s\r", "");
|
||||
DISPLAY(" %s : \n", name);
|
||||
DISPLAY(" Sample %u bytes : \n", (unsigned)benchedSize);
|
||||
if (benchNb) {
|
||||
benchMem(benchNb, origBuff, benchedSize, cLevel, cparams);
|
||||
} else { /* 0 == run all tests */
|
||||
@@ -654,7 +675,9 @@ static unsigned readU32FromChar(const char** stringPtr)
|
||||
while ((**stringPtr >='0') && (**stringPtr <='9')) {
|
||||
unsigned const max = (((unsigned)(-1)) / 10) - 1;
|
||||
if (result > max) ERROR_OUT(errorMsg);
|
||||
result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
|
||||
result *= 10;
|
||||
result += (unsigned)(**stringPtr - '0');
|
||||
(*stringPtr)++ ;
|
||||
}
|
||||
if ((**stringPtr=='K') || (**stringPtr=='M')) {
|
||||
unsigned const maxK = ((unsigned)(-1)) >> 10;
|
||||
@@ -671,7 +694,7 @@ static unsigned readU32FromChar(const char** stringPtr)
|
||||
return result;
|
||||
}
|
||||
|
||||
static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
|
||||
static int longCommandWArg(const char** stringPtr, const char* longCommand)
|
||||
{
|
||||
size_t const comSize = strlen(longCommand);
|
||||
int const result = !strncmp(*stringPtr, longCommand, comSize);
|
||||
@@ -698,10 +721,11 @@ static int usage_advanced(const char* exename)
|
||||
usage(exename);
|
||||
DISPLAY( "\nAdvanced options :\n");
|
||||
DISPLAY( " -b# : test only function # \n");
|
||||
DISPLAY( " -i# : iteration loops [1-9](default : %i)\n", NBLOOPS);
|
||||
DISPLAY( " -P# : sample compressibility (default : %.1f%%)\n", COMPRESSIBILITY_DEFAULT * 100);
|
||||
DISPLAY( " -l# : benchmark functions at that compression level (default : %i)\n", DEFAULT_CLEVEL);
|
||||
DISPLAY( " --zstd : custom parameter selection. Format same as zstdcli \n");
|
||||
DISPLAY( " -P# : sample compressibility (default : %.1f%%)\n", COMPRESSIBILITY_DEFAULT * 100);
|
||||
DISPLAY( " -B# : sample size (default : %u)\n", (unsigned)kSampleSizeDefault);
|
||||
DISPLAY( " -i# : iteration loops [1-9](default : %i)\n", NBLOOPS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -720,13 +744,15 @@ int main(int argc, const char** argv)
|
||||
U32 benchNb = 0, main_pause = 0;
|
||||
int cLevel = DEFAULT_CLEVEL;
|
||||
ZSTD_compressionParameters cparams = ZSTD_getCParams(cLevel, 0, 0);
|
||||
size_t sampleSize = kSampleSizeDefault;
|
||||
double compressibility = COMPRESSIBILITY_DEFAULT;
|
||||
|
||||
DISPLAY(WELCOME_MESSAGE);
|
||||
if (argc<1) return badusage(exename);
|
||||
|
||||
for (argNb=1; argNb<argc; argNb++) {
|
||||
const char* argument = argv[argNb];
|
||||
assert(argument != NULL);
|
||||
CONTROL(argument != NULL);
|
||||
|
||||
if (longCommandWArg(&argument, "--zstd=")) {
|
||||
for ( ; ;) {
|
||||
@@ -769,21 +795,29 @@ int main(int argc, const char** argv)
|
||||
benchNb = readU32FromChar(&argument);
|
||||
break;
|
||||
|
||||
/* Modify Nb Iterations */
|
||||
case 'i':
|
||||
/* Select compression level to use */
|
||||
case 'l':
|
||||
argument++;
|
||||
BMK_SetNbIterations((int)readU32FromChar(&argument));
|
||||
cLevel = (int)readU32FromChar(&argument);
|
||||
cparams = ZSTD_getCParams(cLevel, 0, 0);
|
||||
break;
|
||||
|
||||
/* Select compressibility of synthetic sample */
|
||||
case 'P':
|
||||
argument++;
|
||||
g_compressibility = (double)readU32FromChar(&argument) / 100.;
|
||||
compressibility = (double)readU32FromChar(&argument) / 100.;
|
||||
break;
|
||||
case 'l':
|
||||
|
||||
/* Select size of synthetic sample */
|
||||
case 'B':
|
||||
argument++;
|
||||
cLevel = readU32FromChar(&argument);
|
||||
cparams = ZSTD_getCParams(cLevel, 0, 0);
|
||||
sampleSize = (size_t)readU32FromChar(&argument);
|
||||
break;
|
||||
|
||||
/* Modify Nb Iterations */
|
||||
case 'i':
|
||||
argument++;
|
||||
g_nbIterations = readU32FromChar(&argument);
|
||||
break;
|
||||
|
||||
/* Unknown command */
|
||||
@@ -800,7 +834,7 @@ int main(int argc, const char** argv)
|
||||
|
||||
|
||||
if (filenamesStart==0) /* no input file */
|
||||
result = benchSample(benchNb, cLevel, cparams);
|
||||
result = benchSample(benchNb, sampleSize, compressibility, cLevel, cparams);
|
||||
else
|
||||
result = benchFiles(benchNb, argv+filenamesStart, argc-filenamesStart, cLevel, cparams);
|
||||
|
||||
|
||||
+33
-8
@@ -26,17 +26,17 @@ ZSTDDIR = ../../lib
|
||||
PRGDIR = ../../programs
|
||||
|
||||
FUZZ_CPPFLAGS := -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
|
||||
-I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR) \
|
||||
$(CPPFLAGS)
|
||||
-I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(ZSTDDIR)/legacy \
|
||||
-I$(PRGDIR) -DZSTD_MULTITHREAD -DZSTD_LEGACY_SUPPORT=1 $(CPPFLAGS)
|
||||
FUZZ_EXTRA_FLAGS := -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||
-Wstrict-prototypes -Wundef -Wformat-security \
|
||||
-Wstrict-prototypes -Wundef \
|
||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||
-Wredundant-decls \
|
||||
-g -fno-omit-frame-pointer
|
||||
FUZZ_CFLAGS := $(FUZZ_EXTRA_FLAGS) $(CFLAGS)
|
||||
FUZZ_CXXFLAGS := $(FUZZ_EXTRA_FLAGS) -std=c++11 $(CXXFLAGS)
|
||||
FUZZ_LDFLAGS := $(LDFLAGS)
|
||||
FUZZ_LDFLAGS := -pthread $(LDFLAGS)
|
||||
FUZZ_ARFLAGS := $(ARFLAGS)
|
||||
FUZZ_TARGET_FLAGS = $(FUZZ_CPPFLAGS) $(FUZZ_CXXFLAGS) $(FUZZ_LDFLAGS)
|
||||
|
||||
@@ -46,11 +46,15 @@ FUZZ_SRC := $(PRGDIR)/util.c zstd_helpers.c
|
||||
ZSTDCOMMON_SRC := $(ZSTDDIR)/common/*.c
|
||||
ZSTDCOMP_SRC := $(ZSTDDIR)/compress/*.c
|
||||
ZSTDDECOMP_SRC := $(ZSTDDIR)/decompress/*.c
|
||||
ZSTDDICT_SRC := $(ZSTDDIR)/dictBuilder/*.c
|
||||
ZSTDLEGACY_SRC := $(ZSTDDIR)/legacy/*.c
|
||||
FUZZ_SRC := \
|
||||
$(FUZZ_SRC) \
|
||||
$(ZSTDDECOMP_SRC) \
|
||||
$(ZSTDCOMMON_SRC) \
|
||||
$(ZSTDCOMP_SRC)
|
||||
$(ZSTDCOMP_SRC) \
|
||||
$(ZSTDDICT_SRC) \
|
||||
$(ZSTDLEGACY_SRC)
|
||||
|
||||
FUZZ_OBJ := $(patsubst %.c,%.o, $(wildcard $(FUZZ_SRC)))
|
||||
|
||||
@@ -65,7 +69,11 @@ FUZZ_TARGETS := \
|
||||
block_round_trip \
|
||||
simple_decompress \
|
||||
stream_decompress \
|
||||
block_decompress
|
||||
block_decompress \
|
||||
dictionary_round_trip \
|
||||
dictionary_decompress \
|
||||
zstd_frame_info \
|
||||
simple_compress
|
||||
|
||||
all: $(FUZZ_TARGETS)
|
||||
|
||||
@@ -90,11 +98,23 @@ stream_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) stream_decompress.o
|
||||
block_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) block_decompress.o
|
||||
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) block_decompress.o $(LIB_FUZZING_ENGINE) -o $@
|
||||
|
||||
dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_round_trip.o
|
||||
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_round_trip.o $(LIB_FUZZING_ENGINE) -o $@
|
||||
|
||||
dictionary_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_decompress.o
|
||||
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_decompress.o $(LIB_FUZZING_ENGINE) -o $@
|
||||
|
||||
simple_compress: $(FUZZ_HEADERS) $(FUZZ_OBJ) simple_compress.o
|
||||
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) simple_compress.o $(LIB_FUZZING_ENGINE) -o $@
|
||||
|
||||
zstd_frame_info: $(FUZZ_HEADERS) $(FUZZ_OBJ) zstd_frame_info.o
|
||||
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) zstd_frame_info.o $(LIB_FUZZING_ENGINE) -o $@
|
||||
|
||||
libregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c regression_driver.o
|
||||
$(AR) $(FUZZ_ARFLAGS) $@ regression_driver.o
|
||||
|
||||
# Install libfuzzer (not usable for MSAN testing)
|
||||
# Provided for convienence. To use this library run make libFuzzer and
|
||||
# Provided for convenience. To use this library run make libFuzzer and
|
||||
# set LDFLAGS=-L.
|
||||
.PHONY: libFuzzer
|
||||
libFuzzer:
|
||||
@@ -112,6 +132,9 @@ corpora/%: corpora/%_seed_corpus.zip
|
||||
.PHONY: corpora
|
||||
corpora: $(patsubst %,corpora/%,$(FUZZ_TARGETS))
|
||||
|
||||
.PHONY: seedcorpora
|
||||
seedcorpora: $(patsubst %,corpora/%_seed_corpus.zip,$(FUZZ_TARGETS))
|
||||
|
||||
regressiontest: corpora
|
||||
CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" $(PYTHON) ./fuzz.py build all
|
||||
$(PYTHON) ./fuzz.py regression all
|
||||
@@ -120,7 +143,9 @@ clean:
|
||||
@$(MAKE) -C $(ZSTDDIR) clean
|
||||
@$(RM) *.a *.o
|
||||
@$(RM) simple_round_trip stream_round_trip simple_decompress \
|
||||
stream_decompress block_decompress block_round_trip
|
||||
stream_decompress block_decompress block_round_trip \
|
||||
simple_compress dictionary_round_trip dictionary_decompress \
|
||||
zstd_frame_info
|
||||
|
||||
cleanall:
|
||||
@$(RM) -r Fuzzer
|
||||
|
||||
@@ -37,8 +37,8 @@ The specific fuzzing engine is selected with `LIB_FUZZING_ENGINE` or
|
||||
`--lib-fuzzing-engine`, the default is `libregression.a`.
|
||||
It has flags that can easily set up sanitizers `--enable-{a,ub,m}san`, and
|
||||
coverage instrumentation `--enable-coverage`.
|
||||
It sets sane defaults which can be overriden with flags `--debug`,
|
||||
`--enable-ubsan-pointer-overlow`, etc.
|
||||
It sets sane defaults which can be overridden with flags `--debug`,
|
||||
`--enable-ubsan-pointer-overflow`, etc.
|
||||
Run `./fuzz.py build -h` for help.
|
||||
|
||||
### Running Fuzzers
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[libfuzzer]
|
||||
max_len = 8192
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
/**
|
||||
* This fuzz target attempts to decompress the fuzzed data with the dictionary
|
||||
* decompression function to ensure the decompressor never crashes. It does not
|
||||
* fuzz the dictionary.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "fuzz_helpers.h"
|
||||
#include "zstd_helpers.h"
|
||||
|
||||
static ZSTD_DCtx *dctx = NULL;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
{
|
||||
uint32_t seed = FUZZ_seed(&src, &size);
|
||||
FUZZ_dict_t dict;
|
||||
ZSTD_DDict* ddict = NULL;
|
||||
int i;
|
||||
|
||||
if (!dctx) {
|
||||
dctx = ZSTD_createDCtx();
|
||||
FUZZ_ASSERT(dctx);
|
||||
}
|
||||
dict = FUZZ_train(src, size, &seed);
|
||||
if (FUZZ_rand32(&seed, 0, 1) == 0) {
|
||||
ddict = ZSTD_createDDict(dict.buff, dict.size);
|
||||
FUZZ_ASSERT(ddict);
|
||||
} else {
|
||||
FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
|
||||
dctx, dict.buff, dict.size,
|
||||
(ZSTD_dictLoadMethod_e)FUZZ_rand32(&seed, 0, 1),
|
||||
(ZSTD_dictContentType_e)FUZZ_rand32(&seed, 0, 2)));
|
||||
}
|
||||
/* Run it 10 times over 10 output sizes. Reuse the context and dict. */
|
||||
for (i = 0; i < 10; ++i) {
|
||||
size_t const bufSize = FUZZ_rand32(&seed, 0, 2 * size);
|
||||
void* rBuf = malloc(bufSize);
|
||||
FUZZ_ASSERT(rBuf);
|
||||
if (ddict) {
|
||||
ZSTD_decompress_usingDDict(dctx, rBuf, bufSize, src, size, ddict);
|
||||
} else {
|
||||
ZSTD_decompressDCtx(dctx, rBuf, bufSize, src, size);
|
||||
}
|
||||
free(rBuf);
|
||||
}
|
||||
free(dict.buff);
|
||||
ZSTD_freeDDict(ddict);
|
||||
#ifndef STATEFUL_FUZZING
|
||||
ZSTD_freeDCtx(dctx); dctx = NULL;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
/**
|
||||
* This fuzz target performs a zstd round-trip test (compress & decompress) with
|
||||
* a dictionary, compares the result with the original, and calls abort() on
|
||||
* corruption.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "fuzz_helpers.h"
|
||||
#include "zstd_helpers.h"
|
||||
|
||||
static const int kMaxClevel = 19;
|
||||
|
||||
static ZSTD_CCtx *cctx = NULL;
|
||||
static ZSTD_DCtx *dctx = NULL;
|
||||
static uint32_t seed;
|
||||
|
||||
static size_t roundTripTest(void *result, size_t resultCapacity,
|
||||
void *compressed, size_t compressedCapacity,
|
||||
const void *src, size_t srcSize)
|
||||
{
|
||||
ZSTD_dictContentType_e dictContentType = ZSTD_dct_auto;
|
||||
FUZZ_dict_t dict = FUZZ_train(src, srcSize, &seed);
|
||||
size_t cSize;
|
||||
if ((FUZZ_rand(&seed) & 15) == 0) {
|
||||
int const cLevel = FUZZ_rand(&seed) % kMaxClevel;
|
||||
|
||||
cSize = ZSTD_compress_usingDict(cctx,
|
||||
compressed, compressedCapacity,
|
||||
src, srcSize,
|
||||
dict.buff, dict.size,
|
||||
cLevel);
|
||||
} else {
|
||||
dictContentType = FUZZ_rand32(&seed, 0, 2);
|
||||
FUZZ_setRandomParameters(cctx, srcSize, &seed);
|
||||
/* Disable checksum so we can use sizes smaller than compress bound. */
|
||||
FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0));
|
||||
FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(
|
||||
cctx, dict.buff, dict.size,
|
||||
(ZSTD_dictLoadMethod_e)FUZZ_rand32(&seed, 0, 1),
|
||||
dictContentType));
|
||||
cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);
|
||||
}
|
||||
FUZZ_ZASSERT(cSize);
|
||||
FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
|
||||
dctx, dict.buff, dict.size,
|
||||
(ZSTD_dictLoadMethod_e)FUZZ_rand32(&seed, 0, 1),
|
||||
dictContentType));
|
||||
{
|
||||
size_t const ret = ZSTD_decompressDCtx(
|
||||
dctx, result, resultCapacity, compressed, cSize);
|
||||
free(dict.buff);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
{
|
||||
size_t const rBufSize = size;
|
||||
void* rBuf = malloc(rBufSize);
|
||||
size_t cBufSize = ZSTD_compressBound(size);
|
||||
void* cBuf;
|
||||
|
||||
seed = FUZZ_seed(&src, &size);
|
||||
/* Half of the time fuzz with a 1 byte smaller output size.
|
||||
* This will still succeed because we force the checksum to be disabled,
|
||||
* giving us 4 bytes of overhead.
|
||||
*/
|
||||
cBufSize -= FUZZ_rand32(&seed, 0, 1);
|
||||
cBuf = malloc(cBufSize);
|
||||
|
||||
if (!cctx) {
|
||||
cctx = ZSTD_createCCtx();
|
||||
FUZZ_ASSERT(cctx);
|
||||
}
|
||||
if (!dctx) {
|
||||
dctx = ZSTD_createDCtx();
|
||||
FUZZ_ASSERT(dctx);
|
||||
}
|
||||
|
||||
{
|
||||
size_t const result =
|
||||
roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size);
|
||||
FUZZ_ZASSERT(result);
|
||||
FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size");
|
||||
FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!");
|
||||
}
|
||||
free(rBuf);
|
||||
free(cBuf);
|
||||
#ifndef STATEFUL_FUZZING
|
||||
ZSTD_freeCCtx(cctx); cctx = NULL;
|
||||
ZSTD_freeDCtx(dctx); dctx = NULL;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
+24
-6
@@ -34,6 +34,10 @@ TARGETS = [
|
||||
'simple_decompress',
|
||||
'stream_decompress',
|
||||
'block_decompress',
|
||||
'dictionary_round_trip',
|
||||
'dictionary_decompress',
|
||||
'zstd_frame_info',
|
||||
'simple_compress',
|
||||
]
|
||||
ALL_TARGETS = TARGETS + ['all']
|
||||
FUZZ_RNG_SEED_SIZE = 4
|
||||
@@ -192,11 +196,21 @@ def build_parser(args):
|
||||
default=LIB_FUZZING_ENGINE,
|
||||
help=('The fuzzing engine to use e.g. /path/to/libFuzzer.a '
|
||||
"(default: $LIB_FUZZING_ENGINE='{})".format(LIB_FUZZING_ENGINE)))
|
||||
parser.add_argument(
|
||||
|
||||
fuzz_group = parser.add_mutually_exclusive_group()
|
||||
fuzz_group.add_argument(
|
||||
'--enable-coverage',
|
||||
dest='coverage',
|
||||
action='store_true',
|
||||
help='Enable coverage instrumentation (-fsanitize-coverage)')
|
||||
fuzz_group.add_argument(
|
||||
'--enable-fuzzer',
|
||||
dest='fuzzer',
|
||||
action='store_true',
|
||||
help=('Enable clang fuzzer (-fsanitize=fuzzer). When enabled '
|
||||
'LIB_FUZZING_ENGINE is ignored')
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--enable-asan', dest='asan', action='store_true', help='Enable UBSAN')
|
||||
parser.add_argument(
|
||||
@@ -327,13 +341,13 @@ def build_parser(args):
|
||||
args = parse_env_flags(args, ' '.join(
|
||||
[args.cppflags, args.cflags, args.cxxflags, args.ldflags]))
|
||||
|
||||
# Check option sanitiy
|
||||
# Check option sanity
|
||||
if args.msan and (args.asan or args.ubsan):
|
||||
raise RuntimeError('MSAN may not be used with any other sanitizers')
|
||||
if args.msan_track_origins and not args.msan:
|
||||
raise RuntimeError('--enable-msan-track-origins requires MSAN')
|
||||
if args.ubsan_pointer_overflow and not args.ubsan:
|
||||
raise RuntimeError('--enable-ubsan-pointer-overlow requires UBSAN')
|
||||
raise RuntimeError('--enable-ubsan-pointer-overflow requires UBSAN')
|
||||
if args.sanitize_recover and not args.sanitize:
|
||||
raise RuntimeError('--enable-sanitize-recover but no sanitizers used')
|
||||
|
||||
@@ -364,13 +378,17 @@ def build(args):
|
||||
'-DFUZZ_RNG_SEED_SIZE={}'.format(args.fuzz_rng_seed_size),
|
||||
]
|
||||
|
||||
mflags += ['LIB_FUZZING_ENGINE={}'.format(args.lib_fuzzing_engine)]
|
||||
|
||||
# Set flags for options
|
||||
assert not (args.fuzzer and args.coverage)
|
||||
if args.coverage:
|
||||
common_flags += [
|
||||
'-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp'
|
||||
]
|
||||
if args.fuzzer:
|
||||
common_flags += ['-fsanitize=fuzzer']
|
||||
args.lib_fuzzing_engine = ''
|
||||
|
||||
mflags += ['LIB_FUZZING_ENGINE={}'.format(args.lib_fuzzing_engine)]
|
||||
|
||||
if args.sanitize_recover:
|
||||
recover_flags = ['-fsanitize-recover=all']
|
||||
@@ -607,7 +625,7 @@ def regression(args):
|
||||
|
||||
def gen_parser(args):
|
||||
description = """
|
||||
Generate a seed corpus appropiate for TARGET with data generated with
|
||||
Generate a seed corpus appropriate for TARGET with data generated with
|
||||
decodecorpus.
|
||||
The fuzz inputs are prepended with a seed before the zstd data, so the
|
||||
output of decodecorpus shouldn't be used directly.
|
||||
|
||||
@@ -55,7 +55,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Determininistically constructs a seed based on the fuzz input.
|
||||
* Deterministically constructs a seed based on the fuzz input.
|
||||
* Consumes up to the first FUZZ_RNG_SEED_SIZE bytes of the input.
|
||||
*/
|
||||
FUZZ_STATIC uint32_t FUZZ_seed(uint8_t const **src, size_t* size) {
|
||||
|
||||
@@ -40,8 +40,13 @@ int main(int argc, char const **argv) {
|
||||
size_t readSize;
|
||||
FILE *file;
|
||||
|
||||
/* Check that it is a regular file, and that the fileSize is valid */
|
||||
FUZZ_ASSERT_MSG(UTIL_isRegularFile(fileName), fileName);
|
||||
/* Check that it is a regular file, and that the fileSize is valid.
|
||||
* If it is not a regular file, then it may have been deleted since we
|
||||
* constructed the list, so just skip it.
|
||||
*/
|
||||
if (!UTIL_isRegularFile(fileName)) {
|
||||
continue;
|
||||
}
|
||||
FUZZ_ASSERT_MSG(fileSize <= kMaxFileSize, fileName);
|
||||
/* Ensure we have a large enough buffer allocated */
|
||||
if (fileSize > bufferSize) {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
/**
|
||||
* This fuzz target attempts to comprss the fuzzed data with the simple
|
||||
* compression function with an output buffer that may be too small to
|
||||
* ensure that the compressor never crashes.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "fuzz_helpers.h"
|
||||
#include "zstd.h"
|
||||
|
||||
static ZSTD_CCtx *cctx = NULL;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
{
|
||||
uint32_t seed = FUZZ_seed(&src, &size);
|
||||
size_t const maxSize = ZSTD_compressBound(size);
|
||||
int i;
|
||||
if (!cctx) {
|
||||
cctx = ZSTD_createCCtx();
|
||||
FUZZ_ASSERT(cctx);
|
||||
}
|
||||
/* Run it 10 times over 10 output sizes. Reuse the context. */
|
||||
for (i = 0; i < 10; ++i) {
|
||||
int const level = (int)FUZZ_rand32(&seed, 0, 19 + 3) - 3; /* [-3, 19] */
|
||||
size_t const bufSize = FUZZ_rand32(&seed, 0, maxSize);
|
||||
void* rBuf = malloc(bufSize);
|
||||
FUZZ_ASSERT(rBuf);
|
||||
ZSTD_compressCCtx(cctx, rBuf, bufSize, src, size, level);
|
||||
free(rBuf);
|
||||
}
|
||||
|
||||
#ifndef STATEFUL_FUZZING
|
||||
ZSTD_freeCCtx(cctx); cctx = NULL;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -19,28 +19,24 @@
|
||||
#include "zstd.h"
|
||||
|
||||
static ZSTD_DCtx *dctx = NULL;
|
||||
static void* rBuf = NULL;
|
||||
static size_t bufSize = 0;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
{
|
||||
size_t neededBufSize;
|
||||
|
||||
FUZZ_seed(&src, &size);
|
||||
neededBufSize = MAX(20 * size, (size_t)256 << 10);
|
||||
|
||||
/* Allocate all buffers and contexts if not already allocated */
|
||||
if (neededBufSize > bufSize) {
|
||||
free(rBuf);
|
||||
rBuf = malloc(neededBufSize);
|
||||
bufSize = neededBufSize;
|
||||
FUZZ_ASSERT(rBuf);
|
||||
}
|
||||
uint32_t seed = FUZZ_seed(&src, &size);
|
||||
int i;
|
||||
if (!dctx) {
|
||||
dctx = ZSTD_createDCtx();
|
||||
FUZZ_ASSERT(dctx);
|
||||
}
|
||||
ZSTD_decompressDCtx(dctx, rBuf, neededBufSize, src, size);
|
||||
/* Run it 10 times over 10 output sizes. Reuse the context. */
|
||||
for (i = 0; i < 10; ++i) {
|
||||
size_t const bufSize = FUZZ_rand32(&seed, 0, 2 * size);
|
||||
void* rBuf = malloc(bufSize);
|
||||
FUZZ_ASSERT(rBuf);
|
||||
ZSTD_decompressDCtx(dctx, rBuf, bufSize, src, size);
|
||||
free(rBuf);
|
||||
}
|
||||
|
||||
#ifndef STATEFUL_FUZZING
|
||||
ZSTD_freeDCtx(dctx); dctx = NULL;
|
||||
|
||||
@@ -25,9 +25,6 @@ static const int kMaxClevel = 19;
|
||||
|
||||
static ZSTD_CCtx *cctx = NULL;
|
||||
static ZSTD_DCtx *dctx = NULL;
|
||||
static void* cBuf = NULL;
|
||||
static void* rBuf = NULL;
|
||||
static size_t bufSize = 0;
|
||||
static uint32_t seed;
|
||||
|
||||
static size_t roundTripTest(void *result, size_t resultCapacity,
|
||||
@@ -36,16 +33,8 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
|
||||
{
|
||||
size_t cSize;
|
||||
if (FUZZ_rand(&seed) & 1) {
|
||||
ZSTD_inBuffer in = {src, srcSize, 0};
|
||||
ZSTD_outBuffer out = {compressed, compressedCapacity, 0};
|
||||
size_t err;
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
||||
FUZZ_setRandomParameters(cctx, srcSize, &seed);
|
||||
err = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);
|
||||
FUZZ_ZASSERT(err);
|
||||
FUZZ_ASSERT(err == 0);
|
||||
cSize = out.pos;
|
||||
cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);
|
||||
} else {
|
||||
int const cLevel = FUZZ_rand(&seed) % kMaxClevel;
|
||||
cSize = ZSTD_compressCCtx(
|
||||
@@ -57,20 +46,21 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
{
|
||||
size_t neededBufSize;
|
||||
size_t const rBufSize = size;
|
||||
void* rBuf = malloc(rBufSize);
|
||||
size_t cBufSize = ZSTD_compressBound(size);
|
||||
void* cBuf;
|
||||
|
||||
seed = FUZZ_seed(&src, &size);
|
||||
neededBufSize = ZSTD_compressBound(size);
|
||||
/* Half of the time fuzz with a 1 byte smaller output size.
|
||||
* This will still succeed because we don't use a dictionary, so the dictID
|
||||
* field is empty, giving us 4 bytes of overhead.
|
||||
*/
|
||||
cBufSize -= FUZZ_rand32(&seed, 0, 1);
|
||||
cBuf = malloc(cBufSize);
|
||||
|
||||
FUZZ_ASSERT(cBuf && rBuf);
|
||||
|
||||
/* Allocate all buffers and contexts if not already allocated */
|
||||
if (neededBufSize > bufSize) {
|
||||
free(cBuf);
|
||||
free(rBuf);
|
||||
cBuf = malloc(neededBufSize);
|
||||
rBuf = malloc(neededBufSize);
|
||||
bufSize = neededBufSize;
|
||||
FUZZ_ASSERT(cBuf && rBuf);
|
||||
}
|
||||
if (!cctx) {
|
||||
cctx = ZSTD_createCCtx();
|
||||
FUZZ_ASSERT(cctx);
|
||||
@@ -82,11 +72,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
|
||||
{
|
||||
size_t const result =
|
||||
roundTripTest(rBuf, neededBufSize, cBuf, neededBufSize, src, size);
|
||||
roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size);
|
||||
FUZZ_ZASSERT(result);
|
||||
FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size");
|
||||
FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!");
|
||||
}
|
||||
free(rBuf);
|
||||
free(cBuf);
|
||||
#ifndef STATEFUL_FUZZING
|
||||
ZSTD_freeCCtx(cctx); cctx = NULL;
|
||||
ZSTD_freeDCtx(dctx); dctx = NULL;
|
||||
|
||||
@@ -62,9 +62,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
if (!dstream) {
|
||||
dstream = ZSTD_createDStream();
|
||||
FUZZ_ASSERT(dstream);
|
||||
FUZZ_ASSERT(!ZSTD_isError(ZSTD_initDStream(dstream)));
|
||||
} else {
|
||||
FUZZ_ASSERT(!ZSTD_isError(ZSTD_resetDStream(dstream)));
|
||||
FUZZ_ZASSERT(ZSTD_DCtx_reset(dstream, ZSTD_reset_session_only));
|
||||
}
|
||||
|
||||
while (size > 0) {
|
||||
@@ -73,7 +72,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
ZSTD_outBuffer out = makeOutBuffer();
|
||||
size_t const rc = ZSTD_decompressStream(dstream, &out, &in);
|
||||
if (ZSTD_isError(rc)) goto error;
|
||||
if (rc == 0) FUZZ_ASSERT(!ZSTD_isError(ZSTD_resetDStream(dstream)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ static size_t compress(uint8_t *dst, size_t capacity,
|
||||
ZSTD_inBuffer in = makeInBuffer(&src, &srcSize);
|
||||
/* Mode controls the action. If mode == -1 we pick a new mode */
|
||||
int mode = -1;
|
||||
while (in.pos < in.size) {
|
||||
while (in.pos < in.size || mode != -1) {
|
||||
ZSTD_outBuffer out = makeOutBuffer(dst, capacity);
|
||||
/* Previous action finished, pick a new mode. */
|
||||
if (mode == -1) mode = FUZZ_rand(&seed) % 10;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
/**
|
||||
* This fuzz target fuzzes all of the helper functions that consume compressed
|
||||
* input.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "fuzz_helpers.h"
|
||||
#include "zstd_helpers.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
{
|
||||
ZSTD_frameHeader zfh;
|
||||
/* Consume the seed to be compatible with the corpora of other decompression
|
||||
* fuzzers.
|
||||
*/
|
||||
FUZZ_seed(&src, &size);
|
||||
/* You can fuzz any helper functions here that are fast, and take zstd
|
||||
* compressed data as input. E.g. don't expect the input to be a dictionary,
|
||||
* so don't fuzz ZSTD_getDictID_fromDict().
|
||||
*/
|
||||
ZSTD_getFrameContentSize(src, size);
|
||||
ZSTD_getDecompressedSize(src, size);
|
||||
ZSTD_findFrameCompressedSize(src, size);
|
||||
ZSTD_getDictID_fromFrame(src, size);
|
||||
ZSTD_findDecompressedSize(src, size);
|
||||
ZSTD_decompressBound(src, size);
|
||||
ZSTD_frameHeaderSize(src, size);
|
||||
ZSTD_isFrame(src, size);
|
||||
ZSTD_getFrameHeader(&zfh, src, size);
|
||||
ZSTD_getFrameHeader_advanced(&zfh, src, size, ZSTD_f_zstd1);
|
||||
return 0;
|
||||
}
|
||||
@@ -8,10 +8,14 @@
|
||||
*/
|
||||
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
#define ZDICT_STATIC_LINKING_ONLY
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "zstd_helpers.h"
|
||||
#include "fuzz_helpers.h"
|
||||
#include "zstd.h"
|
||||
#include "zdict.h"
|
||||
|
||||
static void set(ZSTD_CCtx *cctx, ZSTD_cParameter param, int value)
|
||||
{
|
||||
@@ -71,8 +75,7 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, uint32_t *state)
|
||||
setRand(cctx, ZSTD_c_contentSizeFlag, 0, 1, state);
|
||||
setRand(cctx, ZSTD_c_checksumFlag, 0, 1, state);
|
||||
setRand(cctx, ZSTD_c_dictIDFlag, 0, 1, state);
|
||||
setRand(cctx, ZSTD_c_forceAttachDict, 0, 2, state);
|
||||
/* Select long distance matchig parameters */
|
||||
/* Select long distance matching parameters */
|
||||
setRand(cctx, ZSTD_c_enableLongDistanceMatching, 0, 1, state);
|
||||
setRand(cctx, ZSTD_c_ldmHashLog, ZSTD_HASHLOG_MIN, 16, state);
|
||||
setRand(cctx, ZSTD_c_ldmMinMatch, ZSTD_LDM_MINMATCH_MIN,
|
||||
@@ -81,4 +84,54 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, uint32_t *state)
|
||||
state);
|
||||
setRand(cctx, ZSTD_c_ldmHashRateLog, ZSTD_LDM_HASHRATELOG_MIN,
|
||||
ZSTD_LDM_HASHRATELOG_MAX, state);
|
||||
/* Set misc parameters */
|
||||
setRand(cctx, ZSTD_c_nbWorkers, 0, 2, state);
|
||||
setRand(cctx, ZSTD_c_rsyncable, 0, 1, state);
|
||||
setRand(cctx, ZSTD_c_forceMaxWindow, 0, 1, state);
|
||||
setRand(cctx, ZSTD_c_literalCompressionMode, 0, 2, state);
|
||||
setRand(cctx, ZSTD_c_forceAttachDict, 0, 2, state);
|
||||
}
|
||||
|
||||
FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, uint32_t *state)
|
||||
{
|
||||
size_t const dictSize = MAX(srcSize / 8, 1024);
|
||||
size_t const totalSampleSize = dictSize * 11;
|
||||
FUZZ_dict_t dict = { malloc(dictSize), dictSize };
|
||||
char* const samples = (char*)malloc(totalSampleSize);
|
||||
unsigned nbSamples = 100;
|
||||
size_t* const samplesSizes = (size_t*)malloc(sizeof(size_t) * nbSamples);
|
||||
size_t pos = 0;
|
||||
size_t sample = 0;
|
||||
ZDICT_fastCover_params_t params;
|
||||
FUZZ_ASSERT(dict.buff && samples && samplesSizes);
|
||||
|
||||
for (sample = 0; sample < nbSamples; ++sample) {
|
||||
size_t const remaining = totalSampleSize - pos;
|
||||
size_t const offset = FUZZ_rand32(state, 0, MAX(srcSize, 1) - 1);
|
||||
size_t const limit = MIN(srcSize - offset, remaining);
|
||||
size_t const toCopy = MIN(limit, remaining / (nbSamples - sample));
|
||||
memcpy(samples + pos, src + offset, toCopy);
|
||||
pos += toCopy;
|
||||
samplesSizes[sample] = toCopy;
|
||||
|
||||
}
|
||||
memset(samples + pos, 0, totalSampleSize - pos);
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.accel = 5;
|
||||
params.k = 40;
|
||||
params.d = 8;
|
||||
params.f = 14;
|
||||
params.zParams.compressionLevel = 1;
|
||||
dict.size = ZDICT_trainFromBuffer_fastCover(dict.buff, dictSize,
|
||||
samples, samplesSizes, nbSamples, params);
|
||||
if (ZSTD_isError(dict.size)) {
|
||||
free(dict.buff);
|
||||
memset(&dict, 0, sizeof(dict));
|
||||
}
|
||||
|
||||
free(samplesSizes);
|
||||
free(samples);
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#ifndef ZSTD_HELPERS_H
|
||||
#define ZSTD_HELPERS_H
|
||||
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
|
||||
#include "zstd.h"
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -27,6 +29,17 @@ ZSTD_compressionParameters FUZZ_randomCParams(size_t srcSize, uint32_t *state);
|
||||
ZSTD_frameParameters FUZZ_randomFParams(uint32_t *state);
|
||||
ZSTD_parameters FUZZ_randomParams(size_t srcSize, uint32_t *state);
|
||||
|
||||
typedef struct {
|
||||
void* buff;
|
||||
size_t size;
|
||||
} FUZZ_dict_t;
|
||||
|
||||
/* Quickly train a dictionary from a source for fuzzing.
|
||||
* NOTE: Don't use this to train production dictionaries, it is only optimized
|
||||
* for speed, and doesn't care about dictionary quality.
|
||||
*/
|
||||
FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, uint32_t *state);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+341
-23
@@ -38,6 +38,7 @@
|
||||
#define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
||||
#include "xxhash.h" /* XXH64 */
|
||||
#include "util.h"
|
||||
#include "timefn.h" /* SEC_TO_MICRO, UTIL_time_t, UTIL_TIME_INITIALIZER, UTIL_clockSpanMicro, UTIL_getTime */
|
||||
|
||||
|
||||
/*-************************************
|
||||
@@ -61,10 +62,12 @@ static U32 g_displayLevel = 2;
|
||||
static const U64 g_refreshRate = SEC_TO_MICRO / 6;
|
||||
static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
|
||||
|
||||
#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
|
||||
if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \
|
||||
{ g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \
|
||||
if (g_displayLevel>=4) fflush(stderr); } }
|
||||
#define DISPLAYUPDATE(l, ...) \
|
||||
if (g_displayLevel>=l) { \
|
||||
if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \
|
||||
{ g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \
|
||||
if (g_displayLevel>=4) fflush(stderr); } \
|
||||
}
|
||||
|
||||
|
||||
/*-*******************************************************
|
||||
@@ -72,7 +75,7 @@ static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
|
||||
*********************************************************/
|
||||
#undef MIN
|
||||
#undef MAX
|
||||
/* Declaring the function is it isn't unused */
|
||||
/* Declaring the function, to avoid -Wmissing-prototype */
|
||||
void FUZ_bug976(void);
|
||||
void FUZ_bug976(void)
|
||||
{ /* these constants shall not depend on MIN() macro */
|
||||
@@ -124,12 +127,14 @@ static U32 FUZ_highbit32(U32 v32)
|
||||
#define CHECK(fn) { CHECK_V(err, fn); }
|
||||
#define CHECKPLUS(var, fn, more) { CHECK_V(var, fn); more; }
|
||||
|
||||
#define CHECK_EQ(lhs, rhs) { \
|
||||
if ((lhs) != (rhs)) { \
|
||||
DISPLAY("Error L%u => %s != %s ", __LINE__, #lhs, #rhs); \
|
||||
#define CHECK_OP(op, lhs, rhs) { \
|
||||
if (!((lhs) op (rhs))) { \
|
||||
DISPLAY("Error L%u => FAILED %s %s %s ", __LINE__, #lhs, #op, #rhs); \
|
||||
goto _output_error; \
|
||||
} \
|
||||
}
|
||||
#define CHECK_EQ(lhs, rhs) CHECK_OP(==, lhs, rhs)
|
||||
#define CHECK_LT(lhs, rhs) CHECK_OP(<, lhs, rhs)
|
||||
|
||||
|
||||
/*=============================================
|
||||
@@ -244,7 +249,7 @@ static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsig
|
||||
|
||||
/* advanced MT streaming API test */
|
||||
if (part <= 4)
|
||||
{ unsigned nbThreads;
|
||||
{ int nbThreads;
|
||||
for (nbThreads=1; nbThreads<=4; nbThreads++) {
|
||||
int compressionLevel;
|
||||
for (compressionLevel=1; compressionLevel<=6; compressionLevel++) {
|
||||
@@ -258,7 +263,7 @@ static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsig
|
||||
CHECK_Z( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue) );
|
||||
while ( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) ) {}
|
||||
ZSTD_freeCCtx(cctx);
|
||||
DISPLAYLEVEL(3, "compress_generic,-T%u,continue level %i : ",
|
||||
DISPLAYLEVEL(3, "compress_generic,-T%i,continue level %i : ",
|
||||
nbThreads, compressionLevel);
|
||||
FUZ_displayMallocStats(malcount);
|
||||
} } }
|
||||
@@ -374,6 +379,20 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : tight ZSTD_decompressBound test : ", testNb++);
|
||||
{
|
||||
unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize);
|
||||
if (bound != CNBuffSize) goto _output_error;
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with invalid srcSize : ", testNb++);
|
||||
{
|
||||
unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize - 1);
|
||||
if (bound != ZSTD_CONTENTSIZE_ERROR) goto _output_error;
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize);
|
||||
{ size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);
|
||||
if (r != CNBuffSize) goto _output_error; }
|
||||
@@ -429,6 +448,27 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; }
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with content size missing : ", testNb++);
|
||||
{ /* create compressed buffer with content size missing */
|
||||
ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
||||
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0) );
|
||||
CHECKPLUS(r, ZSTD_compress2(cctx,
|
||||
compressedBuffer, compressedBufferSize,
|
||||
CNBuffer, CNBuffSize),
|
||||
cSize=r );
|
||||
ZSTD_freeCCtx(cctx);
|
||||
}
|
||||
{ /* ensure frame content size is missing */
|
||||
ZSTD_frameHeader zfh;
|
||||
size_t const ret = ZSTD_getFrameHeader(&zfh, compressedBuffer, compressedBufferSize);
|
||||
if (ret != 0 || zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error;
|
||||
}
|
||||
{ /* ensure CNBuffSize <= decompressBound */
|
||||
unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, compressedBufferSize);
|
||||
if (CNBuffSize > bound) goto _output_error;
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3d : check CCtx size after compressing empty input : ", testNb++);
|
||||
{ ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
size_t const r = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 19);
|
||||
@@ -730,13 +770,11 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : init CCtx for small level %u (should work again) : ", testNb++, 1);
|
||||
{ size_t const r = ZSTD_compressBegin(staticCCtx, 1);
|
||||
if (ZSTD_isError(r)) goto _output_error; }
|
||||
CHECK( ZSTD_compressBegin(staticCCtx, 1) );
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : init CStream for small level %u : ", testNb++, 1);
|
||||
{ size_t const r = ZSTD_initCStream(staticCCtx, 1);
|
||||
if (ZSTD_isError(r)) goto _output_error; }
|
||||
CHECK( ZSTD_initCStream(staticCCtx, 1) );
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : init CStream with dictionary (should fail) : ", testNb++);
|
||||
@@ -828,6 +866,59 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
ZSTDMT_freeCCtx(mtctx);
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : compress -T2 with/without literals compression : ", testNb++)
|
||||
{ ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
||||
size_t cSize1, cSize2;
|
||||
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
|
||||
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2) );
|
||||
cSize1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
|
||||
CHECK(cSize1);
|
||||
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_literalCompressionMode, ZSTD_lcm_uncompressed) );
|
||||
cSize2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
|
||||
CHECK(cSize2);
|
||||
CHECK_LT(cSize1, cSize2);
|
||||
ZSTD_freeCCtx(cctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Multithreaded ZSTD_compress2() with rsyncable : ", testNb++)
|
||||
{ ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
||||
/* Set rsyncable and don't give the ZSTD_compressBound(CNBuffSize) so
|
||||
* ZSTDMT is forced to not take the shortcut.
|
||||
*/
|
||||
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
|
||||
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1) );
|
||||
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_rsyncable, 1) );
|
||||
CHECK( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize - 1, CNBuffer, CNBuffSize) );
|
||||
ZSTD_freeCCtx(cctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : setting multithreaded parameters : ", testNb++)
|
||||
{ ZSTD_CCtx_params* params = ZSTD_createCCtxParams();
|
||||
int value;
|
||||
/* Check that the overlap log and job size are unset. */
|
||||
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
|
||||
CHECK_EQ(value, 0);
|
||||
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
|
||||
CHECK_EQ(value, 0);
|
||||
/* Set and check the overlap log and job size. */
|
||||
CHECK( ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, 5) );
|
||||
CHECK( ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, 2 MB) );
|
||||
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
|
||||
CHECK_EQ(value, 5);
|
||||
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
|
||||
CHECK_EQ(value, 2 MB);
|
||||
/* Set the number of workers and check the overlap log and job size. */
|
||||
CHECK( ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, 2) );
|
||||
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
|
||||
CHECK_EQ(value, 5);
|
||||
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
|
||||
CHECK_EQ(value, 2 MB);
|
||||
ZSTD_freeCCtxParams(params);
|
||||
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
/* Simple API multiframe test */
|
||||
DISPLAYLEVEL(3, "test%3i : compress multiple frames : ", testNb++);
|
||||
@@ -859,6 +950,11 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
if (r != CNBuffSize / 2) goto _output_error; }
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : get tight decompressed bound of multiple frames : ", testNb++);
|
||||
{ unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, cSize);
|
||||
if (bound != CNBuffSize / 2) goto _output_error; }
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : decompress multiple frames : ", testNb++);
|
||||
{ CHECK_V(r, ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize));
|
||||
if (r != CNBuffSize / 2) goto _output_error; }
|
||||
@@ -963,7 +1059,7 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
/* Dictionary and dictBuilder tests */
|
||||
{ ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
size_t const dictBufferCapacity = 16 KB;
|
||||
void* dictBuffer = malloc(dictBufferCapacity);
|
||||
void* const dictBuffer = malloc(dictBufferCapacity);
|
||||
size_t const totalSampleSize = 1 MB;
|
||||
size_t const sampleUnitSize = 8 KB;
|
||||
U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize);
|
||||
@@ -1008,6 +1104,22 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : COVER dictBuilder with shrinkDict: ", testNb++);
|
||||
{ U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
|
||||
{ ZDICT_cover_params_t coverParams;
|
||||
memset(&coverParams, 0, sizeof(coverParams));
|
||||
coverParams.steps = 8;
|
||||
coverParams.nbThreads = 4;
|
||||
coverParams.shrinkDict = 1;
|
||||
coverParams.shrinkDictMaxRegression = 1;
|
||||
dictSize = ZDICT_optimizeTrainFromBuffer_cover(
|
||||
dictBuffer, dictBufferCapacity,
|
||||
CNBuffer, samplesSizes, nbSamples/8, /* less samples for faster tests */
|
||||
&coverParams);
|
||||
if (ZDICT_isError(dictSize)) goto _output_error;
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Multithreaded FASTCOVER dictBuilder : ", testNb++);
|
||||
{ U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
|
||||
{ ZDICT_fastCover_params_t fastCoverParams;
|
||||
@@ -1022,6 +1134,22 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : FASTCOVER dictBuilder with shrinkDict: ", testNb++);
|
||||
{ U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
|
||||
{ ZDICT_fastCover_params_t fastCoverParams;
|
||||
memset(&fastCoverParams, 0, sizeof(fastCoverParams));
|
||||
fastCoverParams.steps = 8;
|
||||
fastCoverParams.nbThreads = 4;
|
||||
fastCoverParams.shrinkDict = 1;
|
||||
fastCoverParams.shrinkDictMaxRegression = 1;
|
||||
dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(
|
||||
dictBuffer, dictBufferCapacity,
|
||||
CNBuffer, samplesSizes, nbSamples,
|
||||
&fastCoverParams);
|
||||
if (ZDICT_isError(dictSize)) goto _output_error;
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize);
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : check dictID : ", testNb++);
|
||||
dictID = ZDICT_getDictID(dictBuffer, dictSize);
|
||||
if (dictID==0) goto _output_error;
|
||||
@@ -1068,6 +1196,7 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize,
|
||||
ZSTD_dlm_byRef, ZSTD_dct_auto,
|
||||
cParams, ZSTD_defaultCMem);
|
||||
assert(cdict != NULL);
|
||||
DISPLAYLEVEL(3, "(size : %u) : ", (unsigned)ZSTD_sizeof_CDict(cdict));
|
||||
cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize,
|
||||
CNBuffer, CNBuffSize, cdict);
|
||||
@@ -1125,8 +1254,11 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
{ ZSTD_frameParameters const fParams = { 0 /* frameSize */, 1 /* checksum */, 1 /* noDictID*/ };
|
||||
ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);
|
||||
ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem);
|
||||
cSize = ZSTD_compress_usingCDict_advanced(cctx, compressedBuffer, compressedBufferSize,
|
||||
CNBuffer, CNBuffSize, cdict, fParams);
|
||||
assert(cdict != NULL);
|
||||
cSize = ZSTD_compress_usingCDict_advanced(cctx,
|
||||
compressedBuffer, compressedBufferSize,
|
||||
CNBuffer, CNBuffSize,
|
||||
cdict, fParams);
|
||||
ZSTD_freeCDict(cdict);
|
||||
if (ZSTD_isError(cSize)) goto _output_error;
|
||||
}
|
||||
@@ -1139,7 +1271,8 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
DISPLAYLEVEL(3, "OK (unknown)\n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : frame built without dictID should be decompressible : ", testNb++);
|
||||
{ ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);
|
||||
{ ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||
assert(dctx != NULL);
|
||||
CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,
|
||||
decodedBuffer, CNBuffSize,
|
||||
compressedBuffer, cSize,
|
||||
@@ -1203,9 +1336,13 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
{
|
||||
size_t ret;
|
||||
MEM_writeLE32((char*)dictBuffer+2, ZSTD_MAGIC_DICTIONARY);
|
||||
/* Either operation is allowed to fail, but one must fail. */
|
||||
ret = ZSTD_CCtx_loadDictionary_advanced(
|
||||
cctx, (const char*)dictBuffer+2, dictSize-2, ZSTD_dlm_byRef, ZSTD_dct_auto);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
if (!ZSTD_isError(ret)) {
|
||||
ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100));
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
}
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
@@ -1216,6 +1353,187 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
ret = ZSTD_CCtx_loadDictionary_advanced(
|
||||
cctx, (const char*)dictBuffer+2, dictSize-2, ZSTD_dlm_byRef, ZSTD_dct_rawContent);
|
||||
if (ZSTD_isError(ret)) goto _output_error;
|
||||
ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100));
|
||||
if (ZSTD_isError(ret)) goto _output_error;
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_CCtx_refCDict() then set parameters : ", testNb++);
|
||||
{ ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, dictSize, 1);
|
||||
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
|
||||
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 ));
|
||||
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
|
||||
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
|
||||
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 ));
|
||||
ZSTD_freeCDict(cdict);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Loading dictionary before setting parameters is the same as loading after : ", testNb++);
|
||||
{
|
||||
size_t size1, size2;
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) );
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
|
||||
size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
|
||||
if (ZSTD_isError(size1)) goto _output_error;
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
|
||||
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) );
|
||||
size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
|
||||
if (ZSTD_isError(size2)) goto _output_error;
|
||||
|
||||
if (size1 != size2) goto _output_error;
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the prefix : ", testNb++);
|
||||
{
|
||||
CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
|
||||
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the cdict : ", testNb++);
|
||||
{
|
||||
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
|
||||
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
|
||||
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
|
||||
ZSTD_freeCDict(cdict);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the prefix : ", testNb++);
|
||||
{
|
||||
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
|
||||
CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
|
||||
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
|
||||
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
|
||||
ZSTD_freeCDict(cdict);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the dictionary : ", testNb++);
|
||||
{
|
||||
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
|
||||
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
|
||||
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
|
||||
ZSTD_freeCDict(cdict);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the dictionary : ", testNb++);
|
||||
{
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
|
||||
CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
|
||||
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the cdict : ", testNb++);
|
||||
{
|
||||
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
|
||||
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
|
||||
CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
|
||||
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
|
||||
ZSTD_freeCDict(cdict);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Loaded dictionary persists across reset session : ", testNb++);
|
||||
{
|
||||
size_t size1, size2;
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
|
||||
size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
|
||||
if (ZSTD_isError(size1)) goto _output_error;
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
||||
size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
|
||||
if (ZSTD_isError(size2)) goto _output_error;
|
||||
|
||||
if (size1 != size2) goto _output_error;
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : Loaded dictionary is cleared after resetting parameters : ", testNb++);
|
||||
{
|
||||
size_t size1, size2;
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
|
||||
size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
|
||||
if (ZSTD_isError(size1)) goto _output_error;
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
|
||||
if (ZSTD_isError(size2)) goto _output_error;
|
||||
|
||||
if (size1 == size2) goto _output_error;
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, dictBuffer, dictSize) );
|
||||
cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
|
||||
CHECK_Z(cSize);
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with dictionary : ", testNb++);
|
||||
{
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
size_t ret;
|
||||
/* We should fail to decompress without a dictionary. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
/* We should succeed to decompress with the dictionary. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictSize) );
|
||||
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
|
||||
/* The dictionary should presist across calls. */
|
||||
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
|
||||
/* When we reset the context the dictionary is cleared. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
ZSTD_freeDCtx(dctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with ddict : ", testNb++);
|
||||
{
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
ZSTD_DDict* ddict = ZSTD_createDDict(dictBuffer, dictSize);
|
||||
size_t ret;
|
||||
/* We should succeed to decompress with the ddict. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddict) );
|
||||
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
|
||||
/* The ddict should presist across calls. */
|
||||
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
|
||||
/* When we reset the context the ddict is cleared. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
ZSTD_freeDCtx(dctx);
|
||||
ZSTD_freeDDict(ddict);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with prefix : ", testNb++);
|
||||
{
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
size_t ret;
|
||||
/* We should succeed to decompress with the prefix. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_DCtx_refPrefix_advanced(dctx, dictBuffer, dictSize, ZSTD_dct_auto) );
|
||||
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
|
||||
/* The prefix should be cleared after the first compression. */
|
||||
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
ZSTD_freeDCtx(dctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
@@ -2178,7 +2496,7 @@ static unsigned readU32FromChar(const char** stringPtr)
|
||||
* If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
|
||||
* @return 0 and doesn't modify *stringPtr otherwise.
|
||||
*/
|
||||
static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
|
||||
static int longCommandWArg(const char** stringPtr, const char* longCommand)
|
||||
{
|
||||
size_t const comSize = strlen(longCommand);
|
||||
int const result = !strncmp(*stringPtr, longCommand, comSize);
|
||||
@@ -2238,7 +2556,7 @@ int main(int argc, const char** argv)
|
||||
|
||||
case 'i':
|
||||
argument++; maxDuration = 0;
|
||||
nbTests = readU32FromChar(&argument);
|
||||
nbTests = (int)readU32FromChar(&argument);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
@@ -2258,12 +2576,12 @@ int main(int argc, const char** argv)
|
||||
|
||||
case 't':
|
||||
argument++;
|
||||
testNb = readU32FromChar(&argument);
|
||||
testNb = (int)readU32FromChar(&argument);
|
||||
break;
|
||||
|
||||
case 'P': /* compressibility % */
|
||||
argument++;
|
||||
proba = readU32FromChar(&argument);
|
||||
proba = (int)readU32FromChar(&argument);
|
||||
if (proba>100) proba = 100;
|
||||
break;
|
||||
|
||||
|
||||
+43
-8
@@ -16,10 +16,11 @@
|
||||
/*===========================================
|
||||
* Dependencies
|
||||
*==========================================*/
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <stdio.h> /* fprintf */
|
||||
#include <string.h> /* strlen */
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <stdio.h> /* fprintf */
|
||||
#include <string.h> /* strlen */
|
||||
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_decompressBound */
|
||||
#include "zstd.h"
|
||||
#include "zstd_errors.h"
|
||||
|
||||
@@ -74,6 +75,7 @@ static int testSimpleAPI(void)
|
||||
|
||||
static int testStreamingAPI(void)
|
||||
{
|
||||
int error_code = 0;
|
||||
size_t const outBuffSize = ZSTD_DStreamOutSize();
|
||||
char* const outBuff = malloc(outBuffSize);
|
||||
ZSTD_DStream* const stream = ZSTD_createDStream();
|
||||
@@ -87,6 +89,7 @@ static int testStreamingAPI(void)
|
||||
}
|
||||
if (stream == NULL) {
|
||||
DISPLAY("ERROR: Could not create dstream\n");
|
||||
free(outBuff);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -96,13 +99,15 @@ static int testStreamingAPI(void)
|
||||
size_t const ret = ZSTD_initDStream(stream);
|
||||
if (ZSTD_isError(ret)) {
|
||||
DISPLAY("ERROR: ZSTD_initDStream: %s\n", ZSTD_getErrorName(ret));
|
||||
return 1;
|
||||
error_code = 1;
|
||||
break;
|
||||
} }
|
||||
|
||||
{ size_t const ret = ZSTD_decompressStream(stream, &output, &input);
|
||||
if (ZSTD_isError(ret)) {
|
||||
DISPLAY("ERROR: ZSTD_decompressStream: %s\n", ZSTD_getErrorName(ret));
|
||||
return 1;
|
||||
error_code = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
@@ -111,7 +116,8 @@ static int testStreamingAPI(void)
|
||||
|
||||
if (memcmp(outBuff, EXPECTED + outputPos, output.pos) != 0) {
|
||||
DISPLAY("ERROR: Wrong decoded output produced\n");
|
||||
return 1;
|
||||
error_code = 1;
|
||||
break;
|
||||
}
|
||||
outputPos += output.pos;
|
||||
if (input.pos == input.size && output.pos < output.size) {
|
||||
@@ -121,7 +127,34 @@ static int testStreamingAPI(void)
|
||||
|
||||
free(outBuff);
|
||||
ZSTD_freeDStream(stream);
|
||||
DISPLAY("Streaming API OK\n");
|
||||
if (error_code == 0) DISPLAY("Streaming API OK\n");
|
||||
return error_code;
|
||||
}
|
||||
|
||||
static int testFrameDecoding(void)
|
||||
{
|
||||
if (strlen(EXPECTED) > ZSTD_decompressBound(COMPRESSED, COMPRESSED_SIZE)) {
|
||||
DISPLAY("ERROR: ZSTD_decompressBound: decompressed bound too small\n");
|
||||
return 1;
|
||||
}
|
||||
{ const char* ip = COMPRESSED;
|
||||
size_t remainingSize = COMPRESSED_SIZE;
|
||||
while (1) {
|
||||
size_t frameSize = ZSTD_findFrameCompressedSize(ip, remainingSize);
|
||||
if (ZSTD_isError(frameSize)) {
|
||||
DISPLAY("ERROR: ZSTD_findFrameCompressedSize: %s\n", ZSTD_getErrorName(frameSize));
|
||||
return 1;
|
||||
}
|
||||
if (frameSize > remainingSize) {
|
||||
DISPLAY("ERROR: ZSTD_findFrameCompressedSize: expected frameSize to align with src buffer");
|
||||
return 1;
|
||||
}
|
||||
ip += frameSize;
|
||||
remainingSize -= frameSize;
|
||||
if (remainingSize == 0) break;
|
||||
}
|
||||
}
|
||||
DISPLAY("Frame Decoding OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -131,6 +164,8 @@ int main(void)
|
||||
if (ret) return ret; }
|
||||
{ int const ret = testStreamingAPI();
|
||||
if (ret) return ret; }
|
||||
{ int const ret = testFrameDecoding();
|
||||
if (ret) return ret; }
|
||||
|
||||
DISPLAY("OK\n");
|
||||
return 0;
|
||||
|
||||
+39
-30
@@ -19,6 +19,7 @@
|
||||
#include <math.h> /* log */
|
||||
#include <assert.h>
|
||||
|
||||
#include "timefn.h" /* SEC_TO_MICRO, UTIL_time_t, UTIL_clockSpanMicro, UTIL_clockSpanNano, UTIL_getTime */
|
||||
#include "mem.h"
|
||||
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters, ZSTD_estimateCCtxSize */
|
||||
#include "zstd.h"
|
||||
@@ -141,7 +142,7 @@ static const char* g_shortParamNames[NUM_PARAMS] =
|
||||
/* maps value from { 0 to rangetable[param] - 1 } to valid paramvalues */
|
||||
static U32 rangeMap(varInds_t param, int ind)
|
||||
{
|
||||
ind = MAX(MIN(ind, (int)rangetable[param] - 1), 0);
|
||||
U32 const uind = (U32)MAX(MIN(ind, (int)rangetable[param] - 1), 0);
|
||||
switch(param) {
|
||||
case wlog_ind: /* using default: triggers -Wswitch-enum */
|
||||
case clog_ind:
|
||||
@@ -149,11 +150,11 @@ static U32 rangeMap(varInds_t param, int ind)
|
||||
case slog_ind:
|
||||
case mml_ind:
|
||||
case strt_ind:
|
||||
return mintable[param] + ind;
|
||||
return mintable[param] + uind;
|
||||
case tlen_ind:
|
||||
return tlen_table[ind];
|
||||
return tlen_table[uind];
|
||||
case fadt_ind: /* 0, 1, 2 -> -1, 0, 1 */
|
||||
return ind - 1;
|
||||
return uind - 1;
|
||||
case NUM_PARAMS:
|
||||
default:;
|
||||
}
|
||||
@@ -173,7 +174,7 @@ static int invRangeMap(varInds_t param, U32 value)
|
||||
case slog_ind:
|
||||
case mml_ind:
|
||||
case strt_ind:
|
||||
return value - mintable[param];
|
||||
return (int)(value - mintable[param]);
|
||||
case tlen_ind: /* bin search */
|
||||
{
|
||||
int lo = 0;
|
||||
@@ -493,13 +494,15 @@ static void
|
||||
paramVariation(paramValues_t* ptr, memoTable_t* mtAll, const U32 nbChanges)
|
||||
{
|
||||
paramValues_t p;
|
||||
U32 validated = 0;
|
||||
int validated = 0;
|
||||
while (!validated) {
|
||||
U32 i;
|
||||
p = *ptr;
|
||||
for (i = 0 ; i < nbChanges ; i++) {
|
||||
const U32 changeID = (U32)FUZ_rand(&g_rand) % (mtAll[p.vals[strt_ind]].varLen << 1);
|
||||
paramVaryOnce(mtAll[p.vals[strt_ind]].varArray[changeID >> 1], ((changeID & 1) << 1) - 1, &p);
|
||||
paramVaryOnce(mtAll[p.vals[strt_ind]].varArray[changeID >> 1],
|
||||
(int)((changeID & 1) << 1) - 1,
|
||||
&p);
|
||||
}
|
||||
validated = paramValid(p);
|
||||
}
|
||||
@@ -511,7 +514,7 @@ static paramValues_t randomParams(void)
|
||||
{
|
||||
varInds_t v; paramValues_t p;
|
||||
for(v = 0; v < NUM_PARAMS; v++) {
|
||||
p.vals[v] = rangeMap(v, FUZ_rand(&g_rand) % rangetable[v]);
|
||||
p.vals[v] = rangeMap(v, (int)(FUZ_rand(&g_rand) % rangetable[v]));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -606,8 +609,8 @@ compareResultLT(const BMK_benchResult_t result1, const BMK_benchResult_t result2
|
||||
|
||||
static constraint_t relaxTarget(constraint_t target) {
|
||||
target.cMem = (U32)-1;
|
||||
target.cSpeed *= ((double)g_strictness) / 100;
|
||||
target.dSpeed *= ((double)g_strictness) / 100;
|
||||
target.cSpeed = (target.cSpeed * g_strictness) / 100;
|
||||
target.dSpeed = (target.dSpeed * g_strictness) / 100;
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -1232,7 +1235,7 @@ static int createBuffersFromMemory(buffers_t* buff, void * srcBuffer, const size
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* allocates buffer's arguments. returns success / failuere */
|
||||
/* allocates buffer's arguments. returns success / failure */
|
||||
static int createBuffers(buffers_t* buff, const char* const * const fileNamesTable,
|
||||
size_t nbFiles) {
|
||||
size_t pos = 0;
|
||||
@@ -1505,7 +1508,7 @@ createMemoTableArray(const paramValues_t p,
|
||||
}
|
||||
|
||||
/* Sets pc to random unmeasured set of parameters */
|
||||
/* specifiy strategy */
|
||||
/* specify strategy */
|
||||
static void randomConstrainedParams(paramValues_t* pc, const memoTable_t* memoTableArray, const ZSTD_strategy st)
|
||||
{
|
||||
size_t j;
|
||||
@@ -1570,7 +1573,7 @@ BMK_benchMemInvertible( buffers_t buf, contexts_t ctx,
|
||||
display_params_tested(*comprParams);
|
||||
memset(&bResult, 0, sizeof(bResult));
|
||||
|
||||
/* warmimg up memory */
|
||||
/* warming up memory */
|
||||
for (i = 0; i < buf.nbBlocks; i++) {
|
||||
if (mode != BMK_decodeOnly) {
|
||||
RDG_genBuffer(dstPtrs[i], dstCapacities[i], 0.10, 0.50, 1);
|
||||
@@ -1638,7 +1641,7 @@ BMK_benchMemInvertible( buffers_t buf, contexts_t ctx,
|
||||
return bOut;
|
||||
}
|
||||
{ BMK_runTime_t const rResult = BMK_extract_runTime(cOutcome);
|
||||
bResult.cSpeed = (srcSize * TIMELOOP_NANOSEC) / rResult.nanoSecPerRun;
|
||||
bResult.cSpeed = (unsigned long long)((double)srcSize * TIMELOOP_NANOSEC / rResult.nanoSecPerRun);
|
||||
bResult.cSize = rResult.sumOfReturn;
|
||||
}
|
||||
compressionCompleted = BMK_isCompleted_TimedFn(timeStateCompress);
|
||||
@@ -1656,7 +1659,7 @@ BMK_benchMemInvertible( buffers_t buf, contexts_t ctx,
|
||||
return bOut;
|
||||
}
|
||||
{ BMK_runTime_t const rResult = BMK_extract_runTime(dOutcome);
|
||||
bResult.dSpeed = (srcSize * TIMELOOP_NANOSEC) / rResult.nanoSecPerRun;
|
||||
bResult.dSpeed = (unsigned long long)((double)srcSize * TIMELOOP_NANOSEC / rResult.nanoSecPerRun);
|
||||
}
|
||||
decompressionCompleted = BMK_isCompleted_TimedFn(timeStateDecompress);
|
||||
}
|
||||
@@ -1734,8 +1737,8 @@ static int allBench(BMK_benchResult_t* resultPtr,
|
||||
|
||||
/* optimistic assumption of benchres */
|
||||
{ BMK_benchResult_t resultMax = benchres;
|
||||
resultMax.cSpeed *= uncertaintyConstantC * VARIANCE;
|
||||
resultMax.dSpeed *= uncertaintyConstantD * VARIANCE;
|
||||
resultMax.cSpeed = (unsigned long long)(resultMax.cSpeed * uncertaintyConstantC * VARIANCE);
|
||||
resultMax.dSpeed = (unsigned long long)(resultMax.dSpeed * uncertaintyConstantD * VARIANCE);
|
||||
|
||||
/* disregard infeasible results in feas mode */
|
||||
/* disregard if resultMax < winner in infeas mode */
|
||||
@@ -1989,7 +1992,7 @@ BMK_selectRandomStart( FILE* f,
|
||||
|
||||
/* BMK_generate_cLevelTable() :
|
||||
* test a large number of configurations
|
||||
* and distribute them accross compression levels according to speed conditions.
|
||||
* and distribute them across compression levels according to speed conditions.
|
||||
* display and save all intermediate results into rfName = "grillResults.txt".
|
||||
* the function automatically stops after g_timeLimit_s.
|
||||
* this function cannot error, it directly exit() in case of problem.
|
||||
@@ -2199,7 +2202,9 @@ static winnerInfo_t climbOnce(const constraint_t target,
|
||||
for (offset = -1; offset <= 1; offset += 2) {
|
||||
CHECKTIME(winnerInfo);
|
||||
candidateInfo.params = cparam;
|
||||
paramVaryOnce(mtAll[cparam.vals[strt_ind]].varArray[i], offset, &candidateInfo.params);
|
||||
paramVaryOnce(mtAll[cparam.vals[strt_ind]].varArray[i],
|
||||
offset,
|
||||
&candidateInfo.params);
|
||||
|
||||
if(paramValid(candidateInfo.params)) {
|
||||
int res;
|
||||
@@ -2265,7 +2270,7 @@ static winnerInfo_t climbOnce(const constraint_t target,
|
||||
|
||||
/* Optimizes for a fixed strategy */
|
||||
|
||||
/* flexible parameters: iterations of failed climbing (or if we do non-random, maybe this is when everything is close to visitied)
|
||||
/* flexible parameters: iterations of failed climbing (or if we do non-random, maybe this is when everything is close to visited)
|
||||
weight more on visit for bad results, less on good results/more on later results / ones with more failures.
|
||||
allocate memoTable here.
|
||||
*/
|
||||
@@ -2351,7 +2356,7 @@ static int nextStrategy(const int currentStrategy, const int bestStrategy)
|
||||
* cLevel - compression level to exceed (all solutions must be > lvl in cSpeed + ratio)
|
||||
*/
|
||||
|
||||
static int g_maxTries = 5;
|
||||
static unsigned g_maxTries = 5;
|
||||
#define TRY_DECAY 1
|
||||
|
||||
static int
|
||||
@@ -2424,9 +2429,9 @@ optimizeForSize(const char* const * const fileNamesTable, const size_t nbFiles,
|
||||
}
|
||||
|
||||
g_lvltarget = winner.result;
|
||||
g_lvltarget.cSpeed *= ((double)g_strictness) / 100;
|
||||
g_lvltarget.dSpeed *= ((double)g_strictness) / 100;
|
||||
g_lvltarget.cSize /= ((double)g_strictness) / 100;
|
||||
g_lvltarget.cSpeed = (g_lvltarget.cSpeed * g_strictness) / 100;
|
||||
g_lvltarget.dSpeed = (g_lvltarget.dSpeed * g_strictness) / 100;
|
||||
g_lvltarget.cSize = (g_lvltarget.cSize * 100) / g_strictness;
|
||||
|
||||
target.cSpeed = (U32)g_lvltarget.cSpeed;
|
||||
target.dSpeed = (U32)g_lvltarget.dSpeed;
|
||||
@@ -2561,7 +2566,7 @@ _cleanUp:
|
||||
* @return 0 and doesn't modify *stringPtr otherwise.
|
||||
* from zstdcli.c
|
||||
*/
|
||||
static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
|
||||
static int longCommandWArg(const char** stringPtr, const char* longCommand)
|
||||
{
|
||||
size_t const comSize = strlen(longCommand);
|
||||
int const result = !strncmp(*stringPtr, longCommand, comSize);
|
||||
@@ -2588,7 +2593,10 @@ static unsigned readU32FromChar(const char** stringPtr)
|
||||
while ((**stringPtr >='0') && (**stringPtr <='9')) {
|
||||
unsigned const max = (((unsigned)(-1)) / 10) - 1;
|
||||
if (result > max) errorOut(errorMsg);
|
||||
result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
|
||||
result *= 10;
|
||||
assert(**stringPtr >= '0');
|
||||
result += (unsigned)(**stringPtr - '0');
|
||||
(*stringPtr)++ ;
|
||||
}
|
||||
if ((**stringPtr=='K') || (**stringPtr=='M')) {
|
||||
unsigned const maxK = ((unsigned)(-1)) >> 10;
|
||||
@@ -2726,7 +2734,7 @@ int main(int argc, const char** argv)
|
||||
PARSE_SUB_ARGS("strict=", "stc=", g_strictness);
|
||||
PARSE_SUB_ARGS("maxTries=", "tries=", g_maxTries);
|
||||
PARSE_SUB_ARGS("memoLimitLog=", "memLog=", memoTableLog);
|
||||
if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevelOpt = readU32FromChar(&argument); g_optmode = 1; if (argument[0]==',') { argument++; continue; } else break; }
|
||||
if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevelOpt = (int)readU32FromChar(&argument); g_optmode = 1; if (argument[0]==',') { argument++; continue; } else break; }
|
||||
if (longCommandWArg(&argument, "speedForRatio=") || longCommandWArg(&argument, "speedRatio=")) { g_ratioMultiplier = readDoubleFromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }
|
||||
|
||||
DISPLAY("invalid optimization parameter \n");
|
||||
@@ -2743,7 +2751,7 @@ int main(int argc, const char** argv)
|
||||
g_singleRun = 1;
|
||||
for ( ; ;) {
|
||||
if(parse_params(&argument, &g_params)) { if(argument[0] == ',') { argument++; continue; } else break; }
|
||||
if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevelRun = readU32FromChar(&argument); g_params = emptyParams(); if (argument[0]==',') { argument++; continue; } else break; }
|
||||
if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevelRun = (int)readU32FromChar(&argument); g_params = emptyParams(); if (argument[0]==',') { argument++; continue; } else break; }
|
||||
|
||||
DISPLAY("invalid compression parameter \n");
|
||||
return 1;
|
||||
@@ -2855,7 +2863,7 @@ int main(int argc, const char** argv)
|
||||
continue;
|
||||
case 'L':
|
||||
{ argument++;
|
||||
cLevelRun = readU32FromChar(&argument);
|
||||
cLevelRun = (int)readU32FromChar(&argument);
|
||||
g_params = emptyParams();
|
||||
continue;
|
||||
}
|
||||
@@ -2944,7 +2952,8 @@ int main(int argc, const char** argv)
|
||||
}
|
||||
} else {
|
||||
if (g_optimizer) {
|
||||
result = optimizeForSize(argv+filenamesStart, argc-filenamesStart, dictFileName, target, paramTarget, cLevelOpt, cLevelRun, memoTableLog);
|
||||
assert(filenamesStart < argc);
|
||||
result = optimizeForSize(argv+filenamesStart, (size_t)(argc-filenamesStart), dictFileName, target, paramTarget, cLevelOpt, cLevelRun, memoTableLog);
|
||||
} else {
|
||||
result = benchFiles(argv+filenamesStart, argc-filenamesStart, dictFileName, cLevelRun);
|
||||
}
|
||||
|
||||
+344
-282
@@ -1,7 +1,9 @@
|
||||
#!/bin/sh -e
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
die() {
|
||||
$ECHO "$@" 1>&2
|
||||
println "$@" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -20,7 +22,7 @@ roundTripTest() {
|
||||
fi
|
||||
|
||||
rm -f tmp1 tmp2
|
||||
$ECHO "roundTripTest: ./datagen $1 $proba | $ZSTD -v$cLevel | $ZSTD -d$dLevel"
|
||||
println "roundTripTest: ./datagen $1 $proba | $ZSTD -v$cLevel | $ZSTD -d$dLevel"
|
||||
./datagen $1 $proba | $MD5SUM > tmp1
|
||||
./datagen $1 $proba | $ZSTD --ultra -v$cLevel | $ZSTD -d$dLevel | $MD5SUM > tmp2
|
||||
$DIFF -q tmp1 tmp2
|
||||
@@ -41,7 +43,7 @@ fileRoundTripTest() {
|
||||
fi
|
||||
|
||||
rm -f tmp.zstd tmp.md5.1 tmp.md5.2
|
||||
$ECHO "fileRoundTripTest: ./datagen $1 $local_p > tmp && $ZSTD -v$local_c -c tmp | $ZSTD -d$local_d"
|
||||
println "fileRoundTripTest: ./datagen $1 $local_p > tmp && $ZSTD -v$local_c -c tmp | $ZSTD -d$local_d"
|
||||
./datagen $1 $local_p > tmp
|
||||
< tmp $MD5SUM > tmp.md5.1
|
||||
$ZSTD --ultra -v$local_c -c tmp | $ZSTD -d$local_d | $MD5SUM > tmp.md5.2
|
||||
@@ -49,9 +51,17 @@ fileRoundTripTest() {
|
||||
}
|
||||
|
||||
truncateLastByte() {
|
||||
dd bs=1 count=$(($(wc -c < "$1") - 1)) if="$1" status=none
|
||||
dd bs=1 count=$(($(wc -c < "$1") - 1)) if="$1"
|
||||
}
|
||||
|
||||
println() {
|
||||
printf '%b\n' "${*}"
|
||||
}
|
||||
|
||||
|
||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
PRGDIR="$SCRIPT_DIR/../programs"
|
||||
TESTDIR="$SCRIPT_DIR/../tests"
|
||||
UNAME=$(uname)
|
||||
|
||||
isTerminal=false
|
||||
@@ -86,16 +96,11 @@ case "$UNAME" in
|
||||
SunOS) DIFF="gdiff" ;;
|
||||
esac
|
||||
|
||||
ECHO="echo -e"
|
||||
case "$UNAME" in
|
||||
Darwin) ECHO="echo" ;;
|
||||
esac
|
||||
|
||||
$ECHO "\nStarting playTests.sh isWindows=$isWindows ZSTD='$ZSTD'"
|
||||
println "\nStarting playTests.sh isWindows=$isWindows ZSTD='$ZSTD'"
|
||||
|
||||
[ -n "$ZSTD" ] || die "ZSTD variable must be defined!"
|
||||
|
||||
if [ -n "$(echo hello | $ZSTD -v -T2 2>&1 > $INTOVOID | grep 'multi-threading is disabled')" ]
|
||||
if echo hello | $ZSTD -v -T2 2>&1 > $INTOVOID | grep -q 'multi-threading is disabled'
|
||||
then
|
||||
hasMT=""
|
||||
else
|
||||
@@ -104,124 +109,133 @@ fi
|
||||
|
||||
|
||||
|
||||
$ECHO "\n===> simple tests "
|
||||
println "\n===> simple tests "
|
||||
|
||||
./datagen > tmp
|
||||
$ECHO "test : basic compression "
|
||||
println "test : basic compression "
|
||||
$ZSTD -f tmp # trivial compression case, creates tmp.zst
|
||||
$ECHO "test : basic decompression"
|
||||
println "test : basic decompression"
|
||||
$ZSTD -df tmp.zst # trivial decompression case (overwrites tmp)
|
||||
$ECHO "test : too large compression level => auto-fix"
|
||||
println "test : too large compression level => auto-fix"
|
||||
$ZSTD -99 -f tmp # too large compression level, automatic sized down
|
||||
$ZSTD -5000000000 -f tmp && die "too large numeric value : must fail"
|
||||
$ECHO "test : --fast aka negative compression levels"
|
||||
println "test : --fast aka negative compression levels"
|
||||
$ZSTD --fast -f tmp # == -1
|
||||
$ZSTD --fast=3 -f tmp # == -3
|
||||
$ZSTD --fast=200000 -f tmp # too low compression level, automatic fixed
|
||||
$ZSTD --fast=5000000000 -f tmp && die "too large numeric value : must fail"
|
||||
$ZSTD -c --fast=0 tmp > $INTOVOID && die "--fast must not accept value 0"
|
||||
$ECHO "test : too large numeric argument"
|
||||
println "test : too large numeric argument"
|
||||
$ZSTD --fast=9999999999 -f tmp && die "should have refused numeric value"
|
||||
$ECHO "test : set compression level with environment variable ZSTD_CLEVEL"
|
||||
println "test : set compression level with environment variable ZSTD_CLEVEL"
|
||||
ZSTD_CLEVEL=12 $ZSTD -f tmp # positive compression level
|
||||
ZSTD_CLEVEL=-12 $ZSTD -f tmp # negative compression level
|
||||
ZSTD_CLEVEL=+12 $ZSTD -f tmp # valid: verbose '+' sign
|
||||
ZSTD_CLEVEL= $ZSTD -f tmp # empty env var, warn and revert to default setting
|
||||
ZSTD_CLEVEL='' $ZSTD -f tmp # empty env var, warn and revert to default setting
|
||||
ZSTD_CLEVEL=- $ZSTD -f tmp # malformed env var, warn and revert to default setting
|
||||
ZSTD_CLEVEL=a $ZSTD -f tmp # malformed env var, warn and revert to default setting
|
||||
ZSTD_CLEVEL=+a $ZSTD -f tmp # malformed env var, warn and revert to default setting
|
||||
ZSTD_CLEVEL=3a7 $ZSTD -f tmp # malformed env var, warn and revert to default setting
|
||||
ZSTD_CLEVEL=50000000000 $ZSTD -f tmp # numeric value too large, warn and revert to default setting
|
||||
$ECHO "test : override ZSTD_CLEVEL with command line option"
|
||||
println "test : override ZSTD_CLEVEL with command line option"
|
||||
ZSTD_CLEVEL=12 $ZSTD --fast=3 -f tmp # overridden by command line option
|
||||
$ECHO "test : compress to stdout"
|
||||
println "test : compress to stdout"
|
||||
$ZSTD tmp -c > tmpCompressed
|
||||
$ZSTD tmp --stdout > tmpCompressed # long command format
|
||||
$ECHO "test : compress to named file"
|
||||
println "test : compress to named file"
|
||||
rm tmpCompressed
|
||||
$ZSTD tmp -o tmpCompressed
|
||||
test -f tmpCompressed # file must be created
|
||||
$ECHO "test : -o must be followed by filename (must fail)"
|
||||
println "test : -o must be followed by filename (must fail)"
|
||||
$ZSTD tmp -of tmpCompressed && die "-o must be followed by filename "
|
||||
$ECHO "test : force write, correct order"
|
||||
println "test : force write, correct order"
|
||||
$ZSTD tmp -fo tmpCompressed
|
||||
$ECHO "test : forgotten argument"
|
||||
println "test : forgotten argument"
|
||||
cp tmp tmp2
|
||||
$ZSTD tmp2 -fo && die "-o must be followed by filename "
|
||||
$ECHO "test : implied stdout when input is stdin"
|
||||
$ECHO bob | $ZSTD | $ZSTD -d
|
||||
println "test : implied stdout when input is stdin"
|
||||
println bob | $ZSTD | $ZSTD -d
|
||||
if [ "$isTerminal" = true ]; then
|
||||
$ECHO "test : compressed data to terminal"
|
||||
$ECHO bob | $ZSTD && die "should have refused : compressed data to terminal"
|
||||
$ECHO "test : compressed data from terminal (a hang here is a test fail, zstd is wrongly waiting on data from terminal)"
|
||||
println "test : compressed data to terminal"
|
||||
println bob | $ZSTD && die "should have refused : compressed data to terminal"
|
||||
println "test : compressed data from terminal (a hang here is a test fail, zstd is wrongly waiting on data from terminal)"
|
||||
$ZSTD -d > $INTOVOID && die "should have refused : compressed data from terminal"
|
||||
fi
|
||||
$ECHO "test : null-length file roundtrip"
|
||||
$ECHO -n '' | $ZSTD - --stdout | $ZSTD -d --stdout
|
||||
$ECHO "test : ensure small file doesn't add 3-bytes null block"
|
||||
println "test : null-length file roundtrip"
|
||||
println -n '' | $ZSTD - --stdout | $ZSTD -d --stdout
|
||||
println "test : ensure small file doesn't add 3-bytes null block"
|
||||
./datagen -g1 > tmp1
|
||||
$ZSTD tmp1 -c | wc -c | grep "14"
|
||||
$ZSTD < tmp1 | wc -c | grep "14"
|
||||
$ECHO "test : decompress file with wrong suffix (must fail)"
|
||||
println "test : decompress file with wrong suffix (must fail)"
|
||||
$ZSTD -d tmpCompressed && die "wrong suffix error not detected!"
|
||||
$ZSTD -df tmp && die "should have refused : wrong extension"
|
||||
$ECHO "test : decompress into stdout"
|
||||
println "test : decompress into stdout"
|
||||
$ZSTD -d tmpCompressed -c > tmpResult # decompression using stdout
|
||||
$ZSTD --decompress tmpCompressed -c > tmpResult
|
||||
$ZSTD --decompress tmpCompressed --stdout > tmpResult
|
||||
$ECHO "test : decompress from stdin into stdout"
|
||||
println "test : decompress from stdin into stdout"
|
||||
$ZSTD -dc < tmp.zst > $INTOVOID # combine decompression, stdin & stdout
|
||||
$ZSTD -dc - < tmp.zst > $INTOVOID
|
||||
$ZSTD -d < tmp.zst > $INTOVOID # implicit stdout when stdin is used
|
||||
$ZSTD -d - < tmp.zst > $INTOVOID
|
||||
$ECHO "test : impose memory limitation (must fail)"
|
||||
println "test : impose memory limitation (must fail)"
|
||||
$ZSTD -d -f tmp.zst -M2K -c > $INTOVOID && die "decompression needs more memory than allowed"
|
||||
$ZSTD -d -f tmp.zst --memlimit=2K -c > $INTOVOID && die "decompression needs more memory than allowed" # long command
|
||||
$ZSTD -d -f tmp.zst --memory=2K -c > $INTOVOID && die "decompression needs more memory than allowed" # long command
|
||||
$ZSTD -d -f tmp.zst --memlimit-decompress=2K -c > $INTOVOID && die "decompression needs more memory than allowed" # long command
|
||||
$ECHO "test : overwrite protection"
|
||||
println "test : overwrite protection"
|
||||
$ZSTD -q tmp && die "overwrite check failed!"
|
||||
$ECHO "test : force overwrite"
|
||||
println "test : force overwrite"
|
||||
$ZSTD -q -f tmp
|
||||
$ZSTD -q --force tmp
|
||||
$ECHO "test : overwrite readonly file"
|
||||
println "test : overwrite readonly file"
|
||||
rm -f tmpro tmpro.zst
|
||||
$ECHO foo > tmpro.zst
|
||||
$ECHO foo > tmpro
|
||||
println foo > tmpro.zst
|
||||
println foo > tmpro
|
||||
chmod 400 tmpro.zst
|
||||
$ZSTD -q tmpro && die "should have refused to overwrite read-only file"
|
||||
$ZSTD -q -f tmpro
|
||||
$ECHO "test: --no-progress flag"
|
||||
println "test: --no-progress flag"
|
||||
$ZSTD tmpro -c --no-progress | $ZSTD -d -f -o "$INTOVOID" --no-progress
|
||||
$ZSTD tmpro -cv --no-progress | $ZSTD -dv -f -o "$INTOVOID" --no-progress
|
||||
rm -f tmpro tmpro.zst
|
||||
$ECHO "test: overwrite input file (must fail)"
|
||||
println "test: overwrite input file (must fail)"
|
||||
$ZSTD tmp -fo tmp && die "zstd compression overwrote the input file"
|
||||
$ZSTD tmp.zst -dfo tmp.zst && die "zstd decompression overwrote the input file"
|
||||
$ECHO "test: detect that input file does not exist"
|
||||
println "test: detect that input file does not exist"
|
||||
$ZSTD nothere && die "zstd hasn't detected that input file does not exist"
|
||||
println "test: --[no-]compress-literals"
|
||||
$ZSTD tmp -c --no-compress-literals -1 | $ZSTD -t
|
||||
$ZSTD tmp -c --no-compress-literals --fast=1 | $ZSTD -t
|
||||
$ZSTD tmp -c --no-compress-literals -19 | $ZSTD -t
|
||||
$ZSTD tmp -c --compress-literals -1 | $ZSTD -t
|
||||
$ZSTD tmp -c --compress-literals --fast=1 | $ZSTD -t
|
||||
$ZSTD tmp -c --compress-literals -19 | $ZSTD -t
|
||||
$ZSTD -b --fast=1 -i1e1 tmp --compress-literals
|
||||
$ZSTD -b --fast=1 -i1e1 tmp --no-compress-literals
|
||||
|
||||
$ECHO "test : file removal"
|
||||
println "test : file removal"
|
||||
$ZSTD -f --rm tmp
|
||||
test ! -f tmp # tmp should no longer be present
|
||||
$ZSTD -f -d --rm tmp.zst
|
||||
test ! -f tmp.zst # tmp.zst should no longer be present
|
||||
$ECHO "test : should quietly not remove non-regular file"
|
||||
$ECHO hello > tmp
|
||||
println "test : should quietly not remove non-regular file"
|
||||
println hello > tmp
|
||||
$ZSTD tmp -f -o "$DEVDEVICE" 2>tmplog > "$INTOVOID"
|
||||
grep -v "Refusing to remove non-regular file" tmplog
|
||||
rm -f tmplog
|
||||
$ZSTD tmp -f -o "$INTOVOID" 2>&1 | grep -v "Refusing to remove non-regular file"
|
||||
$ECHO "test : --rm on stdin"
|
||||
$ECHO a | $ZSTD --rm > $INTOVOID # --rm should remain silent
|
||||
println "test : --rm on stdin"
|
||||
println a | $ZSTD --rm > $INTOVOID # --rm should remain silent
|
||||
rm tmp
|
||||
$ZSTD -f tmp && die "tmp not present : should have failed"
|
||||
test ! -f tmp.zst # tmp.zst should not be created
|
||||
$ECHO "test : -d -f do not delete destination when source is not present"
|
||||
println "test : -d -f do not delete destination when source is not present"
|
||||
touch tmp # create destination file
|
||||
$ZSTD -d -f tmp.zst && die "attempt to decompress a non existing file"
|
||||
test -f tmp # destination file should still be present
|
||||
$ECHO "test : -f do not delete destination when source is not present"
|
||||
println "test : -f do not delete destination when source is not present"
|
||||
rm tmp # erase source file
|
||||
touch tmp.zst # create destination file
|
||||
$ZSTD -f tmp && die "attempt to compress a non existing file"
|
||||
@@ -229,9 +243,9 @@ test -f tmp.zst # destination file should still be present
|
||||
rm tmp*
|
||||
|
||||
|
||||
$ECHO "test : compress multiple files"
|
||||
$ECHO hello > tmp1
|
||||
$ECHO world > tmp2
|
||||
println "test : compress multiple files"
|
||||
println hello > tmp1
|
||||
println world > tmp2
|
||||
$ZSTD tmp1 tmp2 -o "$INTOVOID" -f
|
||||
$ZSTD tmp1 tmp2 -c | $ZSTD -t
|
||||
$ZSTD tmp1 tmp2 -o tmp.zst
|
||||
@@ -252,11 +266,11 @@ fi
|
||||
rm tmp*
|
||||
|
||||
|
||||
$ECHO "\n===> Advanced compression parameters "
|
||||
$ECHO "Hello world!" | $ZSTD --zstd=windowLog=21, - -o tmp.zst && die "wrong parameters not detected!"
|
||||
$ECHO "Hello world!" | $ZSTD --zstd=windowLo=21 - -o tmp.zst && die "wrong parameters not detected!"
|
||||
$ECHO "Hello world!" | $ZSTD --zstd=windowLog=21,slog - -o tmp.zst && die "wrong parameters not detected!"
|
||||
$ECHO "Hello world!" | $ZSTD --zstd=strategy=10 - -o tmp.zst && die "parameter out of bound not detected!" # > btultra2 : does not exist
|
||||
println "\n===> Advanced compression parameters "
|
||||
println "Hello world!" | $ZSTD --zstd=windowLog=21, - -o tmp.zst && die "wrong parameters not detected!"
|
||||
println "Hello world!" | $ZSTD --zstd=windowLo=21 - -o tmp.zst && die "wrong parameters not detected!"
|
||||
println "Hello world!" | $ZSTD --zstd=windowLog=21,slog - -o tmp.zst && die "wrong parameters not detected!"
|
||||
println "Hello world!" | $ZSTD --zstd=strategy=10 - -o tmp.zst && die "parameter out of bound not detected!" # > btultra2 : does not exist
|
||||
test ! -f tmp.zst # tmp.zst should not be created
|
||||
roundTripTest -g512K
|
||||
roundTripTest -g512K " --zstd=mml=3,tlen=48,strat=6"
|
||||
@@ -267,17 +281,17 @@ roundTripTest -g512K " --single-thread --long --zstd=lhlog=20,lmml=64,lblog=1,lh
|
||||
roundTripTest -g64K "19 --zstd=strat=9" # btultra2
|
||||
|
||||
|
||||
$ECHO "\n===> Pass-Through mode "
|
||||
$ECHO "Hello world 1!" | $ZSTD -df
|
||||
$ECHO "Hello world 2!" | $ZSTD -dcf
|
||||
$ECHO "Hello world 3!" > tmp1
|
||||
println "\n===> Pass-Through mode "
|
||||
println "Hello world 1!" | $ZSTD -df
|
||||
println "Hello world 2!" | $ZSTD -dcf
|
||||
println "Hello world 3!" > tmp1
|
||||
$ZSTD -dcf tmp1
|
||||
|
||||
|
||||
$ECHO "\n===> frame concatenation "
|
||||
println "\n===> frame concatenation "
|
||||
|
||||
$ECHO "hello " > hello.tmp
|
||||
$ECHO "world!" > world.tmp
|
||||
println "hello " > hello.tmp
|
||||
println "world!" > world.tmp
|
||||
cat hello.tmp world.tmp > helloworld.tmp
|
||||
$ZSTD -c hello.tmp > hello.zstd
|
||||
$ZSTD -c world.tmp > world.zstd
|
||||
@@ -285,52 +299,67 @@ cat hello.zstd world.zstd > helloworld.zstd
|
||||
$ZSTD -dc helloworld.zstd > result.tmp
|
||||
cat result.tmp
|
||||
$DIFF helloworld.tmp result.tmp
|
||||
$ECHO "frame concatenation without checksum"
|
||||
println "frame concatenation without checksum"
|
||||
$ZSTD -c hello.tmp > hello.zstd --no-check
|
||||
$ZSTD -c world.tmp > world.zstd --no-check
|
||||
cat hello.zstd world.zstd > helloworld.zstd
|
||||
$ZSTD -dc helloworld.zstd > result.tmp
|
||||
$DIFF helloworld.tmp result.tmp
|
||||
$ECHO "testing zstdcat symlink"
|
||||
println "testing zstdcat symlink"
|
||||
ln -sf $ZSTD zstdcat
|
||||
./zstdcat helloworld.zstd > result.tmp
|
||||
$DIFF helloworld.tmp result.tmp
|
||||
ln -s helloworld.zstd helloworld.link.zstd
|
||||
./zstdcat helloworld.link.zstd > result.tmp
|
||||
$DIFF helloworld.tmp result.tmp
|
||||
rm zstdcat
|
||||
rm result.tmp
|
||||
$ECHO "testing zcat symlink"
|
||||
println "testing zcat symlink"
|
||||
ln -sf $ZSTD zcat
|
||||
./zcat helloworld.zstd > result.tmp
|
||||
$DIFF helloworld.tmp result.tmp
|
||||
./zcat helloworld.link.zstd > result.tmp
|
||||
$DIFF helloworld.tmp result.tmp
|
||||
rm zcat
|
||||
rm ./*.tmp ./*.zstd
|
||||
$ECHO "frame concatenation tests completed"
|
||||
println "frame concatenation tests completed"
|
||||
|
||||
|
||||
if [ "$isWindows" = false ] && [ "$UNAME" != 'SunOS' ] && [ "$UNAME" != "OpenBSD" ] ; then
|
||||
$ECHO "\n**** flush write error test **** "
|
||||
println "\n**** flush write error test **** "
|
||||
|
||||
$ECHO "$ECHO foo | $ZSTD > /dev/full"
|
||||
$ECHO foo | $ZSTD > /dev/full && die "write error not detected!"
|
||||
$ECHO "$ECHO foo | $ZSTD | $ZSTD -d > /dev/full"
|
||||
$ECHO foo | $ZSTD | $ZSTD -d > /dev/full && die "write error not detected!"
|
||||
|
||||
|
||||
$ECHO "\n===> symbolic link test "
|
||||
|
||||
rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst
|
||||
$ECHO "hello world" > hello.tmp
|
||||
ln -s hello.tmp world.tmp
|
||||
$ZSTD world.tmp hello.tmp
|
||||
test -f hello.tmp.zst # regular file should have been compressed!
|
||||
test ! -f world.tmp.zst # symbolic link should not have been compressed!
|
||||
$ZSTD world.tmp hello.tmp -f
|
||||
test -f world.tmp.zst # symbolic link should have been compressed with --force
|
||||
rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst
|
||||
println "println foo | $ZSTD > /dev/full"
|
||||
println foo | $ZSTD > /dev/full && die "write error not detected!"
|
||||
println "println foo | $ZSTD | $ZSTD -d > /dev/full"
|
||||
println foo | $ZSTD | $ZSTD -d > /dev/full && die "write error not detected!"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
$ECHO "\n===> test sparse file support "
|
||||
if [ "$isWindows" = false ] && [ "$UNAME" != 'SunOS' ] ; then
|
||||
|
||||
println "\n===> symbolic link test "
|
||||
|
||||
rm -f hello.tmp world.tmp world2.tmp hello.tmp.zst world.tmp.zst
|
||||
println "hello world" > hello.tmp
|
||||
ln -s hello.tmp world.tmp
|
||||
ln -s hello.tmp world2.tmp
|
||||
$ZSTD world.tmp hello.tmp || true
|
||||
test -f hello.tmp.zst # regular file should have been compressed!
|
||||
test ! -f world.tmp.zst # symbolic link should not have been compressed!
|
||||
$ZSTD world.tmp || true
|
||||
test ! -f world.tmp.zst # symbolic link should not have been compressed!
|
||||
$ZSTD world.tmp world2.tmp || true
|
||||
test ! -f world.tmp.zst # symbolic link should not have been compressed!
|
||||
test ! -f world2.tmp.zst # symbolic link should not have been compressed!
|
||||
$ZSTD world.tmp hello.tmp -f
|
||||
test -f world.tmp.zst # symbolic link should have been compressed with --force
|
||||
rm -f hello.tmp world.tmp world2.tmp hello.tmp.zst world.tmp.zst
|
||||
|
||||
fi
|
||||
|
||||
|
||||
println "\n===> test sparse file support "
|
||||
|
||||
./datagen -g5M -P100 > tmpSparse
|
||||
$ZSTD tmpSparse -c | $ZSTD -dv -o tmpSparseRegen
|
||||
@@ -343,10 +372,10 @@ ls -ls tmpSparse* # look at file size and block size on disk
|
||||
./datagen -s1 -g1200007 -P100 | $ZSTD | $ZSTD -dv --sparse -c > tmpSparseOdd # Odd size file (to not finish on an exact nb of blocks)
|
||||
./datagen -s1 -g1200007 -P100 | $DIFF -s - tmpSparseOdd
|
||||
ls -ls tmpSparseOdd # look at file size and block size on disk
|
||||
$ECHO "\n Sparse Compatibility with Console :"
|
||||
$ECHO "Hello World 1 !" | $ZSTD | $ZSTD -d -c
|
||||
$ECHO "Hello World 2 !" | $ZSTD | $ZSTD -d | cat
|
||||
$ECHO "\n Sparse Compatibility with Append :"
|
||||
println "\n Sparse Compatibility with Console :"
|
||||
println "Hello World 1 !" | $ZSTD | $ZSTD -d -c
|
||||
println "Hello World 2 !" | $ZSTD | $ZSTD -d | cat
|
||||
println "\n Sparse Compatibility with Append :"
|
||||
./datagen -P100 -g1M > tmpSparse1M
|
||||
cat tmpSparse1M tmpSparse1M > tmpSparse2M
|
||||
$ZSTD -v -f tmpSparse1M -o tmpSparseCompressed
|
||||
@@ -357,185 +386,193 @@ $DIFF tmpSparse2M tmpSparseRegenerated
|
||||
rm tmpSparse*
|
||||
|
||||
|
||||
$ECHO "\n===> multiple files tests "
|
||||
println "\n===> multiple files tests "
|
||||
|
||||
./datagen -s1 > tmp1 2> $INTOVOID
|
||||
./datagen -s2 -g100K > tmp2 2> $INTOVOID
|
||||
./datagen -s3 -g1M > tmp3 2> $INTOVOID
|
||||
$ECHO "compress tmp* : "
|
||||
println "compress tmp* : "
|
||||
$ZSTD -f tmp*
|
||||
ls -ls tmp*
|
||||
rm tmp1 tmp2 tmp3
|
||||
$ECHO "decompress tmp* : "
|
||||
$ZSTD -df *.zst
|
||||
println "decompress tmp* : "
|
||||
$ZSTD -df ./*.zst
|
||||
ls -ls tmp*
|
||||
$ECHO "compress tmp* into stdout > tmpall : "
|
||||
println "compress tmp* into stdout > tmpall : "
|
||||
$ZSTD -c tmp1 tmp2 tmp3 > tmpall
|
||||
ls -ls tmp* # check size of tmpall (should be tmp1.zst + tmp2.zst + tmp3.zst)
|
||||
$ECHO "decompress tmpall* into stdout > tmpdec : "
|
||||
println "decompress tmpall* into stdout > tmpdec : "
|
||||
cp tmpall tmpall2
|
||||
$ZSTD -dc tmpall* > tmpdec
|
||||
ls -ls tmp* # check size of tmpdec (should be 2*(tmp1 + tmp2 + tmp3))
|
||||
$ECHO "compress multiple files including a missing one (notHere) : "
|
||||
println "compress multiple files including a missing one (notHere) : "
|
||||
$ZSTD -f tmp1 notHere tmp2 && die "missing file not detected!"
|
||||
|
||||
|
||||
$ECHO "\n===> dictionary tests "
|
||||
println "\n===> dictionary tests "
|
||||
|
||||
$ECHO "- test with raw dict (content only) "
|
||||
println "- test with raw dict (content only) "
|
||||
./datagen > tmpDict
|
||||
./datagen -g1M | $MD5SUM > tmp1
|
||||
./datagen -g1M | $ZSTD -D tmpDict | $ZSTD -D tmpDict -dvq | $MD5SUM > tmp2
|
||||
$DIFF -q tmp1 tmp2
|
||||
$ECHO "- Create first dictionary "
|
||||
TESTFILE=../programs/zstdcli.c
|
||||
$ZSTD --train *.c ../programs/*.c -o tmpDict
|
||||
cp $TESTFILE tmp
|
||||
$ECHO "- Dictionary compression roundtrip"
|
||||
println "- Create first dictionary "
|
||||
TESTFILE="$PRGDIR"/zstdcli.c
|
||||
$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict
|
||||
cp "$TESTFILE" tmp
|
||||
println "- Test dictionary compression with tmpDict as an input file and dictionary"
|
||||
$ZSTD -f tmpDict -D tmpDict && die "compression error not detected!"
|
||||
println "- Dictionary compression roundtrip"
|
||||
$ZSTD -f tmp -D tmpDict
|
||||
$ZSTD -d tmp.zst -D tmpDict -fo result
|
||||
$DIFF $TESTFILE result
|
||||
$ECHO "- Dictionary compression with btlazy2 strategy"
|
||||
$DIFF "$TESTFILE" result
|
||||
println "- Dictionary compression with btlazy2 strategy"
|
||||
$ZSTD -f tmp -D tmpDict --zstd=strategy=6
|
||||
$ZSTD -d tmp.zst -D tmpDict -fo result
|
||||
$DIFF $TESTFILE result
|
||||
$DIFF "$TESTFILE" result
|
||||
if [ -n "$hasMT" ]
|
||||
then
|
||||
$ECHO "- Test dictionary compression with multithreading "
|
||||
println "- Test dictionary compression with multithreading "
|
||||
./datagen -g5M | $ZSTD -T2 -D tmpDict | $ZSTD -t -D tmpDict # fails with v1.3.2
|
||||
fi
|
||||
$ECHO "- Create second (different) dictionary "
|
||||
$ZSTD --train *.c ../programs/*.c ../programs/*.h -o tmpDictC
|
||||
println "- Create second (different) dictionary "
|
||||
$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC
|
||||
$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
|
||||
$ECHO "- Create dictionary with short dictID"
|
||||
$ZSTD --train *.c ../programs/*.c --dictID=1 -o tmpDict1
|
||||
println "- Create dictionary with short dictID"
|
||||
$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1
|
||||
cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
|
||||
$ECHO "- Create dictionary with wrong dictID parameter order (must fail)"
|
||||
$ZSTD --train *.c ../programs/*.c --dictID -o 1 tmpDict1 && die "wrong order : --dictID must be followed by argument "
|
||||
$ECHO "- Create dictionary with size limit"
|
||||
$ZSTD --train *.c ../programs/*.c -o tmpDict2 --maxdict=4K -v
|
||||
$ECHO "- Create dictionary with small size limit"
|
||||
$ZSTD --train *.c ../programs/*.c -o tmpDict3 --maxdict=1K -v
|
||||
$ECHO "- Create dictionary with wrong parameter order (must fail)"
|
||||
$ZSTD --train *.c ../programs/*.c -o tmpDict3 --maxdict -v 4K && die "wrong order : --maxdict must be followed by argument "
|
||||
$ECHO "- Compress without dictID"
|
||||
println "- Create dictionary with wrong dictID parameter order (must fail)"
|
||||
$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID -o 1 tmpDict1 && die "wrong order : --dictID must be followed by argument "
|
||||
println "- Create dictionary with size limit"
|
||||
$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K -v
|
||||
println "- Create dictionary with small size limit"
|
||||
$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict3 --maxdict=1K -v
|
||||
println "- Create dictionary with wrong parameter order (must fail)"
|
||||
$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict3 --maxdict -v 4K && die "wrong order : --maxdict must be followed by argument "
|
||||
println "- Compress without dictID"
|
||||
$ZSTD -f tmp -D tmpDict1 --no-dictID
|
||||
$ZSTD -d tmp.zst -D tmpDict -fo result
|
||||
$DIFF $TESTFILE result
|
||||
$ECHO "- Compress with wrong argument order (must fail)"
|
||||
$DIFF "$TESTFILE" result
|
||||
println "- Compress with wrong argument order (must fail)"
|
||||
$ZSTD tmp -Df tmpDict1 -c > $INTOVOID && die "-D must be followed by dictionary name "
|
||||
$ECHO "- Compress multiple files with dictionary"
|
||||
println "- Compress multiple files with dictionary"
|
||||
rm -rf dirTestDict
|
||||
mkdir dirTestDict
|
||||
cp *.c dirTestDict
|
||||
cp ../programs/*.c dirTestDict
|
||||
cp ../programs/*.h dirTestDict
|
||||
cp "$TESTDIR"/*.c dirTestDict
|
||||
cp "$PRGDIR"/*.c dirTestDict
|
||||
cp "$PRGDIR"/*.h dirTestDict
|
||||
$MD5SUM dirTestDict/* > tmph1
|
||||
$ZSTD -f --rm dirTestDict/* -D tmpDictC
|
||||
$ZSTD -d --rm dirTestDict/*.zst -D tmpDictC # note : use internal checksum by default
|
||||
case "$UNAME" in
|
||||
Darwin) $ECHO "md5sum -c not supported on OS-X : test skipped" ;; # not compatible with OS-X's md5
|
||||
Darwin) println "md5sum -c not supported on OS-X : test skipped" ;; # not compatible with OS-X's md5
|
||||
*) $MD5SUM -c tmph1 ;;
|
||||
esac
|
||||
rm -rf dirTestDict
|
||||
$ECHO "- dictionary builder on bogus input"
|
||||
$ECHO "Hello World" > tmp
|
||||
println "- dictionary builder on bogus input"
|
||||
println "Hello World" > tmp
|
||||
$ZSTD --train-legacy -q tmp && die "Dictionary training should fail : not enough input source"
|
||||
./datagen -P0 -g10M > tmp
|
||||
$ZSTD --train-legacy -q tmp && die "Dictionary training should fail : source is pure noise"
|
||||
$ECHO "- Test -o before --train"
|
||||
println "- Test -o before --train"
|
||||
rm -f tmpDict dictionary
|
||||
$ZSTD -o tmpDict --train *.c ../programs/*.c
|
||||
$ZSTD -o tmpDict --train "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
test -f tmpDict
|
||||
$ZSTD --train *.c ../programs/*.c
|
||||
$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
test -f dictionary
|
||||
rm tmp* dictionary
|
||||
|
||||
|
||||
$ECHO "\n===> fastCover dictionary builder : advanced options "
|
||||
|
||||
TESTFILE=../programs/zstdcli.c
|
||||
println "\n===> fastCover dictionary builder : advanced options "
|
||||
TESTFILE="$PRGDIR"/zstdcli.c
|
||||
./datagen > tmpDict
|
||||
$ECHO "- Create first dictionary"
|
||||
$ZSTD --train-fastcover=k=46,d=8,f=15,split=80 *.c ../programs/*.c -o tmpDict
|
||||
cp $TESTFILE tmp
|
||||
println "- Create first dictionary"
|
||||
$ZSTD --train-fastcover=k=46,d=8,f=15,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict
|
||||
cp "$TESTFILE" tmp
|
||||
$ZSTD -f tmp -D tmpDict
|
||||
$ZSTD -d tmp.zst -D tmpDict -fo result
|
||||
$DIFF $TESTFILE result
|
||||
$ECHO "- Create second (different) dictionary"
|
||||
$ZSTD --train-fastcover=k=56,d=8 *.c ../programs/*.c ../programs/*.h -o tmpDictC
|
||||
$DIFF "$TESTFILE" result
|
||||
println "- Create second (different) dictionary"
|
||||
$ZSTD --train-fastcover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC
|
||||
$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
|
||||
$ECHO "- Create dictionary with short dictID"
|
||||
$ZSTD --train-fastcover=k=46,d=8,f=15,split=80 *.c ../programs/*.c --dictID=1 -o tmpDict1
|
||||
$ZSTD --train-fastcover=k=56,d=8 && die "Create dictionary without input file"
|
||||
println "- Create dictionary with short dictID"
|
||||
$ZSTD --train-fastcover=k=46,d=8,f=15,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1
|
||||
cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
|
||||
$ECHO "- Create dictionary with size limit"
|
||||
$ZSTD --train-fastcover=steps=8 *.c ../programs/*.c -o tmpDict2 --maxdict=4K
|
||||
$ECHO "- Compare size of dictionary from 90% training samples with 80% training samples"
|
||||
$ZSTD --train-fastcover=split=90 -r *.c ../programs/*.c
|
||||
$ZSTD --train-fastcover=split=80 -r *.c ../programs/*.c
|
||||
$ECHO "- Create dictionary using all samples for both training and testing"
|
||||
$ZSTD --train-fastcover=split=100 -r *.c ../programs/*.c
|
||||
$ECHO "- Create dictionary using f=16"
|
||||
$ZSTD --train-fastcover=f=16 -r *.c ../programs/*.c
|
||||
$ECHO "- Create dictionary using accel=2"
|
||||
$ZSTD --train-fastcover=accel=2 -r *.c ../programs/*.c
|
||||
$ECHO "- Create dictionary using accel=10"
|
||||
$ZSTD --train-fastcover=accel=10 -r *.c ../programs/*.c
|
||||
$ECHO "- Create dictionary with multithreading"
|
||||
$ZSTD --train-fastcover -T4 -r *.c ../programs/*.c
|
||||
$ECHO "- Test -o before --train-fastcover"
|
||||
println "- Create dictionaries with shrink-dict flag enabled"
|
||||
$ZSTD --train-fastcover=steps=256,shrink "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpShrinkDict
|
||||
$ZSTD --train-fastcover=steps=256,shrink=1 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpShrinkDict1
|
||||
$ZSTD --train-fastcover=steps=256,shrink=5 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpShrinkDict2
|
||||
println "- Create dictionary with size limit"
|
||||
$ZSTD --train-fastcover=steps=8 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K
|
||||
println "- Compare size of dictionary from 90% training samples with 80% training samples"
|
||||
$ZSTD --train-fastcover=split=90 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
$ZSTD --train-fastcover=split=80 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
println "- Create dictionary using all samples for both training and testing"
|
||||
$ZSTD --train-fastcover=split=100 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
println "- Create dictionary using f=16"
|
||||
$ZSTD --train-fastcover=f=16 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
$ZSTD --train-fastcover=accel=15 -r "$TESTDIR"/*.c "$PRGDIR"/*.c && die "Created dictionary using accel=15"
|
||||
println "- Create dictionary using accel=2"
|
||||
$ZSTD --train-fastcover=accel=2 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
println "- Create dictionary using accel=10"
|
||||
$ZSTD --train-fastcover=accel=10 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
println "- Create dictionary with multithreading"
|
||||
$ZSTD --train-fastcover -T4 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
println "- Test -o before --train-fastcover"
|
||||
rm -f tmpDict dictionary
|
||||
$ZSTD -o tmpDict --train-fastcover *.c ../programs/*.c
|
||||
$ZSTD -o tmpDict --train-fastcover "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
test -f tmpDict
|
||||
$ZSTD --train-fastcover *.c ../programs/*.c
|
||||
$ZSTD --train-fastcover "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
test -f dictionary
|
||||
rm tmp* dictionary
|
||||
|
||||
|
||||
$ECHO "\n===> legacy dictionary builder "
|
||||
println "\n===> legacy dictionary builder "
|
||||
|
||||
TESTFILE=../programs/zstdcli.c
|
||||
TESTFILE="$PRGDIR"/zstdcli.c
|
||||
./datagen > tmpDict
|
||||
$ECHO "- Create first dictionary"
|
||||
$ZSTD --train-legacy=selectivity=8 *.c ../programs/*.c -o tmpDict
|
||||
cp $TESTFILE tmp
|
||||
println "- Create first dictionary"
|
||||
$ZSTD --train-legacy=selectivity=8 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict
|
||||
cp "$TESTFILE" tmp
|
||||
$ZSTD -f tmp -D tmpDict
|
||||
$ZSTD -d tmp.zst -D tmpDict -fo result
|
||||
$DIFF $TESTFILE result
|
||||
$ECHO "- Create second (different) dictionary"
|
||||
$ZSTD --train-legacy=s=5 *.c ../programs/*.c ../programs/*.h -o tmpDictC
|
||||
$DIFF "$TESTFILE" result
|
||||
$ZSTD --train-legacy=s=8 && die "Create dictionary without input files (should error)"
|
||||
println "- Create second (different) dictionary"
|
||||
$ZSTD --train-legacy=s=5 "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC
|
||||
$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
|
||||
$ECHO "- Create dictionary with short dictID"
|
||||
$ZSTD --train-legacy -s5 *.c ../programs/*.c --dictID=1 -o tmpDict1
|
||||
println "- Create dictionary with short dictID"
|
||||
$ZSTD --train-legacy -s5 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1
|
||||
cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
|
||||
$ECHO "- Create dictionary with size limit"
|
||||
$ZSTD --train-legacy -s9 *.c ../programs/*.c -o tmpDict2 --maxdict=4K
|
||||
$ECHO "- Test -o before --train-legacy"
|
||||
println "- Create dictionary with size limit"
|
||||
$ZSTD --train-legacy -s9 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K
|
||||
println "- Test -o before --train-legacy"
|
||||
rm -f tmpDict dictionary
|
||||
$ZSTD -o tmpDict --train-legacy *.c ../programs/*.c
|
||||
$ZSTD -o tmpDict --train-legacy "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
test -f tmpDict
|
||||
$ZSTD --train-legacy *.c ../programs/*.c
|
||||
$ZSTD --train-legacy "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
test -f dictionary
|
||||
rm tmp* dictionary
|
||||
|
||||
|
||||
$ECHO "\n===> integrity tests "
|
||||
println "\n===> integrity tests "
|
||||
|
||||
$ECHO "test one file (tmp1.zst) "
|
||||
println "test one file (tmp1.zst) "
|
||||
./datagen > tmp1
|
||||
$ZSTD tmp1
|
||||
$ZSTD -t tmp1.zst
|
||||
$ZSTD --test tmp1.zst
|
||||
$ECHO "test multiple files (*.zst) "
|
||||
$ZSTD -t *.zst
|
||||
$ECHO "test bad files (*) "
|
||||
$ZSTD -t * && die "bad files not detected !"
|
||||
println "test multiple files (*.zst) "
|
||||
$ZSTD -t ./*.zst
|
||||
println "test bad files (*) "
|
||||
$ZSTD -t ./* && die "bad files not detected !"
|
||||
$ZSTD -t tmp1 && die "bad file not detected !"
|
||||
cp tmp1 tmp2.zst
|
||||
$ZSTD -t tmp2.zst && die "bad file not detected !"
|
||||
./datagen -g0 > tmp3
|
||||
$ZSTD -t tmp3 && die "bad file not detected !" # detects 0-sized files as bad
|
||||
$ECHO "test --rm and --test combined "
|
||||
println "test --rm and --test combined "
|
||||
$ZSTD -t --rm tmp1.zst
|
||||
test -f tmp1.zst # check file is still present
|
||||
split -b16384 tmp1.zst tmpSplit.
|
||||
@@ -544,40 +581,40 @@ $ZSTD -t tmpSplit.* && die "bad file not detected !"
|
||||
|
||||
|
||||
|
||||
$ECHO "\n===> golden files tests "
|
||||
println "\n===> golden files tests "
|
||||
|
||||
$ZSTD -t -r files
|
||||
$ZSTD -c -r files | $ZSTD -t
|
||||
$ZSTD -t -r "$TESTDIR/files"
|
||||
$ZSTD -c -r "$TESTDIR/files" | $ZSTD -t
|
||||
|
||||
|
||||
$ECHO "\n===> benchmark mode tests "
|
||||
println "\n===> benchmark mode tests "
|
||||
|
||||
$ECHO "bench one file"
|
||||
println "bench one file"
|
||||
./datagen > tmp1
|
||||
$ZSTD -bi0 tmp1
|
||||
$ECHO "bench multiple levels"
|
||||
println "bench multiple levels"
|
||||
$ZSTD -i0b0e3 tmp1
|
||||
$ECHO "bench negative level"
|
||||
println "bench negative level"
|
||||
$ZSTD -bi0 --fast tmp1
|
||||
$ECHO "with recursive and quiet modes"
|
||||
println "with recursive and quiet modes"
|
||||
$ZSTD -rqi1b1e2 tmp1
|
||||
$ECHO "benchmark decompression only"
|
||||
println "benchmark decompression only"
|
||||
$ZSTD -f tmp1
|
||||
$ZSTD -b -d -i1 tmp1.zst
|
||||
|
||||
$ECHO "\n===> zstd compatibility tests "
|
||||
println "\n===> zstd compatibility tests "
|
||||
|
||||
./datagen > tmp
|
||||
rm -f tmp.zst
|
||||
$ZSTD --format=zstd -f tmp
|
||||
test -f tmp.zst
|
||||
|
||||
$ECHO "\n===> gzip compatibility tests "
|
||||
println "\n===> gzip compatibility tests "
|
||||
|
||||
GZIPMODE=1
|
||||
$ZSTD --format=gzip -V || GZIPMODE=0
|
||||
if [ $GZIPMODE -eq 1 ]; then
|
||||
$ECHO "gzip support detected"
|
||||
println "gzip support detected"
|
||||
GZIPEXE=1
|
||||
gzip -V || GZIPEXE=0
|
||||
if [ $GZIPEXE -eq 1 ]; then
|
||||
@@ -588,14 +625,14 @@ if [ $GZIPMODE -eq 1 ]; then
|
||||
$ZSTD -d -f -v tmp.gz
|
||||
rm tmp*
|
||||
else
|
||||
$ECHO "gzip binary not detected"
|
||||
println "gzip binary not detected"
|
||||
fi
|
||||
else
|
||||
$ECHO "gzip mode not supported"
|
||||
println "gzip mode not supported"
|
||||
fi
|
||||
|
||||
|
||||
$ECHO "\n===> gzip frame tests "
|
||||
println "\n===> gzip frame tests "
|
||||
|
||||
if [ $GZIPMODE -eq 1 ]; then
|
||||
./datagen > tmp
|
||||
@@ -605,7 +642,7 @@ if [ $GZIPMODE -eq 1 ]; then
|
||||
truncateLastByte tmp.gz | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
|
||||
rm tmp*
|
||||
else
|
||||
$ECHO "gzip mode not supported"
|
||||
println "gzip mode not supported"
|
||||
fi
|
||||
|
||||
if [ $GZIPMODE -eq 1 ]; then
|
||||
@@ -615,16 +652,16 @@ if [ $GZIPMODE -eq 1 ]; then
|
||||
test -f tmp.zst
|
||||
fi
|
||||
|
||||
$ECHO "\n===> xz compatibility tests "
|
||||
println "\n===> xz compatibility tests "
|
||||
|
||||
LZMAMODE=1
|
||||
$ZSTD --format=xz -V || LZMAMODE=0
|
||||
if [ $LZMAMODE -eq 1 ]; then
|
||||
$ECHO "xz support detected"
|
||||
println "xz support detected"
|
||||
XZEXE=1
|
||||
xz -Q -V && lzma -Q -V || XZEXE=0
|
||||
if [ $XZEXE -eq 1 ]; then
|
||||
$ECHO "Testing zstd xz and lzma support"
|
||||
println "Testing zstd xz and lzma support"
|
||||
./datagen > tmp
|
||||
$ZSTD --format=lzma -f tmp
|
||||
$ZSTD --format=xz -f tmp
|
||||
@@ -635,18 +672,18 @@ if [ $LZMAMODE -eq 1 ]; then
|
||||
$ZSTD -d -f -v tmp.xz
|
||||
$ZSTD -d -f -v tmp.lzma
|
||||
rm tmp*
|
||||
$ECHO "Creating symlinks"
|
||||
println "Creating symlinks"
|
||||
ln -s $ZSTD ./xz
|
||||
ln -s $ZSTD ./unxz
|
||||
ln -s $ZSTD ./lzma
|
||||
ln -s $ZSTD ./unlzma
|
||||
$ECHO "Testing xz and lzma symlinks"
|
||||
println "Testing xz and lzma symlinks"
|
||||
./datagen > tmp
|
||||
./xz tmp
|
||||
xz -Q -d tmp.xz
|
||||
./lzma tmp
|
||||
lzma -Q -d tmp.lzma
|
||||
$ECHO "Testing unxz and unlzma symlinks"
|
||||
println "Testing unxz and unlzma symlinks"
|
||||
xz -Q tmp
|
||||
./xz -d tmp.xz
|
||||
lzma -Q tmp
|
||||
@@ -654,14 +691,14 @@ if [ $LZMAMODE -eq 1 ]; then
|
||||
rm xz unxz lzma unlzma
|
||||
rm tmp*
|
||||
else
|
||||
$ECHO "xz binary not detected"
|
||||
println "xz binary not detected"
|
||||
fi
|
||||
else
|
||||
$ECHO "xz mode not supported"
|
||||
println "xz mode not supported"
|
||||
fi
|
||||
|
||||
|
||||
$ECHO "\n===> xz frame tests "
|
||||
println "\n===> xz frame tests "
|
||||
|
||||
if [ $LZMAMODE -eq 1 ]; then
|
||||
./datagen > tmp
|
||||
@@ -673,15 +710,15 @@ if [ $LZMAMODE -eq 1 ]; then
|
||||
truncateLastByte tmp.lzma | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
|
||||
rm tmp*
|
||||
else
|
||||
$ECHO "xz mode not supported"
|
||||
println "xz mode not supported"
|
||||
fi
|
||||
|
||||
$ECHO "\n===> lz4 compatibility tests "
|
||||
println "\n===> lz4 compatibility tests "
|
||||
|
||||
LZ4MODE=1
|
||||
$ZSTD --format=lz4 -V || LZ4MODE=0
|
||||
if [ $LZ4MODE -eq 1 ]; then
|
||||
$ECHO "lz4 support detected"
|
||||
println "lz4 support detected"
|
||||
LZ4EXE=1
|
||||
lz4 -V || LZ4EXE=0
|
||||
if [ $LZ4EXE -eq 1 ]; then
|
||||
@@ -692,14 +729,14 @@ if [ $LZ4MODE -eq 1 ]; then
|
||||
$ZSTD -d -f -v tmp.lz4
|
||||
rm tmp*
|
||||
else
|
||||
$ECHO "lz4 binary not detected"
|
||||
println "lz4 binary not detected"
|
||||
fi
|
||||
else
|
||||
$ECHO "lz4 mode not supported"
|
||||
println "lz4 mode not supported"
|
||||
fi
|
||||
|
||||
|
||||
$ECHO "\n===> lz4 frame tests "
|
||||
println "\n===> lz4 frame tests "
|
||||
|
||||
if [ $LZ4MODE -eq 1 ]; then
|
||||
./datagen > tmp
|
||||
@@ -709,10 +746,10 @@ if [ $LZ4MODE -eq 1 ]; then
|
||||
truncateLastByte tmp.lz4 | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
|
||||
rm tmp*
|
||||
else
|
||||
$ECHO "lz4 mode not supported"
|
||||
println "lz4 mode not supported"
|
||||
fi
|
||||
|
||||
$ECHO "\n===> suffix list test"
|
||||
println "\n===> suffix list test"
|
||||
|
||||
! $ZSTD -d tmp.abc 2> tmplg
|
||||
|
||||
@@ -729,7 +766,7 @@ if [ $LZ4MODE -ne 1 ]; then
|
||||
grep ".lz4" tmplg > $INTOVOID && die "Unsupported suffix listed"
|
||||
fi
|
||||
|
||||
$ECHO "\n===> zstd round-trip tests "
|
||||
println "\n===> zstd round-trip tests "
|
||||
|
||||
roundTripTest
|
||||
roundTripTest -g15K # TableID==3
|
||||
@@ -742,7 +779,7 @@ roundTripTest -g516K 19 # btopt
|
||||
|
||||
fileRoundTripTest -g500K
|
||||
|
||||
$ECHO "\n===> zstd long distance matching round-trip tests "
|
||||
println "\n===> zstd long distance matching round-trip tests "
|
||||
roundTripTest -g0 "2 --single-thread --long"
|
||||
roundTripTest -g1000K "1 --single-thread --long"
|
||||
roundTripTest -g517K "6 --single-thread --long"
|
||||
@@ -754,62 +791,75 @@ fileRoundTripTest -g5M "3 --single-thread --long"
|
||||
roundTripTest -g96K "5 --single-thread"
|
||||
if [ -n "$hasMT" ]
|
||||
then
|
||||
$ECHO "\n===> zstdmt round-trip tests "
|
||||
println "\n===> zstdmt round-trip tests "
|
||||
roundTripTest -g4M "1 -T0"
|
||||
roundTripTest -g8M "3 -T2"
|
||||
roundTripTest -g8000K "2 --threads=2"
|
||||
fileRoundTripTest -g4M "19 -T2 -B1M"
|
||||
|
||||
$ECHO "\n===> zstdmt long distance matching round-trip tests "
|
||||
println "\n===> zstdmt long distance matching round-trip tests "
|
||||
roundTripTest -g8M "3 --long=24 -T2"
|
||||
|
||||
$ECHO "\n===> ovLog tests "
|
||||
println "\n===> ovLog tests "
|
||||
./datagen -g2MB > tmp
|
||||
refSize=$($ZSTD tmp -6 -c --zstd=wlog=18 | wc -c)
|
||||
ov9Size=$($ZSTD tmp -6 -c --zstd=wlog=18,ovlog=9 | wc -c)
|
||||
ov1Size=$($ZSTD tmp -6 -c --zstd=wlog=18,ovlog=1 | wc -c)
|
||||
if [ $refSize -eq $ov9Size ]; then
|
||||
if [ "$refSize" -eq "$ov9Size" ]; then
|
||||
echo ov9Size should be different from refSize
|
||||
exit 1
|
||||
fi
|
||||
if [ $refSize -eq $ov1Size ]; then
|
||||
if [ "$refSize" -eq "$ov1Size" ]; then
|
||||
echo ov1Size should be different from refSize
|
||||
exit 1
|
||||
fi
|
||||
if [ $ov9Size -ge $ov1Size ]; then
|
||||
echo ov9Size=$ov9Size should be smaller than ov1Size=$ov1Size
|
||||
if [ "$ov9Size" -ge "$ov1Size" ]; then
|
||||
echo ov9Size="$ov9Size" should be smaller than ov1Size="$ov1Size"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
$ECHO "\n===> no multithreading, skipping zstdmt tests "
|
||||
println "\n===> no multithreading, skipping zstdmt tests "
|
||||
fi
|
||||
|
||||
rm tmp*
|
||||
|
||||
$ECHO "\n===> zstd --list/-l single frame tests "
|
||||
println "\n===> zstd --list/-l single frame tests "
|
||||
./datagen > tmp1
|
||||
./datagen > tmp2
|
||||
./datagen > tmp3
|
||||
$ZSTD tmp*
|
||||
$ZSTD -l *.zst
|
||||
$ZSTD -lv *.zst | grep "Decompressed Size:" # check that decompressed size is present in header
|
||||
$ZSTD --list *.zst
|
||||
$ZSTD --list -v *.zst
|
||||
$ZSTD -l ./*.zst
|
||||
$ZSTD -lv ./*.zst | grep "Decompressed Size:" # check that decompressed size is present in header
|
||||
$ZSTD --list ./*.zst
|
||||
$ZSTD --list -v ./*.zst
|
||||
|
||||
$ECHO "\n===> zstd --list/-l multiple frame tests "
|
||||
println "\n===> zstd --list/-l multiple frame tests "
|
||||
cat tmp1.zst tmp2.zst > tmp12.zst
|
||||
cat tmp12.zst tmp3.zst > tmp123.zst
|
||||
$ZSTD -l *.zst
|
||||
$ZSTD -lv *.zst
|
||||
$ZSTD -l ./*.zst
|
||||
$ZSTD -lv ./*.zst
|
||||
|
||||
$ECHO "\n===> zstd --list/-l error detection tests "
|
||||
println "\n===> zstd --list/-l error detection tests "
|
||||
$ZSTD -l tmp1 tmp1.zst && die "-l must fail on non-zstd file"
|
||||
$ZSTD --list tmp* && die "-l must fail on non-zstd file"
|
||||
$ZSTD -lv tmp1* && die "-l must fail on non-zstd file"
|
||||
$ZSTD --list -v tmp2 tmp12.zst && die "-l must fail on non-zstd file"
|
||||
|
||||
$ECHO "\n===> zstd --list/-l errors when presented with stdin / no files"
|
||||
println "test : detect truncated compressed file "
|
||||
TEST_DATA_FILE=truncatable-input.txt
|
||||
FULL_COMPRESSED_FILE=${TEST_DATA_FILE}.zst
|
||||
TRUNCATED_COMPRESSED_FILE=truncated-input.txt.zst
|
||||
./datagen -g50000 > $TEST_DATA_FILE
|
||||
$ZSTD -f $TEST_DATA_FILE -o $FULL_COMPRESSED_FILE
|
||||
dd bs=1 count=100 if=$FULL_COMPRESSED_FILE of=$TRUNCATED_COMPRESSED_FILE
|
||||
$ZSTD --list $TRUNCATED_COMPRESSED_FILE && die "-l must fail on truncated file"
|
||||
|
||||
rm $TEST_DATA_FILE
|
||||
rm $FULL_COMPRESSED_FILE
|
||||
rm $TRUNCATED_COMPRESSED_FILE
|
||||
|
||||
println "\n===> zstd --list/-l errors when presented with stdin / no files"
|
||||
$ZSTD -l && die "-l must fail on empty list of files"
|
||||
$ZSTD -l - && die "-l does not work on stdin"
|
||||
$ZSTD -l < tmp1.zst && die "-l does not work on stdin"
|
||||
@@ -818,7 +868,7 @@ $ZSTD -l - tmp1.zst && die "-l does not work on stdin"
|
||||
$ZSTD -l - tmp1.zst < tmp1.zst && die "-l does not work on stdin"
|
||||
$ZSTD -l tmp1.zst < tmp2.zst # this will check tmp1.zst, but not tmp2.zst, which is not an error : zstd simply doesn't read stdin in this case. It must not error just because stdin is not a tty
|
||||
|
||||
$ECHO "\n===> zstd --list/-l test with null files "
|
||||
println "\n===> zstd --list/-l test with null files "
|
||||
./datagen -g0 > tmp5
|
||||
$ZSTD tmp5
|
||||
$ZSTD -l tmp5.zst
|
||||
@@ -826,12 +876,12 @@ $ZSTD -l tmp5* && die "-l must fail on non-zstd file"
|
||||
$ZSTD -lv tmp5.zst | grep "Decompressed Size: 0.00 KB (0 B)" # check that 0 size is present in header
|
||||
$ZSTD -lv tmp5* && die "-l must fail on non-zstd file"
|
||||
|
||||
$ECHO "\n===> zstd --list/-l test with no content size field "
|
||||
println "\n===> zstd --list/-l test with no content size field "
|
||||
./datagen -g513K | $ZSTD > tmp6.zst
|
||||
$ZSTD -l tmp6.zst
|
||||
$ZSTD -lv tmp6.zst | grep "Decompressed Size:" && die "Field :Decompressed Size: should not be available in this compressed file"
|
||||
|
||||
$ECHO "\n===> zstd --list/-l test with no checksum "
|
||||
println "\n===> zstd --list/-l test with no checksum "
|
||||
$ZSTD -f --no-check tmp1
|
||||
$ZSTD -l tmp1.zst
|
||||
$ZSTD -lv tmp1.zst
|
||||
@@ -839,7 +889,7 @@ $ZSTD -lv tmp1.zst
|
||||
rm tmp*
|
||||
|
||||
|
||||
$ECHO "\n===> zstd long distance matching tests "
|
||||
println "\n===> zstd long distance matching tests "
|
||||
roundTripTest -g0 " --single-thread --long"
|
||||
roundTripTest -g9M "2 --single-thread --long"
|
||||
# Test parameter parsing
|
||||
@@ -849,29 +899,32 @@ roundTripTest -g1M -P50 "1 --single-thread --long=29" " --long=28 --memory=512MB
|
||||
roundTripTest -g1M -P50 "1 --single-thread --long=29" " --zstd=wlog=28 --memory=512MB"
|
||||
|
||||
|
||||
$ECHO "\n===> adaptive mode "
|
||||
roundTripTest -g270000000 " --adapt"
|
||||
roundTripTest -g27000000 " --adapt=min=1,max=4"
|
||||
$ECHO "===> test: --adapt must fail on incoherent bounds "
|
||||
./datagen > tmp
|
||||
$ZSTD -f -vv --adapt=min=10,max=9 tmp && die "--adapt must fail on incoherent bounds"
|
||||
if [ -n "$hasMT" ]
|
||||
then
|
||||
println "\n===> adaptive mode "
|
||||
roundTripTest -g270000000 " --adapt"
|
||||
roundTripTest -g27000000 " --adapt=min=1,max=4"
|
||||
println "===> test: --adapt must fail on incoherent bounds "
|
||||
./datagen > tmp
|
||||
$ZSTD -f -vv --adapt=min=10,max=9 tmp && die "--adapt must fail on incoherent bounds"
|
||||
|
||||
$ECHO "\n===> rsyncable mode "
|
||||
roundTripTest -g10M " --rsyncable"
|
||||
roundTripTest -g10M " --rsyncable -B100K"
|
||||
$ECHO "===> test: --rsyncable must fail with --single-thread"
|
||||
$ZSTD -f -vv --rsyncable --single-thread tmp && die "--rsyncable must fail with --single-thread"
|
||||
println "\n===> rsyncable mode "
|
||||
roundTripTest -g10M " --rsyncable"
|
||||
roundTripTest -g10M " --rsyncable -B100K"
|
||||
println "===> test: --rsyncable must fail with --single-thread"
|
||||
$ZSTD -f -vv --rsyncable --single-thread tmp && die "--rsyncable must fail with --single-thread"
|
||||
fi
|
||||
|
||||
|
||||
if [ "$1" != "--test-large-data" ]; then
|
||||
$ECHO "Skipping large data tests"
|
||||
println "Skipping large data tests"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
#############################################################################
|
||||
|
||||
$ECHO "\n===> large files tests "
|
||||
println "\n===> large files tests "
|
||||
|
||||
roundTripTest -g270000000 1
|
||||
roundTripTest -g250000000 2
|
||||
@@ -903,7 +956,7 @@ roundTripTest -g1700000000 -P0 "1 --zstd=strategy=6" # ensure btlazy2 can surv
|
||||
fileRoundTripTest -g4193M -P99 1
|
||||
|
||||
|
||||
$ECHO "\n===> zstd long, long distance matching round-trip tests "
|
||||
println "\n===> zstd long, long distance matching round-trip tests "
|
||||
roundTripTest -g270000000 "1 --single-thread --long"
|
||||
roundTripTest -g130000000 -P60 "5 --single-thread --long"
|
||||
roundTripTest -g35000000 -P70 "8 --single-thread --long"
|
||||
@@ -915,45 +968,54 @@ roundTripTest -g600M -P50 "1 --single-thread --long --zstd=wlog=29,clog=28"
|
||||
|
||||
if [ -n "$hasMT" ]
|
||||
then
|
||||
$ECHO "\n===> zstdmt long round-trip tests "
|
||||
println "\n===> zstdmt long round-trip tests "
|
||||
roundTripTest -g80000000 -P99 "19 -T2" " "
|
||||
roundTripTest -g5000000000 -P99 "1 -T2" " "
|
||||
roundTripTest -g500000000 -P97 "1 -T999" " "
|
||||
fileRoundTripTest -g4103M -P98 " -T0" " "
|
||||
roundTripTest -g400000000 -P97 "1 --long=24 -T2" " "
|
||||
# Exposes the bug in https://github.com/facebook/zstd/pull/1678
|
||||
# This test fails on 4 different travis builds at the time of writing
|
||||
# because it needs to allocate 8 GB of memory.
|
||||
# roundTripTest -g10G -P99 "1 -T1 --long=31 --zstd=clog=27 --fast=1000"
|
||||
else
|
||||
$ECHO "\n**** no multithreading, skipping zstdmt tests **** "
|
||||
println "\n**** no multithreading, skipping zstdmt tests **** "
|
||||
fi
|
||||
|
||||
|
||||
$ECHO "\n===> cover dictionary builder : advanced options "
|
||||
println "\n===> cover dictionary builder : advanced options "
|
||||
|
||||
TESTFILE=../programs/zstdcli.c
|
||||
TESTFILE="$PRGDIR"/zstdcli.c
|
||||
./datagen > tmpDict
|
||||
$ECHO "- Create first dictionary"
|
||||
$ZSTD --train-cover=k=46,d=8,split=80 *.c ../programs/*.c -o tmpDict
|
||||
cp $TESTFILE tmp
|
||||
println "- Create first dictionary"
|
||||
$ZSTD --train-cover=k=46,d=8,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict
|
||||
cp "$TESTFILE" tmp
|
||||
$ZSTD -f tmp -D tmpDict
|
||||
$ZSTD -d tmp.zst -D tmpDict -fo result
|
||||
$DIFF $TESTFILE result
|
||||
$ECHO "- Create second (different) dictionary"
|
||||
$ZSTD --train-cover=k=56,d=8 *.c ../programs/*.c ../programs/*.h -o tmpDictC
|
||||
$DIFF "$TESTFILE" result
|
||||
$ZSTD --train-cover=k=56,d=8 && die "Create dictionary without input file (should error)"
|
||||
println "- Create second (different) dictionary"
|
||||
$ZSTD --train-cover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC
|
||||
$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
|
||||
$ECHO "- Create dictionary with short dictID"
|
||||
$ZSTD --train-cover=k=46,d=8,split=80 *.c ../programs/*.c --dictID=1 -o tmpDict1
|
||||
println "- Create dictionary using shrink-dict flag"
|
||||
$ZSTD --train-cover=steps=256,shrink "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpShrinkDict
|
||||
$ZSTD --train-cover=steps=256,shrink=1 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpShrinkDict1
|
||||
$ZSTD --train-cover=steps=256,shrink=5 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpShrinkDict2
|
||||
println "- Create dictionary with short dictID"
|
||||
$ZSTD --train-cover=k=46,d=8,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1
|
||||
cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
|
||||
$ECHO "- Create dictionary with size limit"
|
||||
$ZSTD --train-cover=steps=8 *.c ../programs/*.c -o tmpDict2 --maxdict=4K
|
||||
$ECHO "- Compare size of dictionary from 90% training samples with 80% training samples"
|
||||
$ZSTD --train-cover=split=90 -r *.c ../programs/*.c
|
||||
$ZSTD --train-cover=split=80 -r *.c ../programs/*.c
|
||||
$ECHO "- Create dictionary using all samples for both training and testing"
|
||||
$ZSTD --train-cover=split=100 -r *.c ../programs/*.c
|
||||
$ECHO "- Test -o before --train-cover"
|
||||
println "- Create dictionary with size limit"
|
||||
$ZSTD --train-cover=steps=8 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K
|
||||
println "- Compare size of dictionary from 90% training samples with 80% training samples"
|
||||
$ZSTD --train-cover=split=90 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
$ZSTD --train-cover=split=80 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
println "- Create dictionary using all samples for both training and testing"
|
||||
$ZSTD --train-cover=split=100 -r "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
println "- Test -o before --train-cover"
|
||||
rm -f tmpDict dictionary
|
||||
$ZSTD -o tmpDict --train-cover *.c ../programs/*.c
|
||||
$ZSTD -o tmpDict --train-cover "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
test -f tmpDict
|
||||
$ZSTD --train-cover *.c ../programs/*.c
|
||||
$ZSTD --train-cover "$TESTDIR"/*.c "$PRGDIR"/*.c
|
||||
test -f dictionary
|
||||
rm -f tmp* dictionary
|
||||
|
||||
|
||||
+37
-25
@@ -12,6 +12,7 @@
|
||||
#include "pool.h"
|
||||
#include "threading.h"
|
||||
#include "util.h"
|
||||
#include "timefn.h"
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -25,25 +26,27 @@
|
||||
#define ASSERT_EQ(lhs, rhs) ASSERT_TRUE((lhs) == (rhs))
|
||||
|
||||
struct data {
|
||||
pthread_mutex_t mutex;
|
||||
ZSTD_pthread_mutex_t mutex;
|
||||
unsigned data[16];
|
||||
size_t i;
|
||||
};
|
||||
|
||||
static void fn(void *opaque) {
|
||||
static void fn(void *opaque)
|
||||
{
|
||||
struct data *data = (struct data *)opaque;
|
||||
ZSTD_pthread_mutex_lock(&data->mutex);
|
||||
data->data[data->i] = data->i;
|
||||
data->data[data->i] = (unsigned)(data->i);
|
||||
++data->i;
|
||||
ZSTD_pthread_mutex_unlock(&data->mutex);
|
||||
}
|
||||
|
||||
static int testOrder(size_t numThreads, size_t queueSize) {
|
||||
static int testOrder(size_t numThreads, size_t queueSize)
|
||||
{
|
||||
struct data data;
|
||||
POOL_ctx *ctx = POOL_create(numThreads, queueSize);
|
||||
POOL_ctx* const ctx = POOL_create(numThreads, queueSize);
|
||||
ASSERT_TRUE(ctx);
|
||||
data.i = 0;
|
||||
ZSTD_pthread_mutex_init(&data.mutex, NULL);
|
||||
(void)ZSTD_pthread_mutex_init(&data.mutex, NULL);
|
||||
{ size_t i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
POOL_add(ctx, &fn, &data);
|
||||
@@ -71,7 +74,7 @@ static void waitFn(void *opaque) {
|
||||
/* Tests for deadlock */
|
||||
static int testWait(size_t numThreads, size_t queueSize) {
|
||||
struct data data;
|
||||
POOL_ctx *ctx = POOL_create(numThreads, queueSize);
|
||||
POOL_ctx* const ctx = POOL_create(numThreads, queueSize);
|
||||
ASSERT_TRUE(ctx);
|
||||
{ size_t i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
@@ -87,55 +90,64 @@ static int testWait(size_t numThreads, size_t queueSize) {
|
||||
|
||||
typedef struct {
|
||||
ZSTD_pthread_mutex_t mut;
|
||||
int countdown;
|
||||
int val;
|
||||
int max;
|
||||
ZSTD_pthread_cond_t cond;
|
||||
} poolTest_t;
|
||||
|
||||
static void waitLongFn(void *opaque) {
|
||||
poolTest_t* test = (poolTest_t*) opaque;
|
||||
UTIL_sleepMilli(10);
|
||||
poolTest_t* const test = (poolTest_t*) opaque;
|
||||
ZSTD_pthread_mutex_lock(&test->mut);
|
||||
test->val = test->val + 1;
|
||||
if (test->val == test->max)
|
||||
ZSTD_pthread_cond_signal(&test->cond);
|
||||
test->val++;
|
||||
if (test->val > test->max)
|
||||
test->max = test->val;
|
||||
ZSTD_pthread_mutex_unlock(&test->mut);
|
||||
|
||||
UTIL_sleepMilli(10);
|
||||
|
||||
ZSTD_pthread_mutex_lock(&test->mut);
|
||||
test->val--;
|
||||
test->countdown--;
|
||||
if (test->countdown == 0)
|
||||
ZSTD_pthread_cond_signal(&test->cond);
|
||||
ZSTD_pthread_mutex_unlock(&test->mut);
|
||||
}
|
||||
|
||||
static int testThreadReduction_internal(POOL_ctx* ctx, poolTest_t test)
|
||||
{
|
||||
int const nbWaits = 16;
|
||||
UTIL_time_t startTime;
|
||||
U64 time4threads, time2threads;
|
||||
|
||||
test.countdown = nbWaits;
|
||||
test.val = 0;
|
||||
test.max = nbWaits;
|
||||
test.max = 0;
|
||||
|
||||
startTime = UTIL_getTime();
|
||||
{ int i;
|
||||
for (i=0; i<nbWaits; i++)
|
||||
POOL_add(ctx, &waitLongFn, &test);
|
||||
}
|
||||
ZSTD_pthread_mutex_lock(&test.mut);
|
||||
ZSTD_pthread_cond_wait(&test.cond, &test.mut);
|
||||
ASSERT_EQ(test.val, nbWaits);
|
||||
while (test.countdown > 0)
|
||||
ZSTD_pthread_cond_wait(&test.cond, &test.mut);
|
||||
ASSERT_EQ(test.val, 0);
|
||||
ASSERT_EQ(test.max, 4);
|
||||
ZSTD_pthread_mutex_unlock(&test.mut);
|
||||
time4threads = UTIL_clockSpanNano(startTime);
|
||||
|
||||
ASSERT_EQ( POOL_resize(ctx, 2/*nbThreads*/) , 0 );
|
||||
test.countdown = nbWaits;
|
||||
test.val = 0;
|
||||
startTime = UTIL_getTime();
|
||||
test.max = 0;
|
||||
{ int i;
|
||||
for (i=0; i<nbWaits; i++)
|
||||
POOL_add(ctx, &waitLongFn, &test);
|
||||
}
|
||||
ZSTD_pthread_mutex_lock(&test.mut);
|
||||
ZSTD_pthread_cond_wait(&test.cond, &test.mut);
|
||||
ASSERT_EQ(test.val, nbWaits);
|
||||
while (test.countdown > 0)
|
||||
ZSTD_pthread_cond_wait(&test.cond, &test.mut);
|
||||
ASSERT_EQ(test.val, 0);
|
||||
ASSERT_EQ(test.max, 2);
|
||||
ZSTD_pthread_mutex_unlock(&test.mut);
|
||||
time2threads = UTIL_clockSpanNano(startTime);
|
||||
|
||||
if (time4threads >= time2threads) return 1; /* check 4 threads were effectively faster than 2 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -243,7 +255,7 @@ int main(int argc, const char **argv) {
|
||||
printf("FAIL: thread reduction not effective \n");
|
||||
return 1;
|
||||
} else {
|
||||
printf("SUCCESS: thread reduction effective (slower execution) \n");
|
||||
printf("SUCCESS: thread reduction effective \n");
|
||||
}
|
||||
|
||||
if (testAbruptEnding()) {
|
||||
|
||||
@@ -90,6 +90,17 @@ static config_t mt_ldm = {
|
||||
.param_values = PARAM_VALUES(mt_ldm_param_values),
|
||||
};
|
||||
|
||||
static param_value_t mt_advanced_param_values[] = {
|
||||
{.param = ZSTD_c_nbWorkers, .value = 2},
|
||||
{.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_uncompressed},
|
||||
};
|
||||
|
||||
static config_t mt_advanced = {
|
||||
.name = "multithreaded with advanced params",
|
||||
.cli_args = "-T2 --no-compress-literals",
|
||||
.param_values = PARAM_VALUES(mt_advanced_param_values),
|
||||
};
|
||||
|
||||
static param_value_t const small_wlog_param_values[] = {
|
||||
{.param = ZSTD_c_windowLog, .value = 10},
|
||||
};
|
||||
@@ -122,6 +133,39 @@ static config_t small_clog = {
|
||||
.param_values = PARAM_VALUES(small_clog_param_values),
|
||||
};
|
||||
|
||||
static param_value_t const uncompressed_literals_param_values[] = {
|
||||
{.param = ZSTD_c_compressionLevel, .value = 3},
|
||||
{.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_uncompressed},
|
||||
};
|
||||
|
||||
static config_t uncompressed_literals = {
|
||||
.name = "uncompressed literals",
|
||||
.cli_args = "-3 --no-compress-literals",
|
||||
.param_values = PARAM_VALUES(uncompressed_literals_param_values),
|
||||
};
|
||||
|
||||
static param_value_t const uncompressed_literals_opt_param_values[] = {
|
||||
{.param = ZSTD_c_compressionLevel, .value = 19},
|
||||
{.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_uncompressed},
|
||||
};
|
||||
|
||||
static config_t uncompressed_literals_opt = {
|
||||
.name = "uncompressed literals optimal",
|
||||
.cli_args = "-19 --no-compress-literals",
|
||||
.param_values = PARAM_VALUES(uncompressed_literals_opt_param_values),
|
||||
};
|
||||
|
||||
static param_value_t const huffman_literals_param_values[] = {
|
||||
{.param = ZSTD_c_compressionLevel, .value = -1},
|
||||
{.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_huffman},
|
||||
};
|
||||
|
||||
static config_t huffman_literals = {
|
||||
.name = "huffman literals",
|
||||
.cli_args = "--fast=1 --compress-literals",
|
||||
.param_values = PARAM_VALUES(huffman_literals_param_values),
|
||||
};
|
||||
|
||||
static param_value_t const explicit_params_param_values[] = {
|
||||
{.param = ZSTD_c_checksumFlag, .value = 1},
|
||||
{.param = ZSTD_c_contentSizeFlag, .value = 0},
|
||||
@@ -155,6 +199,10 @@ static config_t const* g_configs[] = {
|
||||
&small_hlog,
|
||||
&small_clog,
|
||||
&explicit_params,
|
||||
&uncompressed_literals,
|
||||
&uncompressed_literals_opt,
|
||||
&huffman_literals,
|
||||
&mt_advanced,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
+163
-58
@@ -175,8 +175,8 @@ static result_t compress_cctx_compress(
|
||||
state->compressed.capacity,
|
||||
input.data,
|
||||
input.size,
|
||||
state->dictionary.data,
|
||||
state->dictionary.size,
|
||||
config->use_dictionary ? state->dictionary.data : NULL,
|
||||
config->use_dictionary ? state->dictionary.size : 0,
|
||||
params);
|
||||
else if (config->use_dictionary)
|
||||
state->compressed.size = ZSTD_compress_usingDict(
|
||||
@@ -432,77 +432,158 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static result_t old_streaming_compress(
|
||||
method_state_t* base,
|
||||
config_t const* config) {
|
||||
buffer_state_t* state = container_of(base, buffer_state_t, base);
|
||||
|
||||
if (buffer_state_bad(state, config))
|
||||
return result_error(result_error_system_error);
|
||||
|
||||
int const level = config_get_level(config);
|
||||
if (level == CONFIG_NO_LEVEL)
|
||||
return result_error(result_error_skip);
|
||||
|
||||
ZSTD_CStream* zcs = ZSTD_createCStream();
|
||||
result_t result;
|
||||
if (zcs == NULL) {
|
||||
result = result_error(result_error_compression_error);
|
||||
goto out;
|
||||
}
|
||||
static int init_cstream(
|
||||
buffer_state_t* state,
|
||||
ZSTD_CStream* zcs,
|
||||
config_t const* config,
|
||||
int const advanced,
|
||||
ZSTD_CDict** cdict)
|
||||
{
|
||||
size_t zret;
|
||||
if (config->use_dictionary) {
|
||||
zret = ZSTD_initCStream_usingDict(
|
||||
zcs, state->dictionary.data, state->dictionary.size, level);
|
||||
if (advanced) {
|
||||
ZSTD_parameters const params = config_get_zstd_params(config, 0, 0);
|
||||
ZSTD_CDict* dict = NULL;
|
||||
if (cdict) {
|
||||
*cdict = ZSTD_createCDict_advanced(
|
||||
state->dictionary.data,
|
||||
state->dictionary.size,
|
||||
ZSTD_dlm_byRef,
|
||||
ZSTD_dct_auto,
|
||||
params.cParams,
|
||||
ZSTD_defaultCMem);
|
||||
if (!*cdict) {
|
||||
return 1;
|
||||
}
|
||||
zret = ZSTD_initCStream_usingCDict_advanced(
|
||||
zcs, *cdict, params.fParams, ZSTD_CONTENTSIZE_UNKNOWN);
|
||||
} else {
|
||||
zret = ZSTD_initCStream_advanced(
|
||||
zcs,
|
||||
state->dictionary.data,
|
||||
state->dictionary.size,
|
||||
params,
|
||||
ZSTD_CONTENTSIZE_UNKNOWN);
|
||||
}
|
||||
} else {
|
||||
zret = ZSTD_initCStream(zcs, level);
|
||||
int const level = config_get_level(config);
|
||||
if (cdict) {
|
||||
*cdict = ZSTD_createCDict(
|
||||
state->dictionary.data,
|
||||
state->dictionary.size,
|
||||
level);
|
||||
if (!*cdict) {
|
||||
return 1;
|
||||
}
|
||||
zret = ZSTD_initCStream_usingCDict(zcs, *cdict);
|
||||
} else if (config->use_dictionary) {
|
||||
zret = ZSTD_initCStream_usingDict(
|
||||
zcs, state->dictionary.data, state->dictionary.size, level);
|
||||
} else {
|
||||
zret = ZSTD_initCStream(zcs, level);
|
||||
}
|
||||
}
|
||||
if (ZSTD_isError(zret)) {
|
||||
result = result_error(result_error_compression_error);
|
||||
goto out;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static result_t old_streaming_compress_internal(
|
||||
method_state_t* base,
|
||||
config_t const* config,
|
||||
int const advanced,
|
||||
int const cdict) {
|
||||
buffer_state_t* state = container_of(base, buffer_state_t, base);
|
||||
|
||||
if (buffer_state_bad(state, config))
|
||||
return result_error(result_error_system_error);
|
||||
|
||||
|
||||
ZSTD_CStream* zcs = ZSTD_createCStream();
|
||||
ZSTD_CDict* cd = NULL;
|
||||
result_t result;
|
||||
if (zcs == NULL) {
|
||||
result = result_error(result_error_compression_error);
|
||||
goto out;
|
||||
}
|
||||
if (init_cstream(state, zcs, config, advanced, cdict ? &cd : NULL)) {
|
||||
result = result_error(result_error_compression_error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
result_data_t data = {.total_size = 0};
|
||||
for (size_t i = 0; i < state->inputs.size; ++i) {
|
||||
data_buffer_t input = state->inputs.buffers[i];
|
||||
size_t zret = ZSTD_resetCStream(
|
||||
zcs,
|
||||
config->no_pledged_src_size ? ZSTD_CONTENTSIZE_UNKNOWN : input.size);
|
||||
if (ZSTD_isError(zret)) {
|
||||
result = result_error(result_error_compression_error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
result_data_t data = {.total_size = 0};
|
||||
for (size_t i = 0; i < state->inputs.size; ++i) {
|
||||
data_buffer_t input = state->inputs.buffers[i];
|
||||
zret = ZSTD_resetCStream(
|
||||
zcs,
|
||||
config->no_pledged_src_size ? ZSTD_CONTENTSIZE_UNKNOWN
|
||||
: input.size);
|
||||
while (input.size > 0) {
|
||||
ZSTD_inBuffer in = {input.data, MIN(input.size, 4096)};
|
||||
input.data += in.size;
|
||||
input.size -= in.size;
|
||||
ZSTD_EndDirective const op =
|
||||
input.size > 0 ? ZSTD_e_continue : ZSTD_e_end;
|
||||
zret = 0;
|
||||
while (in.pos < in.size || (op == ZSTD_e_end && zret != 0)) {
|
||||
ZSTD_outBuffer out = {state->compressed.data,
|
||||
MIN(state->compressed.capacity, 1024)};
|
||||
if (op == ZSTD_e_continue || in.pos < in.size)
|
||||
zret = ZSTD_compressStream(zcs, &out, &in);
|
||||
else
|
||||
zret = ZSTD_endStream(zcs, &out);
|
||||
if (ZSTD_isError(zret)) {
|
||||
result = result_error(result_error_compression_error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (input.size > 0) {
|
||||
ZSTD_inBuffer in = {input.data, MIN(input.size, 4096)};
|
||||
input.data += in.size;
|
||||
input.size -= in.size;
|
||||
ZSTD_EndDirective const op =
|
||||
input.size > 0 ? ZSTD_e_continue : ZSTD_e_end;
|
||||
zret = 0;
|
||||
while (in.pos < in.size || (op == ZSTD_e_end && zret != 0)) {
|
||||
ZSTD_outBuffer out = {state->compressed.data,
|
||||
MIN(state->compressed.capacity, 1024)};
|
||||
if (op == ZSTD_e_continue || in.pos < in.size)
|
||||
zret = ZSTD_compressStream(zcs, &out, &in);
|
||||
else
|
||||
zret = ZSTD_endStream(zcs, &out);
|
||||
if (ZSTD_isError(zret)) {
|
||||
result = result_error(result_error_compression_error);
|
||||
goto out;
|
||||
}
|
||||
data.total_size += out.pos;
|
||||
}
|
||||
result = result_error(result_error_compression_error);
|
||||
goto out;
|
||||
}
|
||||
data.total_size += out.pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = result_data(data);
|
||||
result = result_data(data);
|
||||
out:
|
||||
ZSTD_freeCStream(zcs);
|
||||
ZSTD_freeCDict(cd);
|
||||
return result;
|
||||
}
|
||||
|
||||
static result_t old_streaming_compress(
|
||||
method_state_t* base,
|
||||
config_t const* config)
|
||||
{
|
||||
return old_streaming_compress_internal(
|
||||
base, config, /* advanced */ 0, /* cdict */ 0);
|
||||
}
|
||||
|
||||
static result_t old_streaming_compress_advanced(
|
||||
method_state_t* base,
|
||||
config_t const* config)
|
||||
{
|
||||
return old_streaming_compress_internal(
|
||||
base, config, /* advanced */ 1, /* cdict */ 0);
|
||||
}
|
||||
|
||||
static result_t old_streaming_compress_cdict(
|
||||
method_state_t* base,
|
||||
config_t const* config)
|
||||
{
|
||||
return old_streaming_compress_internal(
|
||||
base, config, /* advanced */ 0, /* cdict */ 1);
|
||||
}
|
||||
|
||||
static result_t old_streaming_compress_cdict_advanced(
|
||||
method_state_t* base,
|
||||
config_t const* config)
|
||||
{
|
||||
return old_streaming_compress_internal(
|
||||
base, config, /* advanced */ 1, /* cdict */ 1);
|
||||
}
|
||||
|
||||
method_t const simple = {
|
||||
.name = "compress simple",
|
||||
.create = buffer_state_create,
|
||||
@@ -545,6 +626,27 @@ method_t const old_streaming = {
|
||||
.destroy = buffer_state_destroy,
|
||||
};
|
||||
|
||||
method_t const old_streaming_advanced = {
|
||||
.name = "old streaming advanced",
|
||||
.create = buffer_state_create,
|
||||
.compress = old_streaming_compress,
|
||||
.destroy = buffer_state_destroy,
|
||||
};
|
||||
|
||||
method_t const old_streaming_cdict = {
|
||||
.name = "old streaming cdcit",
|
||||
.create = buffer_state_create,
|
||||
.compress = old_streaming_compress,
|
||||
.destroy = buffer_state_destroy,
|
||||
};
|
||||
|
||||
method_t const old_streaming_advanced_cdict = {
|
||||
.name = "old streaming advanced cdict",
|
||||
.create = buffer_state_create,
|
||||
.compress = old_streaming_compress,
|
||||
.destroy = buffer_state_destroy,
|
||||
};
|
||||
|
||||
method_t const cli = {
|
||||
.name = "zstdcli",
|
||||
.create = method_state_create,
|
||||
@@ -560,6 +662,9 @@ static method_t const* g_methods[] = {
|
||||
&advanced_one_pass_small_out,
|
||||
&advanced_streaming,
|
||||
&old_streaming,
|
||||
&old_streaming_advanced,
|
||||
&old_streaming_cdict,
|
||||
&old_streaming_advanced_cdict,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
+816
-448
@@ -1,448 +1,816 @@
|
||||
Data, Config, Method, Total compressed size
|
||||
silesia.tar, level -5, compress simple, 7160438
|
||||
silesia.tar, level -3, compress simple, 6789024
|
||||
silesia.tar, level -1, compress simple, 6195462
|
||||
silesia.tar, level 0, compress simple, 4875008
|
||||
silesia.tar, level 1, compress simple, 5339697
|
||||
silesia.tar, level 3, compress simple, 4875008
|
||||
silesia.tar, level 4, compress simple, 4813507
|
||||
silesia.tar, level 5, compress simple, 4722235
|
||||
silesia.tar, level 6, compress simple, 4672194
|
||||
silesia.tar, level 7, compress simple, 4606658
|
||||
silesia.tar, level 9, compress simple, 4554098
|
||||
silesia.tar, level 13, compress simple, 4491702
|
||||
silesia.tar, level 16, compress simple, 4381277
|
||||
silesia.tar, level 19, compress simple, 4281514
|
||||
silesia, level -5, compress cctx, 7152294
|
||||
silesia, level -3, compress cctx, 6789969
|
||||
silesia, level -1, compress cctx, 6191548
|
||||
silesia, level 0, compress cctx, 4862377
|
||||
silesia, level 1, compress cctx, 5318036
|
||||
silesia, level 3, compress cctx, 4862377
|
||||
silesia, level 4, compress cctx, 4800629
|
||||
silesia, level 5, compress cctx, 4710178
|
||||
silesia, level 6, compress cctx, 4659996
|
||||
silesia, level 7, compress cctx, 4596234
|
||||
silesia, level 9, compress cctx, 4543862
|
||||
silesia, level 13, compress cctx, 4482073
|
||||
silesia, level 16, compress cctx, 4377391
|
||||
silesia, level 19, compress cctx, 4293262
|
||||
silesia, long distance mode, compress cctx, 4862377
|
||||
silesia, multithreaded, compress cctx, 4862377
|
||||
silesia, multithreaded long distance mode, compress cctx, 4862377
|
||||
silesia, small window log, compress cctx, 7115734
|
||||
silesia, small hash log, compress cctx, 6554898
|
||||
silesia, small chain log, compress cctx, 4931093
|
||||
silesia, explicit params, compress cctx, 4813352
|
||||
github, level -5, compress cctx, 232744
|
||||
github, level -5 with dict, compress cctx, 47294
|
||||
github, level -3, compress cctx, 220611
|
||||
github, level -3 with dict, compress cctx, 48047
|
||||
github, level -1, compress cctx, 176575
|
||||
github, level -1 with dict, compress cctx, 43527
|
||||
github, level 0, compress cctx, 136397
|
||||
github, level 0 with dict, compress cctx, 41536
|
||||
github, level 1, compress cctx, 143457
|
||||
github, level 1 with dict, compress cctx, 42157
|
||||
github, level 3, compress cctx, 136397
|
||||
github, level 3 with dict, compress cctx, 41536
|
||||
github, level 4, compress cctx, 136144
|
||||
github, level 4 with dict, compress cctx, 41721
|
||||
github, level 5, compress cctx, 135106
|
||||
github, level 5 with dict, compress cctx, 38934
|
||||
github, level 6, compress cctx, 135108
|
||||
github, level 6 with dict, compress cctx, 38628
|
||||
github, level 7, compress cctx, 135108
|
||||
github, level 7 with dict, compress cctx, 38741
|
||||
github, level 9, compress cctx, 135108
|
||||
github, level 9 with dict, compress cctx, 39335
|
||||
github, level 13, compress cctx, 133717
|
||||
github, level 13 with dict, compress cctx, 39923
|
||||
github, level 16, compress cctx, 133717
|
||||
github, level 16 with dict, compress cctx, 37568
|
||||
github, level 19, compress cctx, 133717
|
||||
github, level 19 with dict, compress cctx, 37567
|
||||
github, long distance mode, compress cctx, decompression error
|
||||
github, multithreaded, compress cctx, decompression error
|
||||
github, multithreaded long distance mode, compress cctx, decompression error
|
||||
github, small window log, compress cctx, decompression error
|
||||
github, small hash log, compress cctx, decompression error
|
||||
github, small chain log, compress cctx, decompression error
|
||||
github, explicit params, compress cctx, decompression error
|
||||
silesia, level -5, zstdcli, 7152342
|
||||
silesia, level -3, zstdcli, 6790021
|
||||
silesia, level -1, zstdcli, 6191597
|
||||
silesia, level 0, zstdcli, 4862425
|
||||
silesia, level 1, zstdcli, 5318084
|
||||
silesia, level 3, zstdcli, 4862425
|
||||
silesia, level 4, zstdcli, 4800677
|
||||
silesia, level 5, zstdcli, 4710226
|
||||
silesia, level 6, zstdcli, 4660044
|
||||
silesia, level 7, zstdcli, 4596282
|
||||
silesia, level 9, zstdcli, 4543910
|
||||
silesia, level 13, zstdcli, 4482121
|
||||
silesia, level 16, zstdcli, 4377439
|
||||
silesia, level 19, zstdcli, 4293310
|
||||
silesia, long distance mode, zstdcli, 4853437
|
||||
silesia, multithreaded, zstdcli, 4862425
|
||||
silesia, multithreaded long distance mode, zstdcli, 4853437
|
||||
silesia, small window log, zstdcli, 7126434
|
||||
silesia, small hash log, zstdcli, 6554946
|
||||
silesia, small chain log, zstdcli, 4931141
|
||||
silesia, explicit params, zstdcli, 4815380
|
||||
silesia.tar, level -5, zstdcli, 7161160
|
||||
silesia.tar, level -3, zstdcli, 6789865
|
||||
silesia.tar, level -1, zstdcli, 6196433
|
||||
silesia.tar, level 0, zstdcli, 4875136
|
||||
silesia.tar, level 1, zstdcli, 5340573
|
||||
silesia.tar, level 3, zstdcli, 4875136
|
||||
silesia.tar, level 4, zstdcli, 4814531
|
||||
silesia.tar, level 5, zstdcli, 4723284
|
||||
silesia.tar, level 6, zstdcli, 4673591
|
||||
silesia.tar, level 7, zstdcli, 4608342
|
||||
silesia.tar, level 9, zstdcli, 4554700
|
||||
silesia.tar, level 13, zstdcli, 4491706
|
||||
silesia.tar, level 16, zstdcli, 4381281
|
||||
silesia.tar, level 19, zstdcli, 4281518
|
||||
silesia.tar, no source size, zstdcli, 4875132
|
||||
silesia.tar, long distance mode, zstdcli, 4866975
|
||||
silesia.tar, multithreaded, zstdcli, 4875136
|
||||
silesia.tar, multithreaded long distance mode, zstdcli, 4866975
|
||||
silesia.tar, small window log, zstdcli, 7130434
|
||||
silesia.tar, small hash log, zstdcli, 6587841
|
||||
silesia.tar, small chain log, zstdcli, 4943259
|
||||
silesia.tar, explicit params, zstdcli, 4839202
|
||||
github, level -5, zstdcli, 234744
|
||||
github, level -5 with dict, zstdcli, 48718
|
||||
github, level -3, zstdcli, 222611
|
||||
github, level -3 with dict, zstdcli, 47395
|
||||
github, level -1, zstdcli, 178575
|
||||
github, level -1 with dict, zstdcli, 45170
|
||||
github, level 0, zstdcli, 138397
|
||||
github, level 0 with dict, zstdcli, 43170
|
||||
github, level 1, zstdcli, 145457
|
||||
github, level 1 with dict, zstdcli, 43682
|
||||
github, level 3, zstdcli, 138397
|
||||
github, level 3 with dict, zstdcli, 43170
|
||||
github, level 4, zstdcli, 138144
|
||||
github, level 4 with dict, zstdcli, 43306
|
||||
github, level 5, zstdcli, 137106
|
||||
github, level 5 with dict, zstdcli, 40938
|
||||
github, level 6, zstdcli, 137108
|
||||
github, level 6 with dict, zstdcli, 40632
|
||||
github, level 7, zstdcli, 137108
|
||||
github, level 7 with dict, zstdcli, 40766
|
||||
github, level 9, zstdcli, 137108
|
||||
github, level 9 with dict, zstdcli, 41326
|
||||
github, level 13, zstdcli, 135717
|
||||
github, level 13 with dict, zstdcli, 41716
|
||||
github, level 16, zstdcli, 135717
|
||||
github, level 16 with dict, zstdcli, 39577
|
||||
github, level 19, zstdcli, 135717
|
||||
github, level 19 with dict, zstdcli, 39576
|
||||
github, long distance mode, zstdcli, 138397
|
||||
github, multithreaded, zstdcli, 138397
|
||||
github, multithreaded long distance mode, zstdcli, 138397
|
||||
github, small window log, zstdcli, 138397
|
||||
github, small hash log, zstdcli, 137467
|
||||
github, small chain log, zstdcli, 138314
|
||||
github, explicit params, zstdcli, 136140
|
||||
silesia, level -5, advanced one pass, 7152294
|
||||
silesia, level -3, advanced one pass, 6789969
|
||||
silesia, level -1, advanced one pass, 6191548
|
||||
silesia, level 0, advanced one pass, 4862377
|
||||
silesia, level 1, advanced one pass, 5318036
|
||||
silesia, level 3, advanced one pass, 4862377
|
||||
silesia, level 4, advanced one pass, 4800629
|
||||
silesia, level 5, advanced one pass, 4710178
|
||||
silesia, level 6, advanced one pass, 4659996
|
||||
silesia, level 7, advanced one pass, 4596234
|
||||
silesia, level 9, advanced one pass, 4543862
|
||||
silesia, level 13, advanced one pass, 4482073
|
||||
silesia, level 16, advanced one pass, 4377391
|
||||
silesia, level 19, advanced one pass, 4293262
|
||||
silesia, no source size, advanced one pass, 4862377
|
||||
silesia, long distance mode, advanced one pass, 4853389
|
||||
silesia, multithreaded, advanced one pass, 4862377
|
||||
silesia, multithreaded long distance mode, advanced one pass, 4853389
|
||||
silesia, small window log, advanced one pass, 7126386
|
||||
silesia, small hash log, advanced one pass, 6554898
|
||||
silesia, small chain log, advanced one pass, 4931093
|
||||
silesia, explicit params, advanced one pass, 4815369
|
||||
silesia.tar, level -5, advanced one pass, 7160438
|
||||
silesia.tar, level -3, advanced one pass, 6789024
|
||||
silesia.tar, level -1, advanced one pass, 6195462
|
||||
silesia.tar, level 0, advanced one pass, 4875008
|
||||
silesia.tar, level 1, advanced one pass, 5339697
|
||||
silesia.tar, level 3, advanced one pass, 4875008
|
||||
silesia.tar, level 4, advanced one pass, 4813507
|
||||
silesia.tar, level 5, advanced one pass, 4722235
|
||||
silesia.tar, level 6, advanced one pass, 4672194
|
||||
silesia.tar, level 7, advanced one pass, 4606658
|
||||
silesia.tar, level 9, advanced one pass, 4554098
|
||||
silesia.tar, level 13, advanced one pass, 4491702
|
||||
silesia.tar, level 16, advanced one pass, 4381277
|
||||
silesia.tar, level 19, advanced one pass, 4281514
|
||||
silesia.tar, no source size, advanced one pass, 4875008
|
||||
silesia.tar, long distance mode, advanced one pass, 4861218
|
||||
silesia.tar, multithreaded, advanced one pass, 4874631
|
||||
silesia.tar, multithreaded long distance mode, advanced one pass, 4860683
|
||||
silesia.tar, small window log, advanced one pass, 7130394
|
||||
silesia.tar, small hash log, advanced one pass, 6587833
|
||||
silesia.tar, small chain log, advanced one pass, 4943255
|
||||
silesia.tar, explicit params, advanced one pass, 4829974
|
||||
github, level -5, advanced one pass, 232744
|
||||
github, level -5 with dict, advanced one pass, 46718
|
||||
github, level -3, advanced one pass, 220611
|
||||
github, level -3 with dict, advanced one pass, 45395
|
||||
github, level -1, advanced one pass, 176575
|
||||
github, level -1 with dict, advanced one pass, 43170
|
||||
github, level 0, advanced one pass, 136397
|
||||
github, level 0 with dict, advanced one pass, 41170
|
||||
github, level 1, advanced one pass, 143457
|
||||
github, level 1 with dict, advanced one pass, 41682
|
||||
github, level 3, advanced one pass, 136397
|
||||
github, level 3 with dict, advanced one pass, 41170
|
||||
github, level 4, advanced one pass, 136144
|
||||
github, level 4 with dict, advanced one pass, 41306
|
||||
github, level 5, advanced one pass, 135106
|
||||
github, level 5 with dict, advanced one pass, 38938
|
||||
github, level 6, advanced one pass, 135108
|
||||
github, level 6 with dict, advanced one pass, 38632
|
||||
github, level 7, advanced one pass, 135108
|
||||
github, level 7 with dict, advanced one pass, 38766
|
||||
github, level 9, advanced one pass, 135108
|
||||
github, level 9 with dict, advanced one pass, 39326
|
||||
github, level 13, advanced one pass, 133717
|
||||
github, level 13 with dict, advanced one pass, 39716
|
||||
github, level 16, advanced one pass, 133717
|
||||
github, level 16 with dict, advanced one pass, 37577
|
||||
github, level 19, advanced one pass, 133717
|
||||
github, level 19 with dict, advanced one pass, 37576
|
||||
github, no source size, advanced one pass, 136397
|
||||
github, long distance mode, advanced one pass, 136397
|
||||
github, multithreaded, advanced one pass, 136397
|
||||
github, multithreaded long distance mode, advanced one pass, 136397
|
||||
github, small window log, advanced one pass, 136397
|
||||
github, small hash log, advanced one pass, 135467
|
||||
github, small chain log, advanced one pass, 136314
|
||||
github, explicit params, advanced one pass, 137670
|
||||
silesia, level -5, advanced one pass small out, 7152294
|
||||
silesia, level -3, advanced one pass small out, 6789969
|
||||
silesia, level -1, advanced one pass small out, 6191548
|
||||
silesia, level 0, advanced one pass small out, 4862377
|
||||
silesia, level 1, advanced one pass small out, 5318036
|
||||
silesia, level 3, advanced one pass small out, 4862377
|
||||
silesia, level 4, advanced one pass small out, 4800629
|
||||
silesia, level 5, advanced one pass small out, 4710178
|
||||
silesia, level 6, advanced one pass small out, 4659996
|
||||
silesia, level 7, advanced one pass small out, 4596234
|
||||
silesia, level 9, advanced one pass small out, 4543862
|
||||
silesia, level 13, advanced one pass small out, 4482073
|
||||
silesia, level 16, advanced one pass small out, 4377391
|
||||
silesia, level 19, advanced one pass small out, 4293262
|
||||
silesia, no source size, advanced one pass small out, 4862377
|
||||
silesia, long distance mode, advanced one pass small out, 4853389
|
||||
silesia, multithreaded, advanced one pass small out, 4862377
|
||||
silesia, multithreaded long distance mode, advanced one pass small out, 4853389
|
||||
silesia, small window log, advanced one pass small out, 7126386
|
||||
silesia, small hash log, advanced one pass small out, 6554898
|
||||
silesia, small chain log, advanced one pass small out, 4931093
|
||||
silesia, explicit params, advanced one pass small out, 4815369
|
||||
silesia.tar, level -5, advanced one pass small out, 7160438
|
||||
silesia.tar, level -3, advanced one pass small out, 6789024
|
||||
silesia.tar, level -1, advanced one pass small out, 6195462
|
||||
silesia.tar, level 0, advanced one pass small out, 4875008
|
||||
silesia.tar, level 1, advanced one pass small out, 5339697
|
||||
silesia.tar, level 3, advanced one pass small out, 4875008
|
||||
silesia.tar, level 4, advanced one pass small out, 4813507
|
||||
silesia.tar, level 5, advanced one pass small out, 4722235
|
||||
silesia.tar, level 6, advanced one pass small out, 4672194
|
||||
silesia.tar, level 7, advanced one pass small out, 4606658
|
||||
silesia.tar, level 9, advanced one pass small out, 4554098
|
||||
silesia.tar, level 13, advanced one pass small out, 4491702
|
||||
silesia.tar, level 16, advanced one pass small out, 4381277
|
||||
silesia.tar, level 19, advanced one pass small out, 4281514
|
||||
silesia.tar, no source size, advanced one pass small out, 4875008
|
||||
silesia.tar, long distance mode, advanced one pass small out, 4861218
|
||||
silesia.tar, multithreaded, advanced one pass small out, 4874631
|
||||
silesia.tar, multithreaded long distance mode, advanced one pass small out, 4860683
|
||||
silesia.tar, small window log, advanced one pass small out, 7130394
|
||||
silesia.tar, small hash log, advanced one pass small out, 6587833
|
||||
silesia.tar, small chain log, advanced one pass small out, 4943255
|
||||
silesia.tar, explicit params, advanced one pass small out, 4829974
|
||||
github, level -5, advanced one pass small out, 232744
|
||||
github, level -5 with dict, advanced one pass small out, 46718
|
||||
github, level -3, advanced one pass small out, 220611
|
||||
github, level -3 with dict, advanced one pass small out, 45395
|
||||
github, level -1, advanced one pass small out, 176575
|
||||
github, level -1 with dict, advanced one pass small out, 43170
|
||||
github, level 0, advanced one pass small out, 136397
|
||||
github, level 0 with dict, advanced one pass small out, 41170
|
||||
github, level 1, advanced one pass small out, 143457
|
||||
github, level 1 with dict, advanced one pass small out, 41682
|
||||
github, level 3, advanced one pass small out, 136397
|
||||
github, level 3 with dict, advanced one pass small out, 41170
|
||||
github, level 4, advanced one pass small out, 136144
|
||||
github, level 4 with dict, advanced one pass small out, 41306
|
||||
github, level 5, advanced one pass small out, 135106
|
||||
github, level 5 with dict, advanced one pass small out, 38938
|
||||
github, level 6, advanced one pass small out, 135108
|
||||
github, level 6 with dict, advanced one pass small out, 38632
|
||||
github, level 7, advanced one pass small out, 135108
|
||||
github, level 7 with dict, advanced one pass small out, 38766
|
||||
github, level 9, advanced one pass small out, 135108
|
||||
github, level 9 with dict, advanced one pass small out, 39326
|
||||
github, level 13, advanced one pass small out, 133717
|
||||
github, level 13 with dict, advanced one pass small out, 39716
|
||||
github, level 16, advanced one pass small out, 133717
|
||||
github, level 16 with dict, advanced one pass small out, 37577
|
||||
github, level 19, advanced one pass small out, 133717
|
||||
github, level 19 with dict, advanced one pass small out, 37576
|
||||
github, no source size, advanced one pass small out, 136397
|
||||
github, long distance mode, advanced one pass small out, 136397
|
||||
github, multithreaded, advanced one pass small out, 136397
|
||||
github, multithreaded long distance mode, advanced one pass small out, 136397
|
||||
github, small window log, advanced one pass small out, 136397
|
||||
github, small hash log, advanced one pass small out, 135467
|
||||
github, small chain log, advanced one pass small out, 136314
|
||||
github, explicit params, advanced one pass small out, 137670
|
||||
silesia, level -5, advanced streaming, 7152294
|
||||
silesia, level -3, advanced streaming, 6789973
|
||||
silesia, level -1, advanced streaming, 6191549
|
||||
silesia, level 0, advanced streaming, 4862377
|
||||
silesia, level 1, advanced streaming, 5318036
|
||||
silesia, level 3, advanced streaming, 4862377
|
||||
silesia, level 4, advanced streaming, 4800629
|
||||
silesia, level 5, advanced streaming, 4710178
|
||||
silesia, level 6, advanced streaming, 4659996
|
||||
silesia, level 7, advanced streaming, 4596234
|
||||
silesia, level 9, advanced streaming, 4543862
|
||||
silesia, level 13, advanced streaming, 4482073
|
||||
silesia, level 16, advanced streaming, 4377391
|
||||
silesia, level 19, advanced streaming, 4293262
|
||||
silesia, no source size, advanced streaming, 4862341
|
||||
silesia, long distance mode, advanced streaming, 4853389
|
||||
silesia, multithreaded, advanced streaming, 4862377
|
||||
silesia, multithreaded long distance mode, advanced streaming, 4853389
|
||||
silesia, small window log, advanced streaming, 7126389
|
||||
silesia, small hash log, advanced streaming, 6554898
|
||||
silesia, small chain log, advanced streaming, 4931093
|
||||
silesia, explicit params, advanced streaming, 4815380
|
||||
silesia.tar, level -5, advanced streaming, 7160440
|
||||
silesia.tar, level -3, advanced streaming, 6789026
|
||||
silesia.tar, level -1, advanced streaming, 6195465
|
||||
silesia.tar, level 0, advanced streaming, 4875010
|
||||
silesia.tar, level 1, advanced streaming, 5339701
|
||||
silesia.tar, level 3, advanced streaming, 4875010
|
||||
silesia.tar, level 4, advanced streaming, 4813507
|
||||
silesia.tar, level 5, advanced streaming, 4722240
|
||||
silesia.tar, level 6, advanced streaming, 4672203
|
||||
silesia.tar, level 7, advanced streaming, 4606658
|
||||
silesia.tar, level 9, advanced streaming, 4554105
|
||||
silesia.tar, level 13, advanced streaming, 4491703
|
||||
silesia.tar, level 16, advanced streaming, 4381277
|
||||
silesia.tar, level 19, advanced streaming, 4281514
|
||||
silesia.tar, no source size, advanced streaming, 4875006
|
||||
silesia.tar, long distance mode, advanced streaming, 4861218
|
||||
silesia.tar, multithreaded, advanced streaming, 4875132
|
||||
silesia.tar, multithreaded long distance mode, advanced streaming, 4866971
|
||||
silesia.tar, small window log, advanced streaming, 7130394
|
||||
silesia.tar, small hash log, advanced streaming, 6587834
|
||||
silesia.tar, small chain log, advanced streaming, 4943260
|
||||
silesia.tar, explicit params, advanced streaming, 4830002
|
||||
github, level -5, advanced streaming, 232744
|
||||
github, level -5 with dict, advanced streaming, 46718
|
||||
github, level -3, advanced streaming, 220611
|
||||
github, level -3 with dict, advanced streaming, 45395
|
||||
github, level -1, advanced streaming, 176575
|
||||
github, level -1 with dict, advanced streaming, 43170
|
||||
github, level 0, advanced streaming, 136397
|
||||
github, level 0 with dict, advanced streaming, 41170
|
||||
github, level 1, advanced streaming, 143457
|
||||
github, level 1 with dict, advanced streaming, 41682
|
||||
github, level 3, advanced streaming, 136397
|
||||
github, level 3 with dict, advanced streaming, 41170
|
||||
github, level 4, advanced streaming, 136144
|
||||
github, level 4 with dict, advanced streaming, 41306
|
||||
github, level 5, advanced streaming, 135106
|
||||
github, level 5 with dict, advanced streaming, 38938
|
||||
github, level 6, advanced streaming, 135108
|
||||
github, level 6 with dict, advanced streaming, 38632
|
||||
github, level 7, advanced streaming, 135108
|
||||
github, level 7 with dict, advanced streaming, 38766
|
||||
github, level 9, advanced streaming, 135108
|
||||
github, level 9 with dict, advanced streaming, 39326
|
||||
github, level 13, advanced streaming, 133717
|
||||
github, level 13 with dict, advanced streaming, 39716
|
||||
github, level 16, advanced streaming, 133717
|
||||
github, level 16 with dict, advanced streaming, 37577
|
||||
github, level 19, advanced streaming, 133717
|
||||
github, level 19 with dict, advanced streaming, 37576
|
||||
github, no source size, advanced streaming, 136397
|
||||
github, long distance mode, advanced streaming, 136397
|
||||
github, multithreaded, advanced streaming, 136397
|
||||
github, multithreaded long distance mode, advanced streaming, 136397
|
||||
github, small window log, advanced streaming, 136397
|
||||
github, small hash log, advanced streaming, 135467
|
||||
github, small chain log, advanced streaming, 136314
|
||||
github, explicit params, advanced streaming, 137670
|
||||
silesia, level -5, old streaming, 7152294
|
||||
silesia, level -3, old streaming, 6789973
|
||||
silesia, level -1, old streaming, 6191549
|
||||
silesia, level 0, old streaming, 4862377
|
||||
silesia, level 1, old streaming, 5318036
|
||||
silesia, level 3, old streaming, 4862377
|
||||
silesia, level 4, old streaming, 4800629
|
||||
silesia, level 5, old streaming, 4710178
|
||||
silesia, level 6, old streaming, 4659996
|
||||
silesia, level 7, old streaming, 4596234
|
||||
silesia, level 9, old streaming, 4543862
|
||||
silesia, level 13, old streaming, 4482073
|
||||
silesia, level 16, old streaming, 4377391
|
||||
silesia, level 19, old streaming, 4293262
|
||||
silesia, no source size, old streaming, 4862341
|
||||
silesia.tar, level -5, old streaming, 7160440
|
||||
silesia.tar, level -3, old streaming, 6789026
|
||||
silesia.tar, level -1, old streaming, 6195465
|
||||
silesia.tar, level 0, old streaming, 4875010
|
||||
silesia.tar, level 1, old streaming, 5339701
|
||||
silesia.tar, level 3, old streaming, 4875010
|
||||
silesia.tar, level 4, old streaming, 4813507
|
||||
silesia.tar, level 5, old streaming, 4722240
|
||||
silesia.tar, level 6, old streaming, 4672203
|
||||
silesia.tar, level 7, old streaming, 4606658
|
||||
silesia.tar, level 9, old streaming, 4554105
|
||||
silesia.tar, level 13, old streaming, 4491703
|
||||
silesia.tar, level 16, old streaming, 4381277
|
||||
silesia.tar, level 19, old streaming, 4281514
|
||||
silesia.tar, no source size, old streaming, 4875006
|
||||
github, level -5, old streaming, 232744
|
||||
github, level -5 with dict, old streaming, 46718
|
||||
github, level -3, old streaming, 220611
|
||||
github, level -3 with dict, old streaming, 45395
|
||||
github, level -1, old streaming, 176575
|
||||
github, level -1 with dict, old streaming, 43170
|
||||
github, level 0, old streaming, 136397
|
||||
github, level 0 with dict, old streaming, 41170
|
||||
github, level 1, old streaming, 143457
|
||||
github, level 1 with dict, old streaming, 41682
|
||||
github, level 3, old streaming, 136397
|
||||
github, level 3 with dict, old streaming, 41170
|
||||
github, level 4, old streaming, 136144
|
||||
github, level 4 with dict, old streaming, 41306
|
||||
github, level 5, old streaming, 135106
|
||||
github, level 5 with dict, old streaming, 38938
|
||||
github, level 6, old streaming, 135108
|
||||
github, level 6 with dict, old streaming, 38632
|
||||
github, level 7, old streaming, 135108
|
||||
github, level 7 with dict, old streaming, 38766
|
||||
github, level 9, old streaming, 135108
|
||||
github, level 9 with dict, old streaming, 39326
|
||||
github, level 13, old streaming, 133717
|
||||
github, level 13 with dict, old streaming, 39716
|
||||
github, level 16, old streaming, 133717
|
||||
github, level 16 with dict, old streaming, 37577
|
||||
github, level 19, old streaming, 133717
|
||||
github, level 19 with dict, old streaming, 37576
|
||||
github, no source size, old streaming, 141003
|
||||
Data, Config, Method, Total compressed size
|
||||
silesia.tar, level -5, compress simple, 6738558
|
||||
silesia.tar, level -3, compress simple, 6446362
|
||||
silesia.tar, level -1, compress simple, 6186038
|
||||
silesia.tar, level 0, compress simple, 4861374
|
||||
silesia.tar, level 1, compress simple, 5334825
|
||||
silesia.tar, level 3, compress simple, 4861374
|
||||
silesia.tar, level 4, compress simple, 4799583
|
||||
silesia.tar, level 5, compress simple, 4722271
|
||||
silesia.tar, level 6, compress simple, 4672231
|
||||
silesia.tar, level 7, compress simple, 4606657
|
||||
silesia.tar, level 9, compress simple, 4554099
|
||||
silesia.tar, level 13, compress simple, 4491706
|
||||
silesia.tar, level 16, compress simple, 4381265
|
||||
silesia.tar, level 19, compress simple, 4281551
|
||||
silesia.tar, uncompressed literals, compress simple, 4861374
|
||||
silesia.tar, uncompressed literals optimal, compress simple, 4281551
|
||||
silesia.tar, huffman literals, compress simple, 6186038
|
||||
silesia, level -5, compress cctx, 6737567
|
||||
silesia, level -3, compress cctx, 6444663
|
||||
silesia, level -1, compress cctx, 6178442
|
||||
silesia, level 0, compress cctx, 4849491
|
||||
silesia, level 1, compress cctx, 5313144
|
||||
silesia, level 3, compress cctx, 4849491
|
||||
silesia, level 4, compress cctx, 4786913
|
||||
silesia, level 5, compress cctx, 4710178
|
||||
silesia, level 6, compress cctx, 4659996
|
||||
silesia, level 7, compress cctx, 4596234
|
||||
silesia, level 9, compress cctx, 4543862
|
||||
silesia, level 13, compress cctx, 4482073
|
||||
silesia, level 16, compress cctx, 4377389
|
||||
silesia, level 19, compress cctx, 4293262
|
||||
silesia, long distance mode, compress cctx, 4849491
|
||||
silesia, multithreaded, compress cctx, 4849491
|
||||
silesia, multithreaded long distance mode, compress cctx, 4849491
|
||||
silesia, small window log, compress cctx, 7112784
|
||||
silesia, small hash log, compress cctx, 6554898
|
||||
silesia, small chain log, compress cctx, 4931093
|
||||
silesia, explicit params, compress cctx, 4794609
|
||||
silesia, uncompressed literals, compress cctx, 4849491
|
||||
silesia, uncompressed literals optimal, compress cctx, 4293262
|
||||
silesia, huffman literals, compress cctx, 6178442
|
||||
silesia, multithreaded with advanced params, compress cctx, 4849491
|
||||
github, level -5, compress cctx, 205285
|
||||
github, level -5 with dict, compress cctx, 47294
|
||||
github, level -3, compress cctx, 190643
|
||||
github, level -3 with dict, compress cctx, 48047
|
||||
github, level -1, compress cctx, 175568
|
||||
github, level -1 with dict, compress cctx, 43527
|
||||
github, level 0, compress cctx, 136311
|
||||
github, level 0 with dict, compress cctx, 41534
|
||||
github, level 1, compress cctx, 142450
|
||||
github, level 1 with dict, compress cctx, 42157
|
||||
github, level 3, compress cctx, 136311
|
||||
github, level 3 with dict, compress cctx, 41534
|
||||
github, level 4, compress cctx, 136144
|
||||
github, level 4 with dict, compress cctx, 41725
|
||||
github, level 5, compress cctx, 135106
|
||||
github, level 5 with dict, compress cctx, 38934
|
||||
github, level 6, compress cctx, 135108
|
||||
github, level 6 with dict, compress cctx, 38628
|
||||
github, level 7, compress cctx, 135108
|
||||
github, level 7 with dict, compress cctx, 38741
|
||||
github, level 9, compress cctx, 135108
|
||||
github, level 9 with dict, compress cctx, 39335
|
||||
github, level 13, compress cctx, 133717
|
||||
github, level 13 with dict, compress cctx, 39923
|
||||
github, level 16, compress cctx, 133717
|
||||
github, level 16 with dict, compress cctx, 37568
|
||||
github, level 19, compress cctx, 133717
|
||||
github, level 19 with dict, compress cctx, 37567
|
||||
github, long distance mode, compress cctx, 141101
|
||||
github, multithreaded, compress cctx, 141101
|
||||
github, multithreaded long distance mode, compress cctx, 141101
|
||||
github, small window log, compress cctx, 141101
|
||||
github, small hash log, compress cctx, 138943
|
||||
github, small chain log, compress cctx, 139239
|
||||
github, explicit params, compress cctx, 140924
|
||||
github, uncompressed literals, compress cctx, 136311
|
||||
github, uncompressed literals optimal, compress cctx, 133717
|
||||
github, huffman literals, compress cctx, 175568
|
||||
github, multithreaded with advanced params, compress cctx, 141101
|
||||
silesia, level -5, zstdcli, 6882514
|
||||
silesia, level -3, zstdcli, 6568406
|
||||
silesia, level -1, zstdcli, 6183433
|
||||
silesia, level 0, zstdcli, 4849539
|
||||
silesia, level 1, zstdcli, 5314157
|
||||
silesia, level 3, zstdcli, 4849539
|
||||
silesia, level 4, zstdcli, 4786961
|
||||
silesia, level 5, zstdcli, 4710226
|
||||
silesia, level 6, zstdcli, 4660044
|
||||
silesia, level 7, zstdcli, 4596282
|
||||
silesia, level 9, zstdcli, 4543910
|
||||
silesia, level 13, zstdcli, 4482121
|
||||
silesia, level 16, zstdcli, 4377437
|
||||
silesia, level 19, zstdcli, 4293310
|
||||
silesia, long distance mode, zstdcli, 4839698
|
||||
silesia, multithreaded, zstdcli, 4849539
|
||||
silesia, multithreaded long distance mode, zstdcli, 4839698
|
||||
silesia, small window log, zstdcli, 7123892
|
||||
silesia, small hash log, zstdcli, 6554946
|
||||
silesia, small chain log, zstdcli, 4931141
|
||||
silesia, explicit params, zstdcli, 4797048
|
||||
silesia, uncompressed literals, zstdcli, 5128008
|
||||
silesia, uncompressed literals optimal, zstdcli, 4325482
|
||||
silesia, huffman literals, zstdcli, 5331158
|
||||
silesia, multithreaded with advanced params, zstdcli, 5128008
|
||||
silesia.tar, level -5, zstdcli, 6738906
|
||||
silesia.tar, level -3, zstdcli, 6448409
|
||||
silesia.tar, level -1, zstdcli, 6186908
|
||||
silesia.tar, level 0, zstdcli, 4861462
|
||||
silesia.tar, level 1, zstdcli, 5336255
|
||||
silesia.tar, level 3, zstdcli, 4861462
|
||||
silesia.tar, level 4, zstdcli, 4800482
|
||||
silesia.tar, level 5, zstdcli, 4723312
|
||||
silesia.tar, level 6, zstdcli, 4673616
|
||||
silesia.tar, level 7, zstdcli, 4608346
|
||||
silesia.tar, level 9, zstdcli, 4554702
|
||||
silesia.tar, level 13, zstdcli, 4491710
|
||||
silesia.tar, level 16, zstdcli, 4381269
|
||||
silesia.tar, level 19, zstdcli, 4281555
|
||||
silesia.tar, no source size, zstdcli, 4861458
|
||||
silesia.tar, long distance mode, zstdcli, 4853140
|
||||
silesia.tar, multithreaded, zstdcli, 4861462
|
||||
silesia.tar, multithreaded long distance mode, zstdcli, 4853140
|
||||
silesia.tar, small window log, zstdcli, 7127964
|
||||
silesia.tar, small hash log, zstdcli, 6587841
|
||||
silesia.tar, small chain log, zstdcli, 4943269
|
||||
silesia.tar, explicit params, zstdcli, 4822318
|
||||
silesia.tar, uncompressed literals, zstdcli, 5129548
|
||||
silesia.tar, uncompressed literals optimal, zstdcli, 4320914
|
||||
silesia.tar, huffman literals, zstdcli, 5347560
|
||||
silesia.tar, multithreaded with advanced params, zstdcli, 5129548
|
||||
github, level -5, zstdcli, 207285
|
||||
github, level -5 with dict, zstdcli, 48718
|
||||
github, level -3, zstdcli, 192643
|
||||
github, level -3 with dict, zstdcli, 47395
|
||||
github, level -1, zstdcli, 177568
|
||||
github, level -1 with dict, zstdcli, 45170
|
||||
github, level 0, zstdcli, 138311
|
||||
github, level 0 with dict, zstdcli, 43148
|
||||
github, level 1, zstdcli, 144450
|
||||
github, level 1 with dict, zstdcli, 43682
|
||||
github, level 3, zstdcli, 138311
|
||||
github, level 3 with dict, zstdcli, 43148
|
||||
github, level 4, zstdcli, 138144
|
||||
github, level 4 with dict, zstdcli, 43251
|
||||
github, level 5, zstdcli, 137106
|
||||
github, level 5 with dict, zstdcli, 40938
|
||||
github, level 6, zstdcli, 137108
|
||||
github, level 6 with dict, zstdcli, 40632
|
||||
github, level 7, zstdcli, 137108
|
||||
github, level 7 with dict, zstdcli, 40766
|
||||
github, level 9, zstdcli, 137108
|
||||
github, level 9 with dict, zstdcli, 41326
|
||||
github, level 13, zstdcli, 135717
|
||||
github, level 13 with dict, zstdcli, 41716
|
||||
github, level 16, zstdcli, 135717
|
||||
github, level 16 with dict, zstdcli, 39577
|
||||
github, level 19, zstdcli, 135717
|
||||
github, level 19 with dict, zstdcli, 39576
|
||||
github, long distance mode, zstdcli, 138311
|
||||
github, multithreaded, zstdcli, 138311
|
||||
github, multithreaded long distance mode, zstdcli, 138311
|
||||
github, small window log, zstdcli, 138311
|
||||
github, small hash log, zstdcli, 137467
|
||||
github, small chain log, zstdcli, 138314
|
||||
github, explicit params, zstdcli, 136140
|
||||
github, uncompressed literals, zstdcli, 167915
|
||||
github, uncompressed literals optimal, zstdcli, 158824
|
||||
github, huffman literals, zstdcli, 144450
|
||||
github, multithreaded with advanced params, zstdcli, 167915
|
||||
silesia, level -5, advanced one pass, 6737567
|
||||
silesia, level -3, advanced one pass, 6444663
|
||||
silesia, level -1, advanced one pass, 6178442
|
||||
silesia, level 0, advanced one pass, 4849491
|
||||
silesia, level 1, advanced one pass, 5313144
|
||||
silesia, level 3, advanced one pass, 4849491
|
||||
silesia, level 4, advanced one pass, 4786913
|
||||
silesia, level 5, advanced one pass, 4710178
|
||||
silesia, level 6, advanced one pass, 4659996
|
||||
silesia, level 7, advanced one pass, 4596234
|
||||
silesia, level 9, advanced one pass, 4543862
|
||||
silesia, level 13, advanced one pass, 4482073
|
||||
silesia, level 16, advanced one pass, 4377389
|
||||
silesia, level 19, advanced one pass, 4293262
|
||||
silesia, no source size, advanced one pass, 4849491
|
||||
silesia, long distance mode, advanced one pass, 4839650
|
||||
silesia, multithreaded, advanced one pass, 4849491
|
||||
silesia, multithreaded long distance mode, advanced one pass, 4839650
|
||||
silesia, small window log, advanced one pass, 7123844
|
||||
silesia, small hash log, advanced one pass, 6554898
|
||||
silesia, small chain log, advanced one pass, 4931093
|
||||
silesia, explicit params, advanced one pass, 4797035
|
||||
silesia, uncompressed literals, advanced one pass, 5127960
|
||||
silesia, uncompressed literals optimal, advanced one pass, 4325434
|
||||
silesia, huffman literals, advanced one pass, 5326210
|
||||
silesia, multithreaded with advanced params, advanced one pass, 5127960
|
||||
silesia.tar, level -5, advanced one pass, 6738558
|
||||
silesia.tar, level -3, advanced one pass, 6446362
|
||||
silesia.tar, level -1, advanced one pass, 6186038
|
||||
silesia.tar, level 0, advanced one pass, 4861374
|
||||
silesia.tar, level 1, advanced one pass, 5334825
|
||||
silesia.tar, level 3, advanced one pass, 4861374
|
||||
silesia.tar, level 4, advanced one pass, 4799583
|
||||
silesia.tar, level 5, advanced one pass, 4722271
|
||||
silesia.tar, level 6, advanced one pass, 4672231
|
||||
silesia.tar, level 7, advanced one pass, 4606657
|
||||
silesia.tar, level 9, advanced one pass, 4554099
|
||||
silesia.tar, level 13, advanced one pass, 4491706
|
||||
silesia.tar, level 16, advanced one pass, 4381265
|
||||
silesia.tar, level 19, advanced one pass, 4281551
|
||||
silesia.tar, no source size, advanced one pass, 4861374
|
||||
silesia.tar, long distance mode, advanced one pass, 4848046
|
||||
silesia.tar, multithreaded, advanced one pass, 4860726
|
||||
silesia.tar, multithreaded long distance mode, advanced one pass, 4847343
|
||||
silesia.tar, small window log, advanced one pass, 7127924
|
||||
silesia.tar, small hash log, advanced one pass, 6587833
|
||||
silesia.tar, small chain log, advanced one pass, 4943266
|
||||
silesia.tar, explicit params, advanced one pass, 4808543
|
||||
silesia.tar, uncompressed literals, advanced one pass, 5129447
|
||||
silesia.tar, uncompressed literals optimal, advanced one pass, 4320910
|
||||
silesia.tar, huffman literals, advanced one pass, 5347283
|
||||
silesia.tar, multithreaded with advanced params, advanced one pass, 5129766
|
||||
github, level -5, advanced one pass, 205285
|
||||
github, level -5 with dict, advanced one pass, 46718
|
||||
github, level -3, advanced one pass, 190643
|
||||
github, level -3 with dict, advanced one pass, 45395
|
||||
github, level -1, advanced one pass, 175568
|
||||
github, level -1 with dict, advanced one pass, 43170
|
||||
github, level 0, advanced one pass, 136311
|
||||
github, level 0 with dict, advanced one pass, 41148
|
||||
github, level 1, advanced one pass, 142450
|
||||
github, level 1 with dict, advanced one pass, 41682
|
||||
github, level 3, advanced one pass, 136311
|
||||
github, level 3 with dict, advanced one pass, 41148
|
||||
github, level 4, advanced one pass, 136144
|
||||
github, level 4 with dict, advanced one pass, 41251
|
||||
github, level 5, advanced one pass, 135106
|
||||
github, level 5 with dict, advanced one pass, 38938
|
||||
github, level 6, advanced one pass, 135108
|
||||
github, level 6 with dict, advanced one pass, 38632
|
||||
github, level 7, advanced one pass, 135108
|
||||
github, level 7 with dict, advanced one pass, 38766
|
||||
github, level 9, advanced one pass, 135108
|
||||
github, level 9 with dict, advanced one pass, 39326
|
||||
github, level 13, advanced one pass, 133717
|
||||
github, level 13 with dict, advanced one pass, 39716
|
||||
github, level 16, advanced one pass, 133717
|
||||
github, level 16 with dict, advanced one pass, 37577
|
||||
github, level 19, advanced one pass, 133717
|
||||
github, level 19 with dict, advanced one pass, 37576
|
||||
github, no source size, advanced one pass, 136311
|
||||
github, long distance mode, advanced one pass, 136311
|
||||
github, multithreaded, advanced one pass, 136311
|
||||
github, multithreaded long distance mode, advanced one pass, 136311
|
||||
github, small window log, advanced one pass, 136311
|
||||
github, small hash log, advanced one pass, 135467
|
||||
github, small chain log, advanced one pass, 136314
|
||||
github, explicit params, advanced one pass, 137670
|
||||
github, uncompressed literals, advanced one pass, 165915
|
||||
github, uncompressed literals optimal, advanced one pass, 156824
|
||||
github, huffman literals, advanced one pass, 142450
|
||||
github, multithreaded with advanced params, advanced one pass, 165915
|
||||
silesia, level -5, advanced one pass small out, 6737567
|
||||
silesia, level -3, advanced one pass small out, 6444663
|
||||
silesia, level -1, advanced one pass small out, 6178442
|
||||
silesia, level 0, advanced one pass small out, 4849491
|
||||
silesia, level 1, advanced one pass small out, 5313144
|
||||
silesia, level 3, advanced one pass small out, 4849491
|
||||
silesia, level 4, advanced one pass small out, 4786913
|
||||
silesia, level 5, advanced one pass small out, 4710178
|
||||
silesia, level 6, advanced one pass small out, 4659996
|
||||
silesia, level 7, advanced one pass small out, 4596234
|
||||
silesia, level 9, advanced one pass small out, 4543862
|
||||
silesia, level 13, advanced one pass small out, 4482073
|
||||
silesia, level 16, advanced one pass small out, 4377389
|
||||
silesia, level 19, advanced one pass small out, 4293262
|
||||
silesia, no source size, advanced one pass small out, 4849491
|
||||
silesia, long distance mode, advanced one pass small out, 4839650
|
||||
silesia, multithreaded, advanced one pass small out, 4849491
|
||||
silesia, multithreaded long distance mode, advanced one pass small out, 4839650
|
||||
silesia, small window log, advanced one pass small out, 7123844
|
||||
silesia, small hash log, advanced one pass small out, 6554898
|
||||
silesia, small chain log, advanced one pass small out, 4931093
|
||||
silesia, explicit params, advanced one pass small out, 4797035
|
||||
silesia, uncompressed literals, advanced one pass small out, 5127960
|
||||
silesia, uncompressed literals optimal, advanced one pass small out, 4325434
|
||||
silesia, huffman literals, advanced one pass small out, 5326210
|
||||
silesia, multithreaded with advanced params, advanced one pass small out, 5127960
|
||||
silesia.tar, level -5, advanced one pass small out, 6738558
|
||||
silesia.tar, level -3, advanced one pass small out, 6446362
|
||||
silesia.tar, level -1, advanced one pass small out, 6186038
|
||||
silesia.tar, level 0, advanced one pass small out, 4861374
|
||||
silesia.tar, level 1, advanced one pass small out, 5334825
|
||||
silesia.tar, level 3, advanced one pass small out, 4861374
|
||||
silesia.tar, level 4, advanced one pass small out, 4799583
|
||||
silesia.tar, level 5, advanced one pass small out, 4722271
|
||||
silesia.tar, level 6, advanced one pass small out, 4672231
|
||||
silesia.tar, level 7, advanced one pass small out, 4606657
|
||||
silesia.tar, level 9, advanced one pass small out, 4554099
|
||||
silesia.tar, level 13, advanced one pass small out, 4491706
|
||||
silesia.tar, level 16, advanced one pass small out, 4381265
|
||||
silesia.tar, level 19, advanced one pass small out, 4281551
|
||||
silesia.tar, no source size, advanced one pass small out, 4861374
|
||||
silesia.tar, long distance mode, advanced one pass small out, 4848046
|
||||
silesia.tar, multithreaded, advanced one pass small out, 4860726
|
||||
silesia.tar, multithreaded long distance mode, advanced one pass small out, 4847343
|
||||
silesia.tar, small window log, advanced one pass small out, 7127924
|
||||
silesia.tar, small hash log, advanced one pass small out, 6587833
|
||||
silesia.tar, small chain log, advanced one pass small out, 4943266
|
||||
silesia.tar, explicit params, advanced one pass small out, 4808543
|
||||
silesia.tar, uncompressed literals, advanced one pass small out, 5129447
|
||||
silesia.tar, uncompressed literals optimal, advanced one pass small out, 4320910
|
||||
silesia.tar, huffman literals, advanced one pass small out, 5347283
|
||||
silesia.tar, multithreaded with advanced params, advanced one pass small out, 5129766
|
||||
github, level -5, advanced one pass small out, 205285
|
||||
github, level -5 with dict, advanced one pass small out, 46718
|
||||
github, level -3, advanced one pass small out, 190643
|
||||
github, level -3 with dict, advanced one pass small out, 45395
|
||||
github, level -1, advanced one pass small out, 175568
|
||||
github, level -1 with dict, advanced one pass small out, 43170
|
||||
github, level 0, advanced one pass small out, 136311
|
||||
github, level 0 with dict, advanced one pass small out, 41148
|
||||
github, level 1, advanced one pass small out, 142450
|
||||
github, level 1 with dict, advanced one pass small out, 41682
|
||||
github, level 3, advanced one pass small out, 136311
|
||||
github, level 3 with dict, advanced one pass small out, 41148
|
||||
github, level 4, advanced one pass small out, 136144
|
||||
github, level 4 with dict, advanced one pass small out, 41251
|
||||
github, level 5, advanced one pass small out, 135106
|
||||
github, level 5 with dict, advanced one pass small out, 38938
|
||||
github, level 6, advanced one pass small out, 135108
|
||||
github, level 6 with dict, advanced one pass small out, 38632
|
||||
github, level 7, advanced one pass small out, 135108
|
||||
github, level 7 with dict, advanced one pass small out, 38766
|
||||
github, level 9, advanced one pass small out, 135108
|
||||
github, level 9 with dict, advanced one pass small out, 39326
|
||||
github, level 13, advanced one pass small out, 133717
|
||||
github, level 13 with dict, advanced one pass small out, 39716
|
||||
github, level 16, advanced one pass small out, 133717
|
||||
github, level 16 with dict, advanced one pass small out, 37577
|
||||
github, level 19, advanced one pass small out, 133717
|
||||
github, level 19 with dict, advanced one pass small out, 37576
|
||||
github, no source size, advanced one pass small out, 136311
|
||||
github, long distance mode, advanced one pass small out, 136311
|
||||
github, multithreaded, advanced one pass small out, 136311
|
||||
github, multithreaded long distance mode, advanced one pass small out, 136311
|
||||
github, small window log, advanced one pass small out, 136311
|
||||
github, small hash log, advanced one pass small out, 135467
|
||||
github, small chain log, advanced one pass small out, 136314
|
||||
github, explicit params, advanced one pass small out, 137670
|
||||
github, uncompressed literals, advanced one pass small out, 165915
|
||||
github, uncompressed literals optimal, advanced one pass small out, 156824
|
||||
github, huffman literals, advanced one pass small out, 142450
|
||||
github, multithreaded with advanced params, advanced one pass small out, 165915
|
||||
silesia, level -5, advanced streaming, 6882466
|
||||
silesia, level -3, advanced streaming, 6568358
|
||||
silesia, level -1, advanced streaming, 6183385
|
||||
silesia, level 0, advanced streaming, 4849491
|
||||
silesia, level 1, advanced streaming, 5314109
|
||||
silesia, level 3, advanced streaming, 4849491
|
||||
silesia, level 4, advanced streaming, 4786913
|
||||
silesia, level 5, advanced streaming, 4710178
|
||||
silesia, level 6, advanced streaming, 4659996
|
||||
silesia, level 7, advanced streaming, 4596234
|
||||
silesia, level 9, advanced streaming, 4543862
|
||||
silesia, level 13, advanced streaming, 4482073
|
||||
silesia, level 16, advanced streaming, 4377389
|
||||
silesia, level 19, advanced streaming, 4293262
|
||||
silesia, no source size, advanced streaming, 4849455
|
||||
silesia, long distance mode, advanced streaming, 4839650
|
||||
silesia, multithreaded, advanced streaming, 4849491
|
||||
silesia, multithreaded long distance mode, advanced streaming, 4839650
|
||||
silesia, small window log, advanced streaming, 7123846
|
||||
silesia, small hash log, advanced streaming, 6554898
|
||||
silesia, small chain log, advanced streaming, 4931093
|
||||
silesia, explicit params, advanced streaming, 4797048
|
||||
silesia, uncompressed literals, advanced streaming, 5127960
|
||||
silesia, uncompressed literals optimal, advanced streaming, 4325434
|
||||
silesia, huffman literals, advanced streaming, 5331110
|
||||
silesia, multithreaded with advanced params, advanced streaming, 5127960
|
||||
silesia.tar, level -5, advanced streaming, 6982738
|
||||
silesia.tar, level -3, advanced streaming, 6641264
|
||||
silesia.tar, level -1, advanced streaming, 6190789
|
||||
silesia.tar, level 0, advanced streaming, 4861376
|
||||
silesia.tar, level 1, advanced streaming, 5336879
|
||||
silesia.tar, level 3, advanced streaming, 4861376
|
||||
silesia.tar, level 4, advanced streaming, 4799583
|
||||
silesia.tar, level 5, advanced streaming, 4722276
|
||||
silesia.tar, level 6, advanced streaming, 4672240
|
||||
silesia.tar, level 7, advanced streaming, 4606657
|
||||
silesia.tar, level 9, advanced streaming, 4554106
|
||||
silesia.tar, level 13, advanced streaming, 4491707
|
||||
silesia.tar, level 16, advanced streaming, 4381284
|
||||
silesia.tar, level 19, advanced streaming, 4281511
|
||||
silesia.tar, no source size, advanced streaming, 4861372
|
||||
silesia.tar, long distance mode, advanced streaming, 4848046
|
||||
silesia.tar, multithreaded, advanced streaming, 4861458
|
||||
silesia.tar, multithreaded long distance mode, advanced streaming, 4853136
|
||||
silesia.tar, small window log, advanced streaming, 7127924
|
||||
silesia.tar, small hash log, advanced streaming, 6587834
|
||||
silesia.tar, small chain log, advanced streaming, 4943271
|
||||
silesia.tar, explicit params, advanced streaming, 4808570
|
||||
silesia.tar, uncompressed literals, advanced streaming, 5129450
|
||||
silesia.tar, uncompressed literals optimal, advanced streaming, 4320841
|
||||
silesia.tar, huffman literals, advanced streaming, 5352306
|
||||
silesia.tar, multithreaded with advanced params, advanced streaming, 5129544
|
||||
github, level -5, advanced streaming, 205285
|
||||
github, level -5 with dict, advanced streaming, 46718
|
||||
github, level -3, advanced streaming, 190643
|
||||
github, level -3 with dict, advanced streaming, 45395
|
||||
github, level -1, advanced streaming, 175568
|
||||
github, level -1 with dict, advanced streaming, 43170
|
||||
github, level 0, advanced streaming, 136311
|
||||
github, level 0 with dict, advanced streaming, 41148
|
||||
github, level 1, advanced streaming, 142450
|
||||
github, level 1 with dict, advanced streaming, 41682
|
||||
github, level 3, advanced streaming, 136311
|
||||
github, level 3 with dict, advanced streaming, 41148
|
||||
github, level 4, advanced streaming, 136144
|
||||
github, level 4 with dict, advanced streaming, 41251
|
||||
github, level 5, advanced streaming, 135106
|
||||
github, level 5 with dict, advanced streaming, 38938
|
||||
github, level 6, advanced streaming, 135108
|
||||
github, level 6 with dict, advanced streaming, 38632
|
||||
github, level 7, advanced streaming, 135108
|
||||
github, level 7 with dict, advanced streaming, 38766
|
||||
github, level 9, advanced streaming, 135108
|
||||
github, level 9 with dict, advanced streaming, 39326
|
||||
github, level 13, advanced streaming, 133717
|
||||
github, level 13 with dict, advanced streaming, 39716
|
||||
github, level 16, advanced streaming, 133717
|
||||
github, level 16 with dict, advanced streaming, 37577
|
||||
github, level 19, advanced streaming, 133717
|
||||
github, level 19 with dict, advanced streaming, 37576
|
||||
github, no source size, advanced streaming, 136311
|
||||
github, long distance mode, advanced streaming, 136311
|
||||
github, multithreaded, advanced streaming, 136311
|
||||
github, multithreaded long distance mode, advanced streaming, 136311
|
||||
github, small window log, advanced streaming, 136311
|
||||
github, small hash log, advanced streaming, 135467
|
||||
github, small chain log, advanced streaming, 136314
|
||||
github, explicit params, advanced streaming, 137670
|
||||
github, uncompressed literals, advanced streaming, 165915
|
||||
github, uncompressed literals optimal, advanced streaming, 156824
|
||||
github, huffman literals, advanced streaming, 142450
|
||||
github, multithreaded with advanced params, advanced streaming, 165915
|
||||
silesia, level -5, old streaming, 6882466
|
||||
silesia, level -3, old streaming, 6568358
|
||||
silesia, level -1, old streaming, 6183385
|
||||
silesia, level 0, old streaming, 4849491
|
||||
silesia, level 1, old streaming, 5314109
|
||||
silesia, level 3, old streaming, 4849491
|
||||
silesia, level 4, old streaming, 4786913
|
||||
silesia, level 5, old streaming, 4710178
|
||||
silesia, level 6, old streaming, 4659996
|
||||
silesia, level 7, old streaming, 4596234
|
||||
silesia, level 9, old streaming, 4543862
|
||||
silesia, level 13, old streaming, 4482073
|
||||
silesia, level 16, old streaming, 4377389
|
||||
silesia, level 19, old streaming, 4293262
|
||||
silesia, no source size, old streaming, 4849455
|
||||
silesia, long distance mode, old streaming, 12000408
|
||||
silesia, multithreaded, old streaming, 12000408
|
||||
silesia, multithreaded long distance mode, old streaming, 12000408
|
||||
silesia, small window log, old streaming, 12000408
|
||||
silesia, small hash log, old streaming, 12000408
|
||||
silesia, small chain log, old streaming, 12000408
|
||||
silesia, explicit params, old streaming, 12000408
|
||||
silesia, uncompressed literals, old streaming, 4849491
|
||||
silesia, uncompressed literals optimal, old streaming, 4293262
|
||||
silesia, huffman literals, old streaming, 6183385
|
||||
silesia, multithreaded with advanced params, old streaming, 12000408
|
||||
silesia.tar, level -5, old streaming, 6982738
|
||||
silesia.tar, level -3, old streaming, 6641264
|
||||
silesia.tar, level -1, old streaming, 6190789
|
||||
silesia.tar, level 0, old streaming, 4861376
|
||||
silesia.tar, level 1, old streaming, 5336879
|
||||
silesia.tar, level 3, old streaming, 4861376
|
||||
silesia.tar, level 4, old streaming, 4799583
|
||||
silesia.tar, level 5, old streaming, 4722276
|
||||
silesia.tar, level 6, old streaming, 4672240
|
||||
silesia.tar, level 7, old streaming, 4606657
|
||||
silesia.tar, level 9, old streaming, 4554106
|
||||
silesia.tar, level 13, old streaming, 4491707
|
||||
silesia.tar, level 16, old streaming, 4381284
|
||||
silesia.tar, level 19, old streaming, 4281511
|
||||
silesia.tar, no source size, old streaming, 4861372
|
||||
silesia.tar, long distance mode, old streaming, 12022046
|
||||
silesia.tar, multithreaded, old streaming, 12022046
|
||||
silesia.tar, multithreaded long distance mode, old streaming, 12022046
|
||||
silesia.tar, small window log, old streaming, 12022046
|
||||
silesia.tar, small hash log, old streaming, 12022046
|
||||
silesia.tar, small chain log, old streaming, 12022046
|
||||
silesia.tar, explicit params, old streaming, 12022046
|
||||
silesia.tar, uncompressed literals, old streaming, 4861376
|
||||
silesia.tar, uncompressed literals optimal, old streaming, 4281511
|
||||
silesia.tar, huffman literals, old streaming, 6190789
|
||||
silesia.tar, multithreaded with advanced params, old streaming, 12022046
|
||||
github, level -5, old streaming, 205285
|
||||
github, level -5 with dict, old streaming, 46718
|
||||
github, level -3, old streaming, 190643
|
||||
github, level -3 with dict, old streaming, 45395
|
||||
github, level -1, old streaming, 175568
|
||||
github, level -1 with dict, old streaming, 43170
|
||||
github, level 0, old streaming, 136311
|
||||
github, level 0 with dict, old streaming, 41148
|
||||
github, level 1, old streaming, 142450
|
||||
github, level 1 with dict, old streaming, 41682
|
||||
github, level 3, old streaming, 136311
|
||||
github, level 3 with dict, old streaming, 41148
|
||||
github, level 4, old streaming, 136144
|
||||
github, level 4 with dict, old streaming, 41251
|
||||
github, level 5, old streaming, 135106
|
||||
github, level 5 with dict, old streaming, 38938
|
||||
github, level 6, old streaming, 135108
|
||||
github, level 6 with dict, old streaming, 38632
|
||||
github, level 7, old streaming, 135108
|
||||
github, level 7 with dict, old streaming, 38766
|
||||
github, level 9, old streaming, 135108
|
||||
github, level 9 with dict, old streaming, 39326
|
||||
github, level 13, old streaming, 133717
|
||||
github, level 13 with dict, old streaming, 39716
|
||||
github, level 16, old streaming, 133717
|
||||
github, level 16 with dict, old streaming, 37577
|
||||
github, level 19, old streaming, 133717
|
||||
github, level 19 with dict, old streaming, 37576
|
||||
github, no source size, old streaming, 140631
|
||||
github, long distance mode, old streaming, 412933
|
||||
github, multithreaded, old streaming, 412933
|
||||
github, multithreaded long distance mode, old streaming, 412933
|
||||
github, small window log, old streaming, 412933
|
||||
github, small hash log, old streaming, 412933
|
||||
github, small chain log, old streaming, 412933
|
||||
github, explicit params, old streaming, 412933
|
||||
github, uncompressed literals, old streaming, 136311
|
||||
github, uncompressed literals optimal, old streaming, 133717
|
||||
github, huffman literals, old streaming, 175568
|
||||
github, multithreaded with advanced params, old streaming, 412933
|
||||
silesia, level -5, old streaming advanced, 6882466
|
||||
silesia, level -3, old streaming advanced, 6568358
|
||||
silesia, level -1, old streaming advanced, 6183385
|
||||
silesia, level 0, old streaming advanced, 4849491
|
||||
silesia, level 1, old streaming advanced, 5314109
|
||||
silesia, level 3, old streaming advanced, 4849491
|
||||
silesia, level 4, old streaming advanced, 4786913
|
||||
silesia, level 5, old streaming advanced, 4710178
|
||||
silesia, level 6, old streaming advanced, 4659996
|
||||
silesia, level 7, old streaming advanced, 4596234
|
||||
silesia, level 9, old streaming advanced, 4543862
|
||||
silesia, level 13, old streaming advanced, 4482073
|
||||
silesia, level 16, old streaming advanced, 4377389
|
||||
silesia, level 19, old streaming advanced, 4293262
|
||||
silesia, no source size, old streaming advanced, 4849455
|
||||
silesia, long distance mode, old streaming advanced, 12000408
|
||||
silesia, multithreaded, old streaming advanced, 12000408
|
||||
silesia, multithreaded long distance mode, old streaming advanced, 12000408
|
||||
silesia, small window log, old streaming advanced, 12000408
|
||||
silesia, small hash log, old streaming advanced, 12000408
|
||||
silesia, small chain log, old streaming advanced, 12000408
|
||||
silesia, explicit params, old streaming advanced, 12000408
|
||||
silesia, uncompressed literals, old streaming advanced, 4849491
|
||||
silesia, uncompressed literals optimal, old streaming advanced, 4293262
|
||||
silesia, huffman literals, old streaming advanced, 6183385
|
||||
silesia, multithreaded with advanced params, old streaming advanced, 12000408
|
||||
silesia.tar, level -5, old streaming advanced, 6982738
|
||||
silesia.tar, level -3, old streaming advanced, 6641264
|
||||
silesia.tar, level -1, old streaming advanced, 6190789
|
||||
silesia.tar, level 0, old streaming advanced, 4861376
|
||||
silesia.tar, level 1, old streaming advanced, 5336879
|
||||
silesia.tar, level 3, old streaming advanced, 4861376
|
||||
silesia.tar, level 4, old streaming advanced, 4799583
|
||||
silesia.tar, level 5, old streaming advanced, 4722276
|
||||
silesia.tar, level 6, old streaming advanced, 4672240
|
||||
silesia.tar, level 7, old streaming advanced, 4606657
|
||||
silesia.tar, level 9, old streaming advanced, 4554106
|
||||
silesia.tar, level 13, old streaming advanced, 4491707
|
||||
silesia.tar, level 16, old streaming advanced, 4381284
|
||||
silesia.tar, level 19, old streaming advanced, 4281511
|
||||
silesia.tar, no source size, old streaming advanced, 4861372
|
||||
silesia.tar, long distance mode, old streaming advanced, 12022046
|
||||
silesia.tar, multithreaded, old streaming advanced, 12022046
|
||||
silesia.tar, multithreaded long distance mode, old streaming advanced, 12022046
|
||||
silesia.tar, small window log, old streaming advanced, 12022046
|
||||
silesia.tar, small hash log, old streaming advanced, 12022046
|
||||
silesia.tar, small chain log, old streaming advanced, 12022046
|
||||
silesia.tar, explicit params, old streaming advanced, 12022046
|
||||
silesia.tar, uncompressed literals, old streaming advanced, 4861376
|
||||
silesia.tar, uncompressed literals optimal, old streaming advanced, 4281511
|
||||
silesia.tar, huffman literals, old streaming advanced, 6190789
|
||||
silesia.tar, multithreaded with advanced params, old streaming advanced, 12022046
|
||||
github, level -5, old streaming advanced, 205285
|
||||
github, level -5 with dict, old streaming advanced, 46718
|
||||
github, level -3, old streaming advanced, 190643
|
||||
github, level -3 with dict, old streaming advanced, 45395
|
||||
github, level -1, old streaming advanced, 175568
|
||||
github, level -1 with dict, old streaming advanced, 43170
|
||||
github, level 0, old streaming advanced, 136311
|
||||
github, level 0 with dict, old streaming advanced, 41148
|
||||
github, level 1, old streaming advanced, 142450
|
||||
github, level 1 with dict, old streaming advanced, 41682
|
||||
github, level 3, old streaming advanced, 136311
|
||||
github, level 3 with dict, old streaming advanced, 41148
|
||||
github, level 4, old streaming advanced, 136144
|
||||
github, level 4 with dict, old streaming advanced, 41251
|
||||
github, level 5, old streaming advanced, 135106
|
||||
github, level 5 with dict, old streaming advanced, 38938
|
||||
github, level 6, old streaming advanced, 135108
|
||||
github, level 6 with dict, old streaming advanced, 38632
|
||||
github, level 7, old streaming advanced, 135108
|
||||
github, level 7 with dict, old streaming advanced, 38766
|
||||
github, level 9, old streaming advanced, 135108
|
||||
github, level 9 with dict, old streaming advanced, 39326
|
||||
github, level 13, old streaming advanced, 133717
|
||||
github, level 13 with dict, old streaming advanced, 39716
|
||||
github, level 16, old streaming advanced, 133717
|
||||
github, level 16 with dict, old streaming advanced, 37577
|
||||
github, level 19, old streaming advanced, 133717
|
||||
github, level 19 with dict, old streaming advanced, 37576
|
||||
github, no source size, old streaming advanced, 140631
|
||||
github, long distance mode, old streaming advanced, 412933
|
||||
github, multithreaded, old streaming advanced, 412933
|
||||
github, multithreaded long distance mode, old streaming advanced, 412933
|
||||
github, small window log, old streaming advanced, 412933
|
||||
github, small hash log, old streaming advanced, 412933
|
||||
github, small chain log, old streaming advanced, 412933
|
||||
github, explicit params, old streaming advanced, 412933
|
||||
github, uncompressed literals, old streaming advanced, 136311
|
||||
github, uncompressed literals optimal, old streaming advanced, 133717
|
||||
github, huffman literals, old streaming advanced, 175568
|
||||
github, multithreaded with advanced params, old streaming advanced, 412933
|
||||
silesia, level -5, old streaming cdcit, 6882466
|
||||
silesia, level -3, old streaming cdcit, 6568358
|
||||
silesia, level -1, old streaming cdcit, 6183385
|
||||
silesia, level 0, old streaming cdcit, 4849491
|
||||
silesia, level 1, old streaming cdcit, 5314109
|
||||
silesia, level 3, old streaming cdcit, 4849491
|
||||
silesia, level 4, old streaming cdcit, 4786913
|
||||
silesia, level 5, old streaming cdcit, 4710178
|
||||
silesia, level 6, old streaming cdcit, 4659996
|
||||
silesia, level 7, old streaming cdcit, 4596234
|
||||
silesia, level 9, old streaming cdcit, 4543862
|
||||
silesia, level 13, old streaming cdcit, 4482073
|
||||
silesia, level 16, old streaming cdcit, 4377389
|
||||
silesia, level 19, old streaming cdcit, 4293262
|
||||
silesia, no source size, old streaming cdcit, 4849455
|
||||
silesia, long distance mode, old streaming cdcit, 12000408
|
||||
silesia, multithreaded, old streaming cdcit, 12000408
|
||||
silesia, multithreaded long distance mode, old streaming cdcit, 12000408
|
||||
silesia, small window log, old streaming cdcit, 12000408
|
||||
silesia, small hash log, old streaming cdcit, 12000408
|
||||
silesia, small chain log, old streaming cdcit, 12000408
|
||||
silesia, explicit params, old streaming cdcit, 12000408
|
||||
silesia, uncompressed literals, old streaming cdcit, 4849491
|
||||
silesia, uncompressed literals optimal, old streaming cdcit, 4293262
|
||||
silesia, huffman literals, old streaming cdcit, 6183385
|
||||
silesia, multithreaded with advanced params, old streaming cdcit, 12000408
|
||||
silesia.tar, level -5, old streaming cdcit, 6982738
|
||||
silesia.tar, level -3, old streaming cdcit, 6641264
|
||||
silesia.tar, level -1, old streaming cdcit, 6190789
|
||||
silesia.tar, level 0, old streaming cdcit, 4861376
|
||||
silesia.tar, level 1, old streaming cdcit, 5336879
|
||||
silesia.tar, level 3, old streaming cdcit, 4861376
|
||||
silesia.tar, level 4, old streaming cdcit, 4799583
|
||||
silesia.tar, level 5, old streaming cdcit, 4722276
|
||||
silesia.tar, level 6, old streaming cdcit, 4672240
|
||||
silesia.tar, level 7, old streaming cdcit, 4606657
|
||||
silesia.tar, level 9, old streaming cdcit, 4554106
|
||||
silesia.tar, level 13, old streaming cdcit, 4491707
|
||||
silesia.tar, level 16, old streaming cdcit, 4381284
|
||||
silesia.tar, level 19, old streaming cdcit, 4281511
|
||||
silesia.tar, no source size, old streaming cdcit, 4861372
|
||||
silesia.tar, long distance mode, old streaming cdcit, 12022046
|
||||
silesia.tar, multithreaded, old streaming cdcit, 12022046
|
||||
silesia.tar, multithreaded long distance mode, old streaming cdcit, 12022046
|
||||
silesia.tar, small window log, old streaming cdcit, 12022046
|
||||
silesia.tar, small hash log, old streaming cdcit, 12022046
|
||||
silesia.tar, small chain log, old streaming cdcit, 12022046
|
||||
silesia.tar, explicit params, old streaming cdcit, 12022046
|
||||
silesia.tar, uncompressed literals, old streaming cdcit, 4861376
|
||||
silesia.tar, uncompressed literals optimal, old streaming cdcit, 4281511
|
||||
silesia.tar, huffman literals, old streaming cdcit, 6190789
|
||||
silesia.tar, multithreaded with advanced params, old streaming cdcit, 12022046
|
||||
github, level -5, old streaming cdcit, 205285
|
||||
github, level -5 with dict, old streaming cdcit, 46718
|
||||
github, level -3, old streaming cdcit, 190643
|
||||
github, level -3 with dict, old streaming cdcit, 45395
|
||||
github, level -1, old streaming cdcit, 175568
|
||||
github, level -1 with dict, old streaming cdcit, 43170
|
||||
github, level 0, old streaming cdcit, 136311
|
||||
github, level 0 with dict, old streaming cdcit, 41148
|
||||
github, level 1, old streaming cdcit, 142450
|
||||
github, level 1 with dict, old streaming cdcit, 41682
|
||||
github, level 3, old streaming cdcit, 136311
|
||||
github, level 3 with dict, old streaming cdcit, 41148
|
||||
github, level 4, old streaming cdcit, 136144
|
||||
github, level 4 with dict, old streaming cdcit, 41251
|
||||
github, level 5, old streaming cdcit, 135106
|
||||
github, level 5 with dict, old streaming cdcit, 38938
|
||||
github, level 6, old streaming cdcit, 135108
|
||||
github, level 6 with dict, old streaming cdcit, 38632
|
||||
github, level 7, old streaming cdcit, 135108
|
||||
github, level 7 with dict, old streaming cdcit, 38766
|
||||
github, level 9, old streaming cdcit, 135108
|
||||
github, level 9 with dict, old streaming cdcit, 39326
|
||||
github, level 13, old streaming cdcit, 133717
|
||||
github, level 13 with dict, old streaming cdcit, 39716
|
||||
github, level 16, old streaming cdcit, 133717
|
||||
github, level 16 with dict, old streaming cdcit, 37577
|
||||
github, level 19, old streaming cdcit, 133717
|
||||
github, level 19 with dict, old streaming cdcit, 37576
|
||||
github, no source size, old streaming cdcit, 140631
|
||||
github, long distance mode, old streaming cdcit, 412933
|
||||
github, multithreaded, old streaming cdcit, 412933
|
||||
github, multithreaded long distance mode, old streaming cdcit, 412933
|
||||
github, small window log, old streaming cdcit, 412933
|
||||
github, small hash log, old streaming cdcit, 412933
|
||||
github, small chain log, old streaming cdcit, 412933
|
||||
github, explicit params, old streaming cdcit, 412933
|
||||
github, uncompressed literals, old streaming cdcit, 136311
|
||||
github, uncompressed literals optimal, old streaming cdcit, 133717
|
||||
github, huffman literals, old streaming cdcit, 175568
|
||||
github, multithreaded with advanced params, old streaming cdcit, 412933
|
||||
silesia, level -5, old streaming advanced cdict, 6882466
|
||||
silesia, level -3, old streaming advanced cdict, 6568358
|
||||
silesia, level -1, old streaming advanced cdict, 6183385
|
||||
silesia, level 0, old streaming advanced cdict, 4849491
|
||||
silesia, level 1, old streaming advanced cdict, 5314109
|
||||
silesia, level 3, old streaming advanced cdict, 4849491
|
||||
silesia, level 4, old streaming advanced cdict, 4786913
|
||||
silesia, level 5, old streaming advanced cdict, 4710178
|
||||
silesia, level 6, old streaming advanced cdict, 4659996
|
||||
silesia, level 7, old streaming advanced cdict, 4596234
|
||||
silesia, level 9, old streaming advanced cdict, 4543862
|
||||
silesia, level 13, old streaming advanced cdict, 4482073
|
||||
silesia, level 16, old streaming advanced cdict, 4377389
|
||||
silesia, level 19, old streaming advanced cdict, 4293262
|
||||
silesia, no source size, old streaming advanced cdict, 4849455
|
||||
silesia, long distance mode, old streaming advanced cdict, 12000408
|
||||
silesia, multithreaded, old streaming advanced cdict, 12000408
|
||||
silesia, multithreaded long distance mode, old streaming advanced cdict, 12000408
|
||||
silesia, small window log, old streaming advanced cdict, 12000408
|
||||
silesia, small hash log, old streaming advanced cdict, 12000408
|
||||
silesia, small chain log, old streaming advanced cdict, 12000408
|
||||
silesia, explicit params, old streaming advanced cdict, 12000408
|
||||
silesia, uncompressed literals, old streaming advanced cdict, 4849491
|
||||
silesia, uncompressed literals optimal, old streaming advanced cdict, 4293262
|
||||
silesia, huffman literals, old streaming advanced cdict, 6183385
|
||||
silesia, multithreaded with advanced params, old streaming advanced cdict, 12000408
|
||||
silesia.tar, level -5, old streaming advanced cdict, 6982738
|
||||
silesia.tar, level -3, old streaming advanced cdict, 6641264
|
||||
silesia.tar, level -1, old streaming advanced cdict, 6190789
|
||||
silesia.tar, level 0, old streaming advanced cdict, 4861376
|
||||
silesia.tar, level 1, old streaming advanced cdict, 5336879
|
||||
silesia.tar, level 3, old streaming advanced cdict, 4861376
|
||||
silesia.tar, level 4, old streaming advanced cdict, 4799583
|
||||
silesia.tar, level 5, old streaming advanced cdict, 4722276
|
||||
silesia.tar, level 6, old streaming advanced cdict, 4672240
|
||||
silesia.tar, level 7, old streaming advanced cdict, 4606657
|
||||
silesia.tar, level 9, old streaming advanced cdict, 4554106
|
||||
silesia.tar, level 13, old streaming advanced cdict, 4491707
|
||||
silesia.tar, level 16, old streaming advanced cdict, 4381284
|
||||
silesia.tar, level 19, old streaming advanced cdict, 4281511
|
||||
silesia.tar, no source size, old streaming advanced cdict, 4861372
|
||||
silesia.tar, long distance mode, old streaming advanced cdict, 12022046
|
||||
silesia.tar, multithreaded, old streaming advanced cdict, 12022046
|
||||
silesia.tar, multithreaded long distance mode, old streaming advanced cdict, 12022046
|
||||
silesia.tar, small window log, old streaming advanced cdict, 12022046
|
||||
silesia.tar, small hash log, old streaming advanced cdict, 12022046
|
||||
silesia.tar, small chain log, old streaming advanced cdict, 12022046
|
||||
silesia.tar, explicit params, old streaming advanced cdict, 12022046
|
||||
silesia.tar, uncompressed literals, old streaming advanced cdict, 4861376
|
||||
silesia.tar, uncompressed literals optimal, old streaming advanced cdict, 4281511
|
||||
silesia.tar, huffman literals, old streaming advanced cdict, 6190789
|
||||
silesia.tar, multithreaded with advanced params, old streaming advanced cdict, 12022046
|
||||
github, level -5, old streaming advanced cdict, 205285
|
||||
github, level -5 with dict, old streaming advanced cdict, 46718
|
||||
github, level -3, old streaming advanced cdict, 190643
|
||||
github, level -3 with dict, old streaming advanced cdict, 45395
|
||||
github, level -1, old streaming advanced cdict, 175568
|
||||
github, level -1 with dict, old streaming advanced cdict, 43170
|
||||
github, level 0, old streaming advanced cdict, 136311
|
||||
github, level 0 with dict, old streaming advanced cdict, 41148
|
||||
github, level 1, old streaming advanced cdict, 142450
|
||||
github, level 1 with dict, old streaming advanced cdict, 41682
|
||||
github, level 3, old streaming advanced cdict, 136311
|
||||
github, level 3 with dict, old streaming advanced cdict, 41148
|
||||
github, level 4, old streaming advanced cdict, 136144
|
||||
github, level 4 with dict, old streaming advanced cdict, 41251
|
||||
github, level 5, old streaming advanced cdict, 135106
|
||||
github, level 5 with dict, old streaming advanced cdict, 38938
|
||||
github, level 6, old streaming advanced cdict, 135108
|
||||
github, level 6 with dict, old streaming advanced cdict, 38632
|
||||
github, level 7, old streaming advanced cdict, 135108
|
||||
github, level 7 with dict, old streaming advanced cdict, 38766
|
||||
github, level 9, old streaming advanced cdict, 135108
|
||||
github, level 9 with dict, old streaming advanced cdict, 39326
|
||||
github, level 13, old streaming advanced cdict, 133717
|
||||
github, level 13 with dict, old streaming advanced cdict, 39716
|
||||
github, level 16, old streaming advanced cdict, 133717
|
||||
github, level 16 with dict, old streaming advanced cdict, 37577
|
||||
github, level 19, old streaming advanced cdict, 133717
|
||||
github, level 19 with dict, old streaming advanced cdict, 37576
|
||||
github, no source size, old streaming advanced cdict, 140631
|
||||
github, long distance mode, old streaming advanced cdict, 412933
|
||||
github, multithreaded, old streaming advanced cdict, 412933
|
||||
github, multithreaded long distance mode, old streaming advanced cdict, 412933
|
||||
github, small window log, old streaming advanced cdict, 412933
|
||||
github, small hash log, old streaming advanced cdict, 412933
|
||||
github, small chain log, old streaming advanced cdict, 412933
|
||||
github, explicit params, old streaming advanced cdict, 412933
|
||||
github, uncompressed literals, old streaming advanced cdict, 136311
|
||||
github, uncompressed literals optimal, old streaming advanced cdict, 133717
|
||||
github, huffman literals, old streaming advanced cdict, 175568
|
||||
github, multithreaded with advanced params, old streaming advanced cdict, 412933
|
||||
|
||||
|
@@ -153,7 +153,7 @@ static void print_help(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Parse the arguments. Teturn 0 on success. Print help on failure. */
|
||||
/** Parse the arguments. Return 0 on success. Print help on failure. */
|
||||
static int parse_args(int argc, char** argv) {
|
||||
int option_index = 0;
|
||||
int c;
|
||||
|
||||
@@ -93,9 +93,9 @@ static size_t cctxParamRoundTripTest(void* resultBuff, size_t resultBuffCapacity
|
||||
int const cLevel = h32 % maxClevel;
|
||||
|
||||
/* Set parameters */
|
||||
CHECK_Z( ZSTD_CCtxParam_setParameter(cctxParams, ZSTD_c_compressionLevel, cLevel) );
|
||||
CHECK_Z( ZSTD_CCtxParam_setParameter(cctxParams, ZSTD_c_nbWorkers, 2) );
|
||||
CHECK_Z( ZSTD_CCtxParam_setParameter(cctxParams, ZSTD_c_overlapLog, 5) );
|
||||
CHECK_Z( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_compressionLevel, cLevel) );
|
||||
CHECK_Z( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_nbWorkers, 2) );
|
||||
CHECK_Z( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_overlapLog, 5) );
|
||||
|
||||
|
||||
/* Apply parameters */
|
||||
|
||||
@@ -31,6 +31,7 @@ static const void *symbols[] = {
|
||||
&ZSTD_getFrameContentSize,
|
||||
&ZSTD_maxCLevel,
|
||||
&ZSTD_compressBound,
|
||||
&ZSTD_decompressBound,
|
||||
&ZSTD_isError,
|
||||
&ZSTD_getErrorName,
|
||||
&ZSTD_createCCtx,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdlib.h> /* free */
|
||||
#include <stdio.h> /* fgets, sscanf */
|
||||
#include <string.h> /* strcmp */
|
||||
#include "timefn.h" /* UTIL_time_t */
|
||||
#include "mem.h"
|
||||
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel */
|
||||
#include "zstd.h" /* ZSTD_compressBound */
|
||||
|
||||
+230
-19
@@ -26,6 +26,7 @@
|
||||
#include <stdio.h> /* fgets, sscanf */
|
||||
#include <string.h> /* strcmp */
|
||||
#include <assert.h> /* assert */
|
||||
#include "timefn.h" /* UTIL_time_t, UTIL_getTime */
|
||||
#include "mem.h"
|
||||
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel, ZSTD_customMem, ZSTD_getDictID_fromFrame */
|
||||
#include "zstd.h" /* ZSTD_compressBound */
|
||||
@@ -37,6 +38,7 @@
|
||||
#include "xxhash.h" /* XXH64_* */
|
||||
#include "seqgen.h"
|
||||
#include "util.h"
|
||||
#include "timefn.h" /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */
|
||||
|
||||
|
||||
/*-************************************
|
||||
@@ -344,6 +346,20 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
DISPLAYLEVEL(3, "OK (%u bytes) \n", (unsigned)(cstreamSize + cdictSize));
|
||||
}
|
||||
|
||||
/* context size functions */
|
||||
DISPLAYLEVEL(3, "test%3i : estimate CStream size using CCtxParams : ", testNb++);
|
||||
{ ZSTD_CCtx_params* const params = ZSTD_createCCtxParams();
|
||||
size_t cstreamSize, cctxSize;
|
||||
CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_compressionLevel, 19) );
|
||||
cstreamSize = ZSTD_estimateCStreamSize_usingCCtxParams(params);
|
||||
CHECK_Z(cstreamSize);
|
||||
cctxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
|
||||
CHECK_Z(cctxSize);
|
||||
if (cstreamSize <= cctxSize + 2 * ZSTD_BLOCKSIZE_MAX) goto _output_error;
|
||||
ZSTD_freeCCtxParams(params);
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : check actual CStream size : ", testNb++);
|
||||
{ size_t const s = ZSTD_sizeof_CStream(zc);
|
||||
if (ZSTD_isError(s)) goto _output_error;
|
||||
@@ -495,7 +511,7 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
|
||||
/* _srcSize compression test */
|
||||
DISPLAYLEVEL(3, "test%3i : compress_srcSize %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
|
||||
ZSTD_initCStream_srcSize(zc, 1, CNBufferSize);
|
||||
CHECK_Z( ZSTD_initCStream_srcSize(zc, 1, CNBufferSize) );
|
||||
outBuff.dst = (char*)(compressedBuffer);
|
||||
outBuff.size = compressedBufferSize;
|
||||
outBuff.pos = 0;
|
||||
@@ -503,11 +519,14 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
inBuff.size = CNBufferSize;
|
||||
inBuff.pos = 0;
|
||||
CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );
|
||||
if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
|
||||
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
||||
if (r != 0) goto _output_error; } /* error, or some data not flushed */
|
||||
{ unsigned long long origSize = ZSTD_findDecompressedSize(outBuff.dst, outBuff.pos);
|
||||
if ((size_t)origSize != CNBufferSize) goto _output_error; } /* exact original size must be present */
|
||||
CHECK(inBuff.pos != inBuff.size, "Entire input should be consumed");
|
||||
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
||||
CHECK(r != 0, "Error or some data not flushed (ret=%zu)", r);
|
||||
}
|
||||
{ unsigned long long origSize = ZSTD_findDecompressedSize(outBuff.dst, outBuff.pos);
|
||||
CHECK(origSize == ZSTD_CONTENTSIZE_UNKNOWN, "Unknown!");
|
||||
CHECK((size_t)origSize != CNBufferSize, "Exact original size must be present (got %llu)", origSize);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
|
||||
|
||||
/* wrong _srcSize compression test */
|
||||
@@ -706,6 +725,156 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK\n");
|
||||
|
||||
ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary(zc, dictionary.start, dictionary.filled) );
|
||||
cSize = ZSTD_compress2(zc, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBufferSize, 100 KB));
|
||||
CHECK_Z(cSize);
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() with dictionary : ", testNb++);
|
||||
{
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
/* We should fail to decompress without a dictionary. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
}
|
||||
/* We should succeed to decompress with the dictionary. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictionary.start, dictionary.filled) );
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
|
||||
if (in.pos != in.size) goto _output_error;
|
||||
}
|
||||
/* The dictionary should presist across calls. */
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
|
||||
if (in.pos != in.size) goto _output_error;
|
||||
}
|
||||
/* The dictionary should not be cleared by ZSTD_reset_session_only. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
|
||||
if (in.pos != in.size) goto _output_error;
|
||||
}
|
||||
/* When we reset the context the dictionary is cleared. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
}
|
||||
ZSTD_freeDCtx(dctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_resetDStream() with dictionary : ", testNb++);
|
||||
{
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
/* We should succeed to decompress with the dictionary. */
|
||||
ZSTD_resetDStream(dctx);
|
||||
CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictionary.start, dictionary.filled) );
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
|
||||
if (in.pos != in.size) goto _output_error;
|
||||
}
|
||||
/* The dictionary should not be cleared by ZSTD_resetDStream(). */
|
||||
ZSTD_resetDStream(dctx);
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
|
||||
if (in.pos != in.size) goto _output_error;
|
||||
}
|
||||
/* The dictionary should be cleared by ZSTD_initDStream(). */
|
||||
CHECK_Z( ZSTD_initDStream(dctx) );
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
}
|
||||
ZSTD_freeDCtx(dctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() with ddict : ", testNb++);
|
||||
{
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
ZSTD_DDict* ddict = ZSTD_createDDict(dictionary.start, dictionary.filled);
|
||||
/* We should succeed to decompress with the ddict. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddict) );
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
|
||||
if (in.pos != in.size) goto _output_error;
|
||||
}
|
||||
/* The ddict should presist across calls. */
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
|
||||
if (in.pos != in.size) goto _output_error;
|
||||
}
|
||||
/* When we reset the context the ddict is cleared. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
}
|
||||
ZSTD_freeDCtx(dctx);
|
||||
ZSTD_freeDDict(ddict);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with prefix : ", testNb++);
|
||||
{
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
/* We should succeed to decompress with the prefix. */
|
||||
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
|
||||
CHECK_Z( ZSTD_DCtx_refPrefix_advanced(dctx, dictionary.start, dictionary.filled, ZSTD_dct_auto) );
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
|
||||
if (in.pos != in.size) goto _output_error;
|
||||
}
|
||||
/* The prefix should be cleared after the first compression. */
|
||||
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
|
||||
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
|
||||
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
}
|
||||
ZSTD_freeDCtx(dctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_initDStream*() with dictionary : ", testNb++);
|
||||
{
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
ZSTD_DDict* ddict = ZSTD_createDDict(dictionary.start, dictionary.filled);
|
||||
size_t ret;
|
||||
/* We should succeed to decompress with the dictionary. */
|
||||
CHECK_Z( ZSTD_initDStream_usingDict(dctx, dictionary.start, dictionary.filled) );
|
||||
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );
|
||||
/* The dictionary should presist across calls. */
|
||||
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );
|
||||
/* We should succeed to decompress with the ddict. */
|
||||
CHECK_Z( ZSTD_initDStream_usingDDict(dctx, ddict) );
|
||||
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );
|
||||
/* The ddict should presist across calls. */
|
||||
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );
|
||||
/* When we reset the context the ddict is cleared. */
|
||||
CHECK_Z( ZSTD_initDStream(dctx) );
|
||||
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize);
|
||||
if (!ZSTD_isError(ret)) goto _output_error;
|
||||
ZSTD_freeDCtx(dctx);
|
||||
ZSTD_freeDDict(ddict);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_usingCDict_advanced with masked dictID : ", testNb++);
|
||||
{ ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictionary.filled);
|
||||
ZSTD_frameParameters const fParams = { 1 /* contentSize */, 1 /* checksum */, 1 /* noDictID */};
|
||||
@@ -882,7 +1051,7 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
inBuff.size = srcSize; assert(srcSize < COMPRESSIBLE_NOISE_LENGTH);
|
||||
inBuff.pos = 0;
|
||||
}
|
||||
{ ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, 4 KB, dictionary.filled); /* intentionnally lies on estimatedSrcSize, to push cdict into targeting a small window size */
|
||||
{ ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, 4 KB, dictionary.filled); /* intentionally lies on estimatedSrcSize, to push cdict into targeting a small window size */
|
||||
ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem);
|
||||
DISPLAYLEVEL(5, "cParams.windowLog = %u : ", cParams.windowLog);
|
||||
CHECK_Z( ZSTD_CCtx_refCDict(zc, cdict) );
|
||||
@@ -1015,6 +1184,58 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
/* Small Sequence Section bug */
|
||||
DISPLAYLEVEL(3, "test%3i : decompress blocks with small sequences section : ", testNb++);
|
||||
{ /* This test consists of 3 blocks. Each block has one sequence.
|
||||
The sequence has literal length of 10, match length of 10 and offset of 10.
|
||||
The sequence value and compression mode for the blocks are following:
|
||||
The order of values are ll, ml, of.
|
||||
- First block : (10, 7, 13) (rle, rle, rle)
|
||||
- size of sequences section: 6 bytes (1 byte for nbSeq, 1 byte for encoding mode, 3 bytes for rle, 1 byte bitstream)
|
||||
- Second block : (10, 7, 1) (repeat, repeat, rle)
|
||||
- size of sequences section: 4 bytes (1 byte for nbSeq, 1 byte for encoding mode, 1 bytes for rle, 1 byte bitstream)
|
||||
- Third block : (10, 7, 1) (repeat, repeat, repeat)
|
||||
- size of sequences section: 3 bytes (1 byte for nbSeq, 1 byte for encoding mode, 1 byte bitstream) */
|
||||
|
||||
unsigned char compressed[] = {
|
||||
0x28, 0xb5, 0x2f, 0xfd, 0x24, 0x3c, 0x35, 0x01, 0x00, 0xf0, 0x85, 0x08,
|
||||
0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x4c, 0x6b, 0xa9, 0x8b,
|
||||
0xbc, 0xc5, 0xb6, 0xd9, 0x7f, 0x4c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac,
|
||||
0x69, 0x94, 0x89, 0x1c, 0x03, 0x44, 0x0a, 0x07, 0x00, 0xb4, 0x04, 0x80,
|
||||
0x40, 0x0a, 0xa4
|
||||
};
|
||||
unsigned int compressedSize = 51;
|
||||
unsigned char decompressed[] = {
|
||||
0x85, 0x08, 0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x85, 0x08,
|
||||
0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x4c, 0x6b, 0xa9, 0x8b,
|
||||
0xbc, 0xc5, 0xb6, 0xd9, 0x7f, 0x4c, 0x4c, 0x6b, 0xa9, 0x8b, 0xbc, 0xc5,
|
||||
0xb6, 0xd9, 0x7f, 0x4c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, 0x69, 0x94,
|
||||
0x89, 0x1c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, 0x69, 0x94, 0x89, 0x1c
|
||||
};
|
||||
unsigned int decompressedSize = 60;
|
||||
|
||||
ZSTD_DStream* const zds = ZSTD_createDStream();
|
||||
if (zds==NULL) goto _output_error;
|
||||
|
||||
CHECK_Z( ZSTD_initDStream(zds) );
|
||||
inBuff.src = compressed;
|
||||
inBuff.size = compressedSize;
|
||||
inBuff.pos = 0;
|
||||
outBuff.dst = decodedBuffer;
|
||||
outBuff.size = CNBufferSize;
|
||||
outBuff.pos = 0;
|
||||
|
||||
CHECK(ZSTD_decompressStream(zds, &outBuff, &inBuff) != 0,
|
||||
"Decompress did not reach the end of frame");
|
||||
CHECK(inBuff.pos != inBuff.size, "Decompress did not fully consume input");
|
||||
CHECK(outBuff.pos != decompressedSize, "Decompressed size does not match");
|
||||
CHECK(memcmp(outBuff.dst, decompressed, decompressedSize) != 0,
|
||||
"Decompressed data does not match");
|
||||
|
||||
ZSTD_freeDStream(zds);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : dictionary + uncompressible block + reusing tables checks offset table validity: ", testNb++);
|
||||
{ ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(
|
||||
dictionary.start, dictionary.filled,
|
||||
@@ -1703,7 +1924,7 @@ static size_t setCCtxParameter(ZSTD_CCtx* zc, ZSTD_CCtx_params* cctxParams,
|
||||
int useOpaqueAPI)
|
||||
{
|
||||
if (useOpaqueAPI) {
|
||||
return ZSTD_CCtxParam_setParameter(cctxParams, param, value);
|
||||
return ZSTD_CCtxParams_setParameter(cctxParams, param, value);
|
||||
} else {
|
||||
return ZSTD_CCtx_setParameter(zc, param, value);
|
||||
}
|
||||
@@ -1900,7 +2121,7 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
|
||||
CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) );
|
||||
}
|
||||
|
||||
/* multi-threading parameters. Only adjust ocassionally for small tests. */
|
||||
/* multi-threading parameters. Only adjust occasionally for small tests. */
|
||||
if (bigTests || (FUZ_rand(&lseed) & 0xF) == 0xF) {
|
||||
U32 const nbThreadsCandidate = (FUZ_rand(&lseed) & 4) + 1;
|
||||
U32 const nbThreadsAdjusted = (windowLogMalus < nbThreadsCandidate) ? nbThreadsCandidate - windowLogMalus : 1;
|
||||
@@ -1930,16 +2151,6 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
|
||||
} else {
|
||||
CHECK_Z( ZSTD_CCtx_loadDictionary_byReference(zc, dict, dictSize) );
|
||||
}
|
||||
if (dict && dictSize) {
|
||||
/* test that compression parameters are rejected (correctly) after loading a non-NULL dictionary */
|
||||
if (opaqueAPI) {
|
||||
size_t const setError = ZSTD_CCtx_setParametersUsingCCtxParams(zc, cctxParams);
|
||||
CHECK(!ZSTD_isError(setError), "ZSTD_CCtx_setParametersUsingCCtxParams should have failed");
|
||||
} else {
|
||||
size_t const setError = ZSTD_CCtx_setParameter(zc, ZSTD_c_windowLog, cParams.windowLog-1);
|
||||
CHECK(!ZSTD_isError(setError), "ZSTD_CCtx_setParameter should have failed");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CHECK_Z( ZSTD_CCtx_refPrefix(zc, dict, dictSize) );
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
# object artifacts
|
||||
*.o
|
||||
|
||||
# Default result files
|
||||
_*
|
||||
example.*
|
||||
example
|
||||
example_zstd.*
|
||||
example_gz.*
|
||||
fitblk.*
|
||||
fitblk
|
||||
fitblk_zstd.*
|
||||
zwrapbench.*
|
||||
zwrapbench
|
||||
foo.gz
|
||||
|
||||
minigzip
|
||||
|
||||
@@ -88,7 +88,7 @@ fitblk: $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(ZSTDLI
|
||||
fitblk_zstd: $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstdTurnedOn_zlibwrapper.o $(ZSTDLIBRARY)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@
|
||||
|
||||
zwrapbench: $(EXAMPLE_PATH)/zwrapbench.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(PROGRAMS_PATH)/util.o $(PROGRAMS_PATH)/datagen.o $(ZSTDLIBRARY)
|
||||
zwrapbench: $(EXAMPLE_PATH)/zwrapbench.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(PROGRAMS_PATH)/util.o $(PROGRAMS_PATH)/timefn.o $(PROGRAMS_PATH)/datagen.o $(ZSTDLIBRARY)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@
|
||||
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ inflate with dictionary: hello, hello!
|
||||
The script used for compilation can be found at [zlibWrapper/Makefile](Makefile).
|
||||
|
||||
|
||||
#### The measurement of performace of Zstandard wrapper for zlib
|
||||
#### The measurement of performance of Zstandard wrapper for zlib
|
||||
|
||||
The zstd distribution contains a tool called `zwrapbench` which can measure speed and ratio of zlib, zstd, and the wrapper.
|
||||
The benchmark is conducted using given filenames or synthetic data if filenames are not provided.
|
||||
@@ -96,8 +96,8 @@ as this case is automatically detected.
|
||||
#### Reusing contexts
|
||||
|
||||
The ordinary zlib compression of two files/streams allocates two contexts:
|
||||
- for the 1st file calls `deflateInit`, `deflate`, `...`, `deflate`, `defalateEnd`
|
||||
- for the 2nd file calls `deflateInit`, `deflate`, `...`, `deflate`, `defalateEnd`
|
||||
- for the 1st file calls `deflateInit`, `deflate`, `...`, `deflate`, `deflateEnd`
|
||||
- for the 2nd file calls `deflateInit`, `deflate`, `...`, `deflate`, `deflateEnd`
|
||||
|
||||
The speed of compression can be improved with reusing a single context with following steps:
|
||||
- initialize the context with `deflateInit`
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
data in order to determine how much of that input will compress to
|
||||
nearly the requested output block size. The first pass generates
|
||||
enough deflate blocks to produce output to fill the requested
|
||||
output size plus a specfied excess amount (see the EXCESS define
|
||||
output size plus a specified excess amount (see the EXCESS define
|
||||
below). The last deflate block may go quite a bit past that, but
|
||||
is discarded. The second pass decompresses and recompresses just
|
||||
the compressed data that fit in the requested plus excess sized
|
||||
@@ -217,7 +217,7 @@ int main(int argc, char **argv)
|
||||
if (ret == Z_MEM_ERROR)
|
||||
quit("out of memory");
|
||||
|
||||
/* set up for next reocmpression */
|
||||
/* set up for next recompression */
|
||||
ret = inflateReset(&inf);
|
||||
assert(ret != Z_STREAM_ERROR);
|
||||
ret = deflateReset(&def);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
data in order to determine how much of that input will compress to
|
||||
nearly the requested output block size. The first pass generates
|
||||
enough deflate blocks to produce output to fill the requested
|
||||
output size plus a specfied excess amount (see the EXCESS define
|
||||
output size plus a specified excess amount (see the EXCESS define
|
||||
below). The last deflate block may go quite a bit past that, but
|
||||
is discarded. The second pass decompresses and recompresses just
|
||||
the compressed data that fit in the requested plus excess sized
|
||||
@@ -198,7 +198,7 @@ int main(int argc, char **argv)
|
||||
if (ret == Z_MEM_ERROR)
|
||||
quit("out of memory");
|
||||
|
||||
/* set up for next reocmpression */
|
||||
/* set up for next recompression */
|
||||
ret = inflateReset(&inf);
|
||||
assert(ret != Z_STREAM_ERROR);
|
||||
ret = deflateReset(&def);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <ctype.h> /* toupper */
|
||||
#include <errno.h> /* errno */
|
||||
|
||||
#include "timefn.h" /* UTIL_time_t, UTIL_getTime, UTIL_clockSpanMicro, UTIL_waitForNextTick */
|
||||
#include "mem.h"
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
#include "zstd.h"
|
||||
@@ -192,7 +193,7 @@ static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
|
||||
remaining -= thisBlockSize;
|
||||
} } }
|
||||
|
||||
/* warmimg up memory */
|
||||
/* warming up memory */
|
||||
RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1);
|
||||
|
||||
/* Bench */
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
|
||||
|
||||
Reference in New Issue
Block a user