Compare commits
303
Commits
estimate_doc
...
RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
794ea1b0af | ||
|
|
78f732cfdd | ||
|
|
273d1279ca | ||
|
|
c6e5257240 | ||
|
|
dc1f7b560b | ||
|
|
6679d0ca7b | ||
|
|
76fbb5f3d4 | ||
|
|
1d3f664fce | ||
|
|
86caab507f | ||
|
|
731f4b70fc | ||
|
|
741b87bbe1 | ||
|
|
f62b2663b9 | ||
|
|
3487a60950 | ||
|
|
6a0052a409 | ||
|
|
6f1215b874 | ||
|
|
c5da438dc0 | ||
|
|
3d18d9a9ce | ||
|
|
902c7ec1fe | ||
|
|
5d82c2b57c | ||
|
|
f5728da365 | ||
|
|
42b02f5185 | ||
|
|
cd4dba74de | ||
|
|
7d970bd83c | ||
|
|
a595e5812a | ||
|
|
79cd0ff712 | ||
|
|
3008f74ee2 | ||
|
|
f79c1c476e | ||
|
|
9dca0602f4 | ||
|
|
88301b58c1 | ||
|
|
0fcdc62c2d | ||
|
|
dff5407cd0 | ||
|
|
351498b932 | ||
|
|
686e7e4b4b | ||
|
|
559762da12 | ||
|
|
9cc3304614 | ||
|
|
a0a9bc6c95 | ||
|
|
515c07a131 | ||
|
|
490163ac73 | ||
|
|
216099a73f | ||
|
|
04d91d5219 | ||
|
|
3613448fb8 | ||
|
|
86b8e39a84 | ||
|
|
2215101cad | ||
|
|
d6ee2d5d24 | ||
|
|
ff0afbad58 | ||
|
|
c8ab027227 | ||
|
|
7c2aa73a8e | ||
|
|
084b362775 | ||
|
|
c1e995321e | ||
|
|
94c102038b | ||
|
|
4bd911ae41 | ||
|
|
b20703f273 | ||
|
|
f65b9e27ce | ||
|
|
ff6713fd72 | ||
|
|
5473b72a05 | ||
|
|
92fbd42894 | ||
|
|
83ec3d0164 | ||
|
|
5a66afa051 | ||
|
|
37ff4f91eb | ||
|
|
e27e156d3c | ||
|
|
a6ff1194d8 | ||
|
|
0ae98ba215 | ||
|
|
db996d253e | ||
|
|
7a43609ffd | ||
|
|
3b573ba1f0 | ||
|
|
8688c6ed92 | ||
|
|
4eea5af595 | ||
|
|
ca0fc763e3 | ||
|
|
b39c76765b | ||
|
|
fe7c645a7e | ||
|
|
8ba5bc4729 | ||
|
|
ee6acaf26b | ||
|
|
e0872806df | ||
|
|
74e856a195 | ||
|
|
edab9eed66 | ||
|
|
f6039f3d5f | ||
|
|
a4db145900 | ||
|
|
f99a450ca4 | ||
|
|
1362699e87 | ||
|
|
fbd9e628ae | ||
|
|
c610a01d7d | ||
|
|
372fddf4e6 | ||
|
|
cb596b024f | ||
|
|
c1875a7386 | ||
|
|
eb5f7a7fa2 | ||
|
|
d2f56ba442 | ||
|
|
a9fb8d4c41 | ||
|
|
e127139ceb | ||
|
|
478e5fedf9 | ||
|
|
aed172a8fe | ||
|
|
ad590275b4 | ||
|
|
007cda88ca | ||
|
|
8689633fdf | ||
|
|
2abe8d63e0 | ||
|
|
4fb0a77314 | ||
|
|
b293d2ebc3 | ||
|
|
70df177615 | ||
|
|
e385c3dd46 | ||
|
|
bb774ae1eb | ||
|
|
61d89067c9 | ||
|
|
b125202440 | ||
|
|
bb4f85db42 | ||
|
|
063d9f24e2 | ||
|
|
b27d1634a5 | ||
|
|
dcd713ce06 | ||
|
|
a58b48ef0e | ||
|
|
34cf4c139e | ||
|
|
8d31e8ec42 | ||
|
|
d23b95d21d | ||
|
|
86db60752d | ||
|
|
ef82b214ad | ||
|
|
aa8592c532 | ||
|
|
e0412c2062 | ||
|
|
a412bedb3f | ||
|
|
1fafd0c4ae | ||
|
|
038a8a906b | ||
|
|
4d2bf7f0f2 | ||
|
|
5c5c1b0d90 | ||
|
|
f8372191f5 | ||
|
|
f77f634d41 | ||
|
|
4b51526412 | ||
|
|
6719794379 | ||
|
|
0591e7eea1 | ||
|
|
3b40100058 | ||
|
|
6b11fc436c | ||
|
|
cc4530924b | ||
|
|
68a232c591 | ||
|
|
621a263fb2 | ||
|
|
ce6cadc860 | ||
|
|
3c78b42210 | ||
|
|
4afe31ba7b | ||
|
|
0a68be83e7 | ||
|
|
7170f51dd2 | ||
|
|
9e711c9360 | ||
|
|
e62e15df19 | ||
|
|
b34517a440 | ||
|
|
588dfbcc97 | ||
|
|
c2d3570338 | ||
|
|
1e240af30a | ||
|
|
7a225c0c46 | ||
|
|
83598aa106 | ||
|
|
7003c9905e | ||
|
|
3dbd861b7d | ||
|
|
5a1bb4a4e0 | ||
|
|
40874d4aea | ||
|
|
1e046ce7fa | ||
|
|
889392dac8 | ||
|
|
e13d099bf8 | ||
|
|
b6805c54d6 | ||
|
|
927d079944 | ||
|
|
b921f1aad6 | ||
|
|
a3f1b2448c | ||
|
|
b0e8580dc7 | ||
|
|
695d154cac | ||
|
|
54107e263f | ||
|
|
3a64c69eba | ||
|
|
a844455095 | ||
|
|
22574d848d | ||
|
|
1f87c88ecf | ||
|
|
06b5b37b8d | ||
|
|
b88c593d8f | ||
|
|
887f5b62ae | ||
|
|
6c35fb2e8c | ||
|
|
641749fc09 | ||
|
|
5a08f58df2 | ||
|
|
0d9fb5dc33 | ||
|
|
9fed5ef108 | ||
|
|
fe2e2ad36d | ||
|
|
0ae21d8c31 | ||
|
|
5474edbe60 | ||
|
|
9ae3bf5ee2 | ||
|
|
e5af24c5fa | ||
|
|
8168a451e5 | ||
|
|
d31018e223 | ||
|
|
7afd9db8db | ||
|
|
04a6c8cbe2 | ||
|
|
79e9459efc | ||
|
|
0166b2ba80 | ||
|
|
81bfe3655e | ||
|
|
4683667785 | ||
|
|
de10f56be2 | ||
|
|
fd03971252 | ||
|
|
befcec1788 | ||
|
|
3ce4c6e046 | ||
|
|
a261375996 | ||
|
|
d0b7da30e2 | ||
|
|
a7b4dafa03 | ||
|
|
4a74eb8cfb | ||
|
|
c485b57bc7 | ||
|
|
163e9b6637 | ||
|
|
e1ef81a3ae | ||
|
|
60829445bf | ||
|
|
798034aeae | ||
|
|
2fc7248412 | ||
|
|
799b904628 | ||
|
|
c7611d6964 | ||
|
|
ee2efb634e | ||
|
|
1a860c8737 | ||
|
|
81f444f4f9 | ||
|
|
050fec5c37 | ||
|
|
e6f4b46493 | ||
|
|
d2ea3fb5ef | ||
|
|
572acb9c5d | ||
|
|
e2fe266279 | ||
|
|
3a2e302b2c | ||
|
|
dcf784a04b | ||
|
|
7971fd16f7 | ||
|
|
7f76d37044 | ||
|
|
17332454e5 | ||
|
|
e49d1ab6aa | ||
|
|
66269e74a0 | ||
|
|
923cf3dc92 | ||
|
|
ffde100b68 | ||
|
|
a07cae3976 | ||
|
|
a52d897d60 | ||
|
|
903bc264ad | ||
|
|
f06b18b3ff | ||
|
|
c6cabf9441 | ||
|
|
475da4fb2e | ||
|
|
7cf62bc274 | ||
|
|
377ecefce9 | ||
|
|
8052cd0131 | ||
|
|
e515327764 | ||
|
|
9a3b17c4d6 | ||
|
|
2ce0290e4d | ||
|
|
86ead9f4a4 | ||
|
|
20f8df6440 | ||
|
|
126ec2669c | ||
|
|
468bb17378 | ||
|
|
d151a4880b | ||
|
|
809c7eb6bf | ||
|
|
05059e5a48 | ||
|
|
dc84e35138 | ||
|
|
8193250615 | ||
|
|
6b3d12fe54 | ||
|
|
dd4de1dd7a | ||
|
|
5ab78c0418 | ||
|
|
c7269add7e | ||
|
|
e122fcbf58 | ||
|
|
c2d470581e | ||
|
|
a419265d30 | ||
|
|
59dcc47579 | ||
|
|
fcbf2fde9a | ||
|
|
3fd5f9f52d | ||
|
|
592b1acb18 | ||
|
|
e19fe535f4 | ||
|
|
83adaecf41 | ||
|
|
c5bf96fb74 | ||
|
|
52e41b9ac8 | ||
|
|
e61e3ff152 | ||
|
|
98d8ad27a2 | ||
|
|
c53d650d9a | ||
|
|
f013b1b504 | ||
|
|
1518570c62 | ||
|
|
4502ca5f42 | ||
|
|
fabce2a61c | ||
|
|
81fdca0012 | ||
|
|
324cce4996 | ||
|
|
b38d87b476 | ||
|
|
9446b1910c | ||
|
|
3c3845b9d8 | ||
|
|
af971cec65 | ||
|
|
7567769a7e | ||
|
|
24dabde507 | ||
|
|
d988e00a7f | ||
|
|
e590c8a0e3 | ||
|
|
69036dffe5 | ||
|
|
6bb1688c1a | ||
|
|
ea4027c003 | ||
|
|
c87ad5bdb5 | ||
|
|
e8ff7d18eb | ||
|
|
c692b8d12d | ||
|
|
2b31cb0698 | ||
|
|
19317239ec | ||
|
|
c1e588fcb4 | ||
|
|
4f77b81c8a | ||
|
|
0e2cfebb63 | ||
|
|
43118da8a7 | ||
|
|
3daed7017a | ||
|
|
2c17e05646 | ||
|
|
7b762364cb | ||
|
|
d5cbae7c50 | ||
|
|
585aaa0ed3 | ||
|
|
fe34776c20 | ||
|
|
cdceb0fce5 | ||
|
|
48b5a7bd8b | ||
|
|
1c007e64b8 | ||
|
|
607933a2ff | ||
|
|
f4dbfce79c | ||
|
|
feaa8ac50d | ||
|
|
4edfaa93b7 | ||
|
|
b69d06a810 | ||
|
|
d55ebb5718 | ||
|
|
63779c7982 | ||
|
|
d507e02940 | ||
|
|
73e19c4cf1 | ||
|
|
945f27758c | ||
|
|
e47e674cd0 | ||
|
|
791626dfb9 | ||
|
|
f4a541b021 | ||
|
|
a488ba114e | ||
|
|
e4558ffd1d | ||
|
|
97a3da1df0 |
+1
-1
@@ -2,8 +2,8 @@ task:
|
||||
name: FreeBSD (shortest)
|
||||
freebsd_instance:
|
||||
matrix:
|
||||
image_family: freebsd-14-0
|
||||
image_family: freebsd-13-2
|
||||
image_family: freebsd-12-4
|
||||
install_script: pkg install -y gmake coreutils
|
||||
script: |
|
||||
MOREFLAGS="-Werror" gmake -j all
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
name: facebook/zstd/commit
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
permissions: read-all
|
||||
jobs:
|
||||
short-tests-0:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
docker:
|
||||
image: fbopensource/zstd-circleci-primary:0.0.1
|
||||
options: --entrypoint /bin/bash
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install libcurl4-gnutls-dev
|
||||
- name: Test
|
||||
run: |
|
||||
./tests/test-license.py
|
||||
cc -v
|
||||
CFLAGS="-O0 -Werror -pedantic" make allmost; make clean
|
||||
make c99build; make clean
|
||||
make c11build; make clean
|
||||
make -j regressiontest; make clean
|
||||
make shortest; make clean
|
||||
make cxxtest; make clean
|
||||
short-tests-1:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
docker:
|
||||
image: fbopensource/zstd-circleci-primary:0.0.1
|
||||
options: --entrypoint /bin/bash
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-powerpc-linux-gnu gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu libc6-dev-ppc64-powerpc-cross libcurl4-gnutls-dev lib64gcc-11-dev-powerpc-cross
|
||||
- name: Test
|
||||
run: |-
|
||||
make gnu90build; make clean
|
||||
make gnu99build; make clean
|
||||
make ppc64build V=1; make clean
|
||||
make ppcbuild V=1; make clean
|
||||
make armbuild V=1; make clean
|
||||
make aarch64build V=1; make clean
|
||||
make -C tests test-legacy test-longmatch; make clean
|
||||
make -C lib libzstd-nomt; make clean
|
||||
regression-test:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
docker:
|
||||
image: fbopensource/zstd-circleci-primary:0.0.1
|
||||
options: --entrypoint /bin/bash
|
||||
env:
|
||||
CIRCLE_ARTIFACTS: "/tmp/circleci-artifacts"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: restore_cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: regression-cache-{{ checksum "tests/regression/data.c" }}-v0
|
||||
path: tests/regression/cache
|
||||
restore-keys: regression-cache-{{ checksum "tests/regression/data.c" }}-v0
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install libcurl4-gnutls-dev
|
||||
- name: Regression Test
|
||||
run: |
|
||||
make -C programs zstd
|
||||
make -C tests/regression test
|
||||
mkdir -p $CIRCLE_ARTIFACTS
|
||||
./tests/regression/test \
|
||||
--cache tests/regression/cache \
|
||||
--output $CIRCLE_ARTIFACTS/results.csv \
|
||||
--zstd programs/zstd
|
||||
echo "NOTE: The new results.csv is uploaded as an artifact to this job"
|
||||
echo " If this fails, go to the Artifacts pane in CircleCI, "
|
||||
echo " download /tmp/circleci-artifacts/results.csv, and if they "
|
||||
echo " are still good, copy it into the repo and commit it."
|
||||
echo "> diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv"
|
||||
diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: "/tmp/circleci-artifacts"
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
make-all:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: make all
|
||||
run: make all
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
DEVNULLRIGHTS: 1
|
||||
READFROMBLOCKDEVICE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: make test
|
||||
run: make test
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
make-test-osx:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: OS-X test
|
||||
run: make test # make -c lib all doesn't work because of the fact that it's not a tty
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
DEVNULLRIGHTS: 1
|
||||
READFROMBLOCKDEVICE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: make test
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -55,29 +55,29 @@ jobs:
|
||||
no-intrinsics-fuzztest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: no intrinsics fuzztest
|
||||
run: MOREFLAGS="-DZSTD_NO_INTRINSICS" make -C tests fuzztest
|
||||
|
||||
tsan-zstreamtest:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: thread sanitizer zstreamtest
|
||||
run: CC=clang ZSTREAM_TESTTIME=-T3mn make tsan-test-zstream
|
||||
|
||||
ubsan-zstreamtest:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: undefined behavior sanitizer zstreamtest
|
||||
run: CC=clang make uasan-test-zstream
|
||||
|
||||
# lasts ~15mn
|
||||
tsan-fuzztest:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: thread sanitizer fuzztest
|
||||
run: CC=clang make tsan-fuzztest
|
||||
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
big-tests-zstreamtest32:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: zstream tests in 32bit mode, with big tests
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -94,9 +94,9 @@ jobs:
|
||||
|
||||
# lasts ~23mn
|
||||
gcc-8-asan-ubsan-testzstd:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: gcc-8 + ASan + UBSan + Test Zstd
|
||||
# See https://askubuntu.com/a/1428822
|
||||
run: |
|
||||
@@ -106,16 +106,16 @@ jobs:
|
||||
CC=gcc-8 make -j uasan-test-zstd </dev/null V=1
|
||||
|
||||
clang-asan-ubsan-testzstd:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: clang + ASan + UBSan + Test Zstd
|
||||
run: CC=clang make -j uasan-test-zstd </dev/null V=1
|
||||
|
||||
gcc-asan-ubsan-testzstd-32bit:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: ASan + UBSan + Test Zstd, 32bit mode
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -127,9 +127,9 @@ jobs:
|
||||
# so any data coming from these libraries is always considered "uninitialized"
|
||||
|
||||
gcc-8-asan-ubsan-fuzz:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: gcc-8 + ASan + UBSan + Fuzz Test
|
||||
# See https://askubuntu.com/a/1428822
|
||||
run: |
|
||||
@@ -139,16 +139,16 @@ jobs:
|
||||
CC=gcc-8 FUZZER_FLAGS="--long-tests" make clean uasan-fuzztest
|
||||
|
||||
clang-asan-ubsan-fuzz:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: clang + ASan + UBSan + Fuzz Test
|
||||
run: CC=clang FUZZER_FLAGS="--long-tests" make clean uasan-fuzztest
|
||||
|
||||
gcc-asan-ubsan-fuzz32:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: ASan + UBSan + Fuzz Test 32bit
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -156,9 +156,9 @@ jobs:
|
||||
CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make uasan-fuzztest
|
||||
|
||||
clang-asan-ubsan-fuzz32:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: clang + ASan + UBSan + Fuzz Test 32bit
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -166,30 +166,30 @@ jobs:
|
||||
CC=clang CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make uasan-fuzztest
|
||||
|
||||
asan-ubsan-regression:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: ASan + UBSan + Regression Test
|
||||
run: make -j uasanregressiontest
|
||||
|
||||
clang-ubsan-regression:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: clang + ASan + UBSan + Regression Test
|
||||
run: CC=clang make -j uasanregressiontest
|
||||
|
||||
msan-regression:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: MSan + Regression Test
|
||||
run: make -j msanregressiontest
|
||||
|
||||
clang-msan-fuzz-unoptimized:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: clang + MSan + Fuzz Test
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -197,9 +197,9 @@ jobs:
|
||||
CC=clang MOREFLAGS="-O0" make clean msan-fuzztest
|
||||
|
||||
clang-msan-fuzz:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: clang + MSan + Fuzz Test
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -208,9 +208,9 @@ jobs:
|
||||
|
||||
# lasts ~24mn
|
||||
clang-msan-testzstd:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: clang + MSan + Test Zstd
|
||||
run: |
|
||||
sudo apt-get update
|
||||
@@ -220,7 +220,7 @@ jobs:
|
||||
armfuzz:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Qemu ARM emulation + Fuzz Test
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -230,7 +230,7 @@ jobs:
|
||||
valgrind-fuzz-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: valgrind + fuzz test stack mode # ~ 7mn
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: |
|
||||
@@ -246,8 +246,8 @@ jobs:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: msys2/setup-msys2@5beef6d11f48bba68b9eb503e3adc60b23c0cc36 # tag=v2
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- uses: msys2/setup-msys2@cc11e9188b693c2b100158c3322424c4cc1dadea # tag=v2.22.0
|
||||
with:
|
||||
msystem: MINGW64
|
||||
install: make
|
||||
@@ -269,7 +269,7 @@ jobs:
|
||||
|
||||
# lasts ~20mn
|
||||
oss-fuzz:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -290,7 +290,7 @@ jobs:
|
||||
dry-run: false
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3.1.3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # tag=v4.3.1
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: ${{ matrix.sanitizer }}-artifacts
|
||||
|
||||
@@ -16,21 +16,21 @@ jobs:
|
||||
linux-kernel:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: linux kernel, library + build + test
|
||||
run: make -C contrib/linux-kernel test CFLAGS="-Werror -Wunused-const-variable -Wunused-but-set-variable"
|
||||
|
||||
benchmarking:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: make benchmarking
|
||||
run: make benchmarking
|
||||
|
||||
check-32bit: # designed to catch https://github.com/facebook/zstd/issues/2428
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: make check on 32-bit
|
||||
run: |
|
||||
sudo apt update
|
||||
@@ -38,9 +38,9 @@ jobs:
|
||||
CFLAGS="-m32 -O1 -fstack-protector" make check V=1
|
||||
|
||||
check-x32:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04 # ubuntu-latest == ubuntu-22.04 have issues currently with x32
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: make check on x32 ABI # https://en.wikipedia.org/wiki/X32_ABI
|
||||
env:
|
||||
CHECK_CONSTRAINED_MEM: true
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
build-c89:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: ensure zstd can be build with c89/c90 compilers (+ long long support + variadic macros)
|
||||
run: |
|
||||
make c89build V=1
|
||||
@@ -60,16 +60,16 @@ jobs:
|
||||
build-zstd-dll:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: build zstd bin against a dynamic lib (debuglevel for more dependencies)
|
||||
run: |
|
||||
make -C lib lib-mt-release
|
||||
make -C lib lib-mt-release
|
||||
DEBUGLEVEL=2 make -C programs zstd-dll
|
||||
|
||||
gcc-7-libzstd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: gcc-7 + libzstdmt compilation
|
||||
# See https://askubuntu.com/a/1428822
|
||||
run: |
|
||||
@@ -80,24 +80,21 @@ jobs:
|
||||
make clean
|
||||
LDFLAGS=-Wl,--no-undefined make -C lib libzstd-mt
|
||||
|
||||
# candidate test (to check) : underlink test
|
||||
# candidate test (for discussion) : underlink test
|
||||
# LDFLAGS=-Wl,--no-undefined : will make the linker fail if dll is underlinked
|
||||
|
||||
cmake-build-and-test-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- name: cmake build and test check
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: cmake build and test
|
||||
run: |
|
||||
FUZZERTEST=-T1mn ZSTREAM_TESTTIME=-T1mn make cmakebuild
|
||||
cp -r ./ "../zstd source"
|
||||
cd "../zstd source"
|
||||
FUZZERTEST=-T1mn ZSTREAM_TESTTIME=-T1mn make cmakebuild
|
||||
FUZZERTEST=-T1mn ZSTREAM_TESTTIME=-T1mn make cmakebuild V=1
|
||||
|
||||
cpp-gnu90-c99-compatibility:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: C++, gnu90 and c99 compatibility
|
||||
run: |
|
||||
make cxxtest
|
||||
@@ -111,7 +108,7 @@ jobs:
|
||||
mingw-cross-compilation:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: mingw cross-compilation
|
||||
run: |
|
||||
# sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix; (doesn't work)
|
||||
@@ -122,7 +119,7 @@ jobs:
|
||||
armbuild:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: ARM Build Test
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -132,7 +129,7 @@ jobs:
|
||||
bourne-shell:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Bourne shell compatibility (shellcheck)
|
||||
run: |
|
||||
wget https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.x86_64.tar.xz
|
||||
@@ -142,7 +139,7 @@ jobs:
|
||||
zlib-wrapper:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: zlib wrapper test
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -153,7 +150,7 @@ jobs:
|
||||
lz4-threadpool-libs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: LZ4, thread pool, and libs build testslib wrapper test
|
||||
run: |
|
||||
make lz4install
|
||||
@@ -167,7 +164,7 @@ jobs:
|
||||
gcc-make-tests-32bit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Make all, 32bit mode
|
||||
run: |
|
||||
sudo apt-get -qqq update
|
||||
@@ -177,7 +174,7 @@ jobs:
|
||||
gcc-8-make:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: gcc-8 build
|
||||
# See https://askubuntu.com/a/1428822
|
||||
run: |
|
||||
@@ -200,7 +197,7 @@ jobs:
|
||||
flags: "HAVE_ZLIB=0 HAVE_LZ4=0 HAVE_LZMA=1"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Build with ${{matrix.name}}
|
||||
run: ${{matrix.flags}} make zstd
|
||||
|
||||
@@ -208,7 +205,7 @@ jobs:
|
||||
implicit-fall-through:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: -Wimplicit-fallthrough build
|
||||
run: |
|
||||
make clean
|
||||
@@ -219,7 +216,7 @@ jobs:
|
||||
meson-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
@@ -243,17 +240,15 @@ jobs:
|
||||
meson-windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Install packages
|
||||
run: pip install --pre meson
|
||||
- name: Initialize the MSVC dev command prompt
|
||||
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89
|
||||
- name: Configure with Meson
|
||||
run: |
|
||||
meson setup build/meson/ builddir -Dbin_tests=true -Dbin_programs=true -Dbin_contrib=true
|
||||
meson setup --vsenv build/meson/ builddir -Dbin_tests=true -Dbin_programs=true -Dbin_contrib=true
|
||||
- name: Build with Meson
|
||||
run: |
|
||||
ninja -C builddir/
|
||||
meson compile -C builddir/
|
||||
- name: Test with Meson
|
||||
run: |
|
||||
meson test -C builddir/ --print-errorlogs
|
||||
@@ -274,17 +269,18 @@ jobs:
|
||||
flags: "-T ClangCL"
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # tag=v1.3
|
||||
- name: Build
|
||||
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # tag=v2.0.0
|
||||
- name: Build & Test
|
||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
||||
run: |
|
||||
cd build\cmake
|
||||
mkdir build
|
||||
cd build
|
||||
cmake.exe -G "${{matrix.generator}}" ${{matrix.flags}} ..
|
||||
cmake.exe -G "${{matrix.generator}}" ${{matrix.flags}} -DCMAKE_BUILD_TYPE=Debug -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_ZSTREAM_FLAGS=-T30s -DZSTD_FUZZER_FLAGS=-T30s -DZSTD_FULLBENCH_FLAGS=-i0 ..
|
||||
cmake.exe --build .
|
||||
ctest.exe -V -C Debug
|
||||
|
||||
msbuild-visual-studio:
|
||||
strategy:
|
||||
@@ -301,9 +297,9 @@ jobs:
|
||||
]
|
||||
runs-on: ${{matrix.runner}}
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # tag=v1.3
|
||||
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # tag=v2.0.0
|
||||
- name: Build ${{matrix.name}}
|
||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
||||
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
|
||||
@@ -326,7 +322,7 @@ jobs:
|
||||
libzstd-size:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: libzstd size test
|
||||
run: |
|
||||
make clean && make -j -C lib libzstd && ./tests/check_size.py lib/libzstd.so 1100000
|
||||
@@ -337,7 +333,7 @@ jobs:
|
||||
minimal-decompressor-macros:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: minimal decompressor macros
|
||||
run: |
|
||||
make clean && make -j all ZSTD_LIB_MINIFY=1 MOREFLAGS="-Werror"
|
||||
@@ -354,7 +350,7 @@ jobs:
|
||||
dynamic-bmi2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: dynamic bmi2 tests
|
||||
run: |
|
||||
make clean && make -j check MOREFLAGS="-O0 -Werror -mbmi2"
|
||||
@@ -366,7 +362,7 @@ jobs:
|
||||
test-variants:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: make all variants & validate
|
||||
run: |
|
||||
make -j -C programs allVariants MOREFLAGS=-O0
|
||||
@@ -385,13 +381,15 @@ jobs:
|
||||
{ name: PPC64LE, xcc_pkg: gcc-powerpc64le-linux-gnu, xcc: powerpc64le-linux-gnu-gcc, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64le-static },
|
||||
{ name: S390X, xcc_pkg: gcc-s390x-linux-gnu, xcc: s390x-linux-gnu-gcc, xemu_pkg: qemu-system-s390x, xemu: qemu-s390x-static },
|
||||
{ name: MIPS, xcc_pkg: gcc-mips-linux-gnu, xcc: mips-linux-gnu-gcc, xemu_pkg: qemu-system-mips, xemu: qemu-mips-static },
|
||||
{ name: RISC-V, xcc_pkg: gcc-riscv64-linux-gnu, xcc: riscv64-linux-gnu-gcc, xemu_pkg: qemu-system-riscv64,xemu: qemu-riscv64-static },
|
||||
{ name: M68K, xcc_pkg: gcc-m68k-linux-gnu, xcc: m68k-linux-gnu-gcc, xemu_pkg: qemu-system-m68k, xemu: qemu-m68k-static },
|
||||
{ name: SPARC, xcc_pkg: gcc-sparc64-linux-gnu, xcc: sparc64-linux-gnu-gcc, xemu_pkg: qemu-system-sparc, xemu: qemu-sparc64-static },
|
||||
]
|
||||
env: # Set environment variables
|
||||
XCC: ${{ matrix.xcc }}
|
||||
XEMU: ${{ matrix.xemu }}
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: apt update & install
|
||||
run: |
|
||||
sudo apt-get update
|
||||
@@ -411,6 +409,7 @@ jobs:
|
||||
- name: ARM64
|
||||
if: ${{ matrix.name == 'ARM64' }}
|
||||
run: |
|
||||
LDFLAGS="-static -z force-bti" MOREFLAGS="-mbranch-protection=standard" CC=$XCC QEMU_SYS=$XEMU make clean check
|
||||
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check
|
||||
- name: PPC
|
||||
if: ${{ matrix.name == 'PPC' }}
|
||||
@@ -428,10 +427,18 @@ jobs:
|
||||
if: ${{ matrix.name == 'MIPS' }}
|
||||
run: |
|
||||
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check
|
||||
- name: RISC-V
|
||||
if: ${{ matrix.name == 'RISC-V' }}
|
||||
run: |
|
||||
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check
|
||||
- name: M68K
|
||||
if: ${{ matrix.name == 'M68K' }}
|
||||
run: |
|
||||
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check
|
||||
- name: SPARC
|
||||
if: ${{ matrix.name == 'SPARC' }}
|
||||
run: |
|
||||
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check
|
||||
|
||||
mingw-short-test:
|
||||
runs-on: windows-latest
|
||||
@@ -447,8 +454,8 @@ jobs:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: msys2/setup-msys2@5beef6d11f48bba68b9eb503e3adc60b23c0cc36 # tag=v2
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- uses: msys2/setup-msys2@cc11e9188b693c2b100158c3322424c4cc1dadea # tag=v2.22.0
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
install: make diffutils
|
||||
@@ -483,9 +490,9 @@ jobs:
|
||||
platform: [x64, Win32]
|
||||
configuration: [Release]
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # tag=v1.3
|
||||
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # tag=v2.0.0
|
||||
- name: Build and run tests
|
||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
||||
env:
|
||||
@@ -504,7 +511,7 @@ jobs:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- run: git config --global core.autocrlf input
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- uses: cygwin/cygwin-install-action@006ad0b0946ca6d0a3ea2d4437677fa767392401 # tag=master
|
||||
with:
|
||||
platform: x86_64
|
||||
@@ -526,31 +533,12 @@ jobs:
|
||||
make -C tests fuzzer &&
|
||||
./tests/fuzzer.exe -v -T1m
|
||||
|
||||
intel-cet-compatibility:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- name: Build Zstd
|
||||
run: |
|
||||
make -j zstd V=1
|
||||
readelf -n zstd
|
||||
- name: Get Intel SDE
|
||||
run: |
|
||||
curl -LO https://downloadmirror.intel.com/684899/sde-external-9.0.0-2021-11-07-lin.tar.xz
|
||||
tar xJvf sde-external-9.0.0-2021-11-07-lin.tar.xz
|
||||
- name: Configure Permissions
|
||||
run: |
|
||||
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
|
||||
- name: Run Under SDE
|
||||
run: |
|
||||
sde-external-9.0.0-2021-11-07-lin/sde -cet -cet-raise 0 -cet-endbr-exe -cet-stderr -cet-abort -- ./zstd -b3
|
||||
|
||||
pkg-config:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: debian:testing
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt -y update
|
||||
@@ -565,7 +553,7 @@ jobs:
|
||||
versions-compatibility:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Versions Compatibility Test
|
||||
run: |
|
||||
make -C tests versionsTest
|
||||
@@ -573,7 +561,7 @@ jobs:
|
||||
clangbuild:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: make clangbuild
|
||||
run: |
|
||||
make clangbuild
|
||||
@@ -581,7 +569,7 @@ jobs:
|
||||
clang-pgo:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Build PGO Zstd with Clang
|
||||
env:
|
||||
CC: clang-14
|
||||
@@ -593,7 +581,7 @@ jobs:
|
||||
gcc-pgo:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Build PGO Zstd with GCC
|
||||
env:
|
||||
CC: gcc
|
||||
@@ -601,10 +589,29 @@ jobs:
|
||||
make -C programs zstd-pgo
|
||||
./programs/zstd -b
|
||||
|
||||
intel-cet-compatibility:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
- name: Build Zstd
|
||||
run: |
|
||||
make -j zstd V=1
|
||||
readelf -n zstd
|
||||
- name: Get Intel SDE
|
||||
run: |
|
||||
curl -LO https://downloadmirror.intel.com/813591/sde-external-9.33.0-2024-01-07-lin.tar.xz
|
||||
tar xJvf sde-external-9.33.0-2024-01-07-lin.tar.xz
|
||||
- name: Configure Permissions
|
||||
run: |
|
||||
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
|
||||
- name: Run Under SDE
|
||||
run: |
|
||||
sde-external-9.33.0-2024-01-07-lin/sde -cet -cet-raise 0 -cet-endbr-exe -cet-stderr -cet-abort -- ./zstd -b3
|
||||
|
||||
|
||||
# Failing tests, for reference
|
||||
|
||||
# For reference : icc tests
|
||||
# icc tests are currently failing on Github Actions, likely to issues during installation stage
|
||||
# To be fixed later
|
||||
#
|
||||
# icc:
|
||||
# name: icc-check
|
||||
@@ -620,7 +627,7 @@ jobs:
|
||||
# sudo add-apt-repository "deb https://apt.repos.intel.com/oneapi all main"
|
||||
# sudo apt-get update
|
||||
# sudo apt-get install -y intel-basekit intel-hpckit
|
||||
# - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
# - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
|
||||
# - name: make check
|
||||
# run: |
|
||||
# make CC=/opt/intel/oneapi/compiler/latest/linux/bin/intel64/icc check
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
name: facebook/zstd/nightly
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 0 * * *
|
||||
push:
|
||||
branches:
|
||||
- release
|
||||
- dev
|
||||
- master
|
||||
permissions: read-all
|
||||
jobs:
|
||||
regression-test:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
docker:
|
||||
image: fbopensource/zstd-circleci-primary:0.0.1
|
||||
options: --entrypoint /bin/bash
|
||||
env:
|
||||
CIRCLE_ARTIFACTS: "/tmp/circleci-artifacts"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
key: regression-cache-{{ checksum "tests/regression/data.c" }}-v0
|
||||
path: tests/regression/cache
|
||||
restore-keys: regression-cache-{{ checksum "tests/regression/data.c" }}-v0
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: "/tmp/circleci-artifacts"
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install libcurl4-gnutls-dev
|
||||
- name: Regression Test
|
||||
run: |
|
||||
make -C programs zstd
|
||||
make -C tests/regression test
|
||||
mkdir -p $CIRCLE_ARTIFACTS
|
||||
./tests/regression/test \
|
||||
--cache tests/regression/cache \
|
||||
--output $CIRCLE_ARTIFACTS/results.csv \
|
||||
--zstd programs/zstd
|
||||
echo "NOTE: The new results.csv is uploaded as an artifact to this job"
|
||||
echo " If this fails, go to the Artifacts pane in CircleCI, "
|
||||
echo " download /tmp/circleci-artifacts/results.csv, and if they "
|
||||
echo " are still good, copy it into the repo and commit it."
|
||||
echo "> diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv"
|
||||
diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv
|
||||
|
||||
# Longer tests
|
||||
#- make -C tests test-zstd-nolegacy && make clean
|
||||
#- pyenv global 3.4.4; make -C tests versionsTest && make clean
|
||||
#- make zlibwrapper && make clean
|
||||
#- gcc -v; make -C tests test32 MOREFLAGS="-I/usr/include/x86_64-linux-gnu" && make clean
|
||||
#- make uasan && make clean
|
||||
#- make asan32 && make clean
|
||||
#- make -C tests test32 CC=clang MOREFLAGS="-g -fsanitize=address -I/usr/include/x86_64-linux-gnu"
|
||||
# Valgrind tests
|
||||
#- CFLAGS="-O1 -g" make -C zlibWrapper valgrindTest && make clean
|
||||
#- make -C tests valgrindTest && make clean
|
||||
# ARM, AArch64, PowerPC, PowerPC64 tests
|
||||
#- make ppctest && make clean
|
||||
#- make ppc64test && make clean
|
||||
#- make armtest && make clean
|
||||
#- make aarch64test && make clean
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3
|
||||
|
||||
- name: Archive
|
||||
env:
|
||||
|
||||
@@ -27,12 +27,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # tag=v2.2.0
|
||||
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # tag=v2.3.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3.1.3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # tag=v4.3.1
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -59,6 +59,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@a09933a12a80f87b87005513f0abb1494c27a716 # tag=v2.21.4
|
||||
uses: github/codeql-action/upload-sarif@3ab4101902695724f9365a384f86c1074d94e18c # tag=v3.24.7
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # tag=v3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3
|
||||
- uses: msys2/setup-msys2@5beef6d11f48bba68b9eb503e3adc60b23c0cc36 # tag=v2
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
cd ..
|
||||
|
||||
- name: Publish zstd-$VERSION-${{matrix.ziparch}}.zip
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # tag=v4.3.1
|
||||
with:
|
||||
path: ${{ github.workspace }}/zstd-${{ github.ref_name }}-${{matrix.ziparch}}.zip
|
||||
name: zstd-${{ github.ref_name }}-${{matrix.ziparch}}.zip
|
||||
|
||||
+7
-2
@@ -27,6 +27,8 @@ tmp*
|
||||
dictionary.
|
||||
dictionary
|
||||
NUL
|
||||
cmakebuild/
|
||||
install/
|
||||
|
||||
# Build artefacts
|
||||
contrib/linux-kernel/linux/
|
||||
@@ -37,12 +39,15 @@ buck-out/
|
||||
build-*
|
||||
*.gcda
|
||||
|
||||
# IDE
|
||||
.clang_complete
|
||||
compile_flags.txt
|
||||
.clang-format
|
||||
|
||||
# Other files
|
||||
.directory
|
||||
_codelite/
|
||||
_zstdbench/
|
||||
.clang_complete
|
||||
compile_flags.txt
|
||||
*.idea
|
||||
*.swp
|
||||
.DS_Store
|
||||
|
||||
@@ -1,3 +1,40 @@
|
||||
V1.5.6 (Mar 2024)
|
||||
api: Promote `ZSTD_c_targetCBlockSize` to Stable API by @felixhandte
|
||||
api: new `ZSTD_d_maxBlockSize` experimental parameter, to reduce streaming decompression memory, by @terrelln
|
||||
perf: improve performance of param `ZSTD_c_targetCBlockSize`, by @Cyan4973
|
||||
perf: improved compression of arrays of integers at high compression, by @Cyan4973
|
||||
lib: reduce binary size with selective built-time exclusion, by @felixhandte
|
||||
lib: improved huffman speed on small data and linux kernel, by @terrelln
|
||||
lib: accept dictionaries with partial literal tables, by @terrelln
|
||||
lib: fix CCtx size estimation with external sequence producer, by @embg
|
||||
lib: fix corner case decoder behaviors, by @Cyan4973 and @aimuz
|
||||
lib: fix zdict prototype mismatch in static_only mode, by @ldv-alt
|
||||
lib: fix several bugs in magicless-format decoding, by @embg
|
||||
cli: add common compressed file types to `--exclude-compressed`` by @daniellerozenblit
|
||||
cli: fix mixing `-c` and `-o` commands with `--rm`, by @Cyan4973
|
||||
cli: fix erroneous exclusion of hidden files with `--output-dir-mirror` by @felixhandte
|
||||
cli: improved time accuracy on BSD, by @felixhandte
|
||||
cli: better errors on argument parsing, by @KapJI
|
||||
tests: better compatibility with older versions of `grep`, by @Cyan4973
|
||||
tests: lorem ipsum generator as default backup content, by @Cyan4973
|
||||
build: cmake improvements by @terrelln, @sighingnow, @gjasny, @JohanMabille, @Saverio976, @gruenich, @teo-tsirpanis
|
||||
build: bazel support, by @jondo2010
|
||||
build: fix cross-compiling for AArch64 with lld by @jcelerier
|
||||
build: fix Apple platform compatibility, by @nidhijaju
|
||||
build: fix Visual 2012 and lower compatibility, by @Cyan4973
|
||||
build: improve win32 support, by @DimitriPapadopoulos
|
||||
build: better C90 compliance for zlibWrapper, by @emaste
|
||||
port: make: fat binaries on macos, by @mredig
|
||||
port: ARM64EC compatibility for Windows, by @dunhor
|
||||
port: QNX support by @klausholstjacobsen
|
||||
port: MSYS2 and Cygwin makefile installation and test support, by @QBos07
|
||||
port: risc-v support validation in CI, by @Cyan4973
|
||||
port: sparc64 support validation in CI, by @Cyan4973
|
||||
port: AIX compatibility, by @likema
|
||||
port: HP-UX compatibility, by @likema
|
||||
doc: Improved specification accuracy, by @elasota
|
||||
bug: Fix and deprecate ZSTD_generateSequences (#3981)
|
||||
|
||||
v1.5.5 (Apr 2023)
|
||||
fix: fix rare corruption bug affecting the high compression mode, reported by @danlark1 (#3517, @terrelln)
|
||||
perf: improve mid-level compression speed (#3529, #3533, #3543, @yoniko and #3552, @terrelln)
|
||||
@@ -98,7 +135,7 @@ build: support for m68k (Motorola 68000's), by @cyan4973
|
||||
build: improved AIX support, by @Helflym
|
||||
build: improved meson unofficial build, by @eli-schwartz
|
||||
cli : custom memory limit when training dictionary (#2925), by @embg
|
||||
cli : report advanced parameters information when compressing in very verbose mode (``-vv`), by @Svetlitski-FB
|
||||
cli : report advanced parameters information when compressing in very verbose mode (`-vv`), by @Svetlitski-FB
|
||||
|
||||
v1.5.0 (May 11, 2021)
|
||||
api: Various functions promoted from experimental to stable API: (#2579-2581, @senhuang42)
|
||||
@@ -165,7 +202,7 @@ api: Add Function to Generate Skippable Frame (#2439, @senhuang42)
|
||||
perf: New Algorithms for the Long Distance Matcher (#2483, @mpu)
|
||||
perf: Performance Improvements for Long Distance Matcher (#2464, @mpu)
|
||||
perf: Don't Shrink Window Log when Streaming with a Dictionary (#2451, @terrelln)
|
||||
cli: Fix `--output-dir-mirror`'s Rejection of `..`-Containing Paths (#2512, @felixhandte)
|
||||
cli: Fix `--output-dir-mirror` rejection of `..` -containing paths (#2512, @felixhandte)
|
||||
cli: Allow Input From Console When `-f`/`--force` is Passed (#2466, @felixhandte)
|
||||
cli: Improve Help Message (#2500, @senhuang42)
|
||||
tests: Remove Flaky Tests (#2455, #2486, #2445, @Cyan4973)
|
||||
|
||||
@@ -145,7 +145,7 @@ clean:
|
||||
$(Q)$(MAKE) -C contrib/largeNbDicts $@ > $(VOID)
|
||||
$(Q)$(MAKE) -C contrib/externalSequenceProducer $@ > $(VOID)
|
||||
$(Q)$(RM) zstd$(EXT) zstdmt$(EXT) tmp*
|
||||
$(Q)$(RM) -r lz4
|
||||
$(Q)$(RM) -r lz4 cmakebuild install
|
||||
@echo Cleaning completed
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -317,7 +317,7 @@ update_regressionResults:
|
||||
# run UBsan with -fsanitize-recover=pointer-overflow
|
||||
# this only works with recent compilers such as gcc 8+
|
||||
usan: clean
|
||||
$(MAKE) test CC=clang MOREFLAGS="-g -fno-sanitize-recover=all -fsanitize-recover=pointer-overflow -fsanitize=undefined -Werror $(MOREFLAGS)"
|
||||
$(MAKE) test CC=clang MOREFLAGS="-g -fno-sanitize-recover=all -fsanitize=undefined -Werror $(MOREFLAGS)"
|
||||
|
||||
asan: clean
|
||||
$(MAKE) test CC=clang MOREFLAGS="-g -fsanitize=address -Werror $(MOREFLAGS)"
|
||||
@@ -328,17 +328,18 @@ asan-%: clean
|
||||
msan: clean
|
||||
$(MAKE) test CC=clang MOREFLAGS="-g -fsanitize=memory -fno-omit-frame-pointer -Werror $(MOREFLAGS)" HAVE_LZMA=0 # datagen.c fails this test for no obvious reason
|
||||
|
||||
msan-%: clean
|
||||
LDFLAGS=-fuse-ld=gold MOREFLAGS="-g -fno-sanitize-recover=all -fsanitize=memory -fno-omit-frame-pointer -Werror $(MOREFLAGS)" FUZZER_FLAGS="--no-big-tests $(FUZZER_FLAGS)" $(MAKE) -C $(TESTDIR) HAVE_LZMA=0 $*
|
||||
msan-%:
|
||||
$(MAKE) clean
|
||||
LDFLAGS=-fuse-ld=gold MOREFLAGS="-g -fno-sanitize-recover=all -fsanitize=memory -fno-omit-frame-pointer -Werror $(MOREFLAGS)" FUZZER_FLAGS="--no-big-tests $(FUZZER_FLAGS)" $(MAKE) -j -C $(TESTDIR) HAVE_LZMA=0 $*
|
||||
|
||||
asan32: clean
|
||||
$(MAKE) -C $(TESTDIR) test32 CC=clang MOREFLAGS="-g -fsanitize=address $(MOREFLAGS)"
|
||||
|
||||
uasan: clean
|
||||
$(MAKE) test CC=clang MOREFLAGS="-g -fno-sanitize-recover=all -fsanitize-recover=pointer-overflow -fsanitize=address,undefined -Werror $(MOREFLAGS)"
|
||||
$(MAKE) test CC=clang MOREFLAGS="-g -fno-sanitize-recover=all -fsanitize=address,undefined -Werror $(MOREFLAGS)"
|
||||
|
||||
uasan-%: clean
|
||||
LDFLAGS=-fuse-ld=gold MOREFLAGS="-g -fno-sanitize-recover=all -fsanitize-recover=pointer-overflow -fsanitize=address,undefined -Werror $(MOREFLAGS)" $(MAKE) -C $(TESTDIR) $*
|
||||
LDFLAGS=-fuse-ld=gold MOREFLAGS="-g -fno-sanitize-recover=all -fsanitize=address,undefined -Werror $(MOREFLAGS)" $(MAKE) -C $(TESTDIR) $*
|
||||
|
||||
tsan-%: clean
|
||||
LDFLAGS=-fuse-ld=gold MOREFLAGS="-g -fno-sanitize-recover=all -fsanitize=thread -Werror $(MOREFLAGS)" $(MAKE) -C $(TESTDIR) $* FUZZER_FLAGS="--no-big-tests $(FUZZER_FLAGS)"
|
||||
@@ -389,28 +390,32 @@ lz4install:
|
||||
endif
|
||||
|
||||
|
||||
CMAKE_PARAMS = -DZSTD_BUILD_CONTRIB:BOOL=ON -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_ZLIB_SUPPORT:BOOL=ON -DZSTD_LZMA_SUPPORT:BOOL=ON -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
ifneq (,$(filter MSYS%,$(shell uname)))
|
||||
HOST_OS = MSYS
|
||||
CMAKE_PARAMS = -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug -DZSTD_MULTITHREAD_SUPPORT:BOOL=OFF -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON
|
||||
endif
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# target specific tests
|
||||
#------------------------------------------------------------------------
|
||||
ifneq (,$(filter $(HOST_OS),MSYS POSIX))
|
||||
.PHONY: cmakebuild c89build gnu90build c99build gnu99build c11build bmix64build bmix32build bmi32build staticAnalyze
|
||||
cmakebuild:
|
||||
cmake --version
|
||||
$(RM) -r $(BUILDIR)/cmake/build
|
||||
$(MKDIR) $(BUILDIR)/cmake/build
|
||||
cd $(BUILDIR)/cmake/build; cmake -DCMAKE_INSTALL_PREFIX:PATH=~/install_test_dir $(CMAKE_PARAMS) ..
|
||||
$(MAKE) -C $(BUILDIR)/cmake/build -j4;
|
||||
$(MAKE) -C $(BUILDIR)/cmake/build install;
|
||||
$(MAKE) -C $(BUILDIR)/cmake/build uninstall;
|
||||
cd $(BUILDIR)/cmake/build; ctest -V -L Medium
|
||||
|
||||
CMAKE ?= cmake
|
||||
CMAKE_PARAMS = -DZSTD_BUILD_CONTRIB:BOOL=ON -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_ZLIB_SUPPORT:BOOL=ON -DZSTD_LZMA_SUPPORT:BOOL=ON
|
||||
|
||||
ifneq (,$(filter MSYS%,$(shell uname)))
|
||||
CMAKE_PARAMS = -G"MSYS Makefiles" -DZSTD_MULTITHREAD_SUPPORT:BOOL=OFF -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON
|
||||
endif
|
||||
|
||||
.PHONY: cmakebuild
|
||||
cmakebuild:
|
||||
$(CMAKE) --version
|
||||
$(RM) -r cmakebuild install
|
||||
$(MKDIR) cmakebuild install
|
||||
cd cmakebuild; $(CMAKE) -Wdev -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS="-Werror -O0" -DCMAKE_INSTALL_PREFIX=install $(CMAKE_PARAMS) ../build/cmake
|
||||
$(CMAKE) --build cmakebuild --target install -- -j V=1
|
||||
cd cmakebuild; ctest -V -L Medium
|
||||
|
||||
.PHONY: c89build gnu90build c99build gnu99build c11build bmix64build bmix32build bmi32build staticAnalyze
|
||||
c89build: clean
|
||||
$(CC) -v
|
||||
CFLAGS="-std=c89 -Werror -Wno-attributes -Wpedantic -Wno-long-long -Wno-variadic-macros -O0" $(MAKE) lib zstd
|
||||
|
||||
@@ -198,6 +198,10 @@ Going into `build` directory, you will find additional possibilities:
|
||||
You can build the zstd binary via buck by executing: `buck build programs:zstd` from the root of the repo.
|
||||
The output binary will be in `buck-out/gen/programs/`.
|
||||
|
||||
### Bazel
|
||||
|
||||
You easily can integrate zstd into your Bazel project by using the module hosted on the [Bazel Central Repository](https://registry.bazel.build/modules/zstd).
|
||||
|
||||
## Testing
|
||||
|
||||
You can run quick local smoke tests by running `make check`.
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Reporting and Fixing Security Issues
|
||||
|
||||
Please do not open GitHub issues or pull requests - this makes the problem immediately visible to everyone, including malicious actors. Security issues in this open source project can be safely reported via the Meta Bug Bounty program:
|
||||
|
||||
https://www.facebook.com/whitehat
|
||||
|
||||
Meta's security team will triage your report and determine whether or not is it eligible for a bounty under our program.
|
||||
|
||||
# Receiving Vulnerability Notifications
|
||||
|
||||
In the case that a significant security vulnerability is reported to us or discovered by us---without being publicly known---we will, at our discretion, notify high-profile, high-exposure users of Zstandard ahead of our public disclosure of the issue and associated fix.
|
||||
|
||||
If you believe your project would benefit from inclusion in this list, please reach out to one of the maintainers.
|
||||
|
||||
<!-- Note to maintainers: this list is kept [here](https://fburl.com/wiki/cgc1l62x). -->
|
||||
@@ -356,6 +356,10 @@
|
||||
RelativePath="..\..\..\programs\dibio.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\programs\lorem.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib\dictBuilder\cover.c"
|
||||
>
|
||||
|
||||
@@ -157,6 +157,8 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\programs\util.c" />
|
||||
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||
<ClCompile Include="..\..\..\programs\lorem.c" />
|
||||
<ClCompile Include="..\..\..\tests\loremOut.c" />
|
||||
<ClCompile Include="..\..\..\tests\datagencli.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
<ClCompile Include="..\..\..\programs\dibio.c" />
|
||||
<ClCompile Include="..\..\..\programs\fileio.c" />
|
||||
<ClCompile Include="..\..\..\programs\fileio_asyncio.c" />
|
||||
<ClCompile Include="..\..\..\programs\lorem.c" />
|
||||
<ClCompile Include="..\..\..\programs\zstdcli.c" />
|
||||
<ClCompile Include="..\..\..\programs\zstdcli_trace.c" />
|
||||
</ItemGroup>
|
||||
|
||||
+35
-31
@@ -7,16 +7,14 @@
|
||||
# in the COPYING file in the root directory of this source tree).
|
||||
# ################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 3.5 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}")
|
||||
if("${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")
|
||||
@@ -32,24 +30,13 @@ set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib)
|
||||
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(ASM) # And ASM
|
||||
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
|
||||
ASM # And ASM
|
||||
CXX # Testing contributed code also utilizes CXX
|
||||
)
|
||||
endif()
|
||||
project(zstd
|
||||
VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}"
|
||||
LANGUAGES C # Main library is in C
|
||||
ASM # And ASM
|
||||
CXX # Testing contributed code also utilizes CXX
|
||||
)
|
||||
|
||||
message(STATUS "ZSTD VERSION: ${zstd_VERSION}")
|
||||
set(zstd_HOMEPAGE_URL "https://facebook.github.io/zstd")
|
||||
set(zstd_DESCRIPTION "Zstandard is a real-time compression algorithm, providing high compression ratios.")
|
||||
@@ -127,10 +114,26 @@ endif ()
|
||||
#-----------------------------------------------------------------------------
|
||||
# External dependencies
|
||||
#-----------------------------------------------------------------------------
|
||||
# Define a function to handle special thread settings for HP-UX
|
||||
# See https://github.com/facebook/zstd/pull/3862 for details.
|
||||
function(setup_hpux_threads)
|
||||
find_package(Threads)
|
||||
if (NOT Threads_FOUND)
|
||||
set(CMAKE_USE_PTHREADS_INIT 1 PARENT_SCOPE)
|
||||
set(CMAKE_THREAD_LIBS_INIT -lpthread PARENT_SCOPE)
|
||||
set(CMAKE_HAVE_THREADS_LIBRARY 1 PARENT_SCOPE)
|
||||
set(Threads_FOUND TRUE PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if (ZSTD_MULTITHREAD_SUPPORT AND UNIX)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
if(CMAKE_USE_PTHREADS_INIT)
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "HP-UX")
|
||||
setup_hpux_threads()
|
||||
else()
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(THREADS_LIBS "${CMAKE_THREAD_LIBS_INIT}")
|
||||
else()
|
||||
message(SEND_ERROR "ZSTD currently does not support thread libraries other than pthreads")
|
||||
@@ -193,10 +196,6 @@ export(EXPORT zstdExports
|
||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/zstdTargets.cmake"
|
||||
NAMESPACE zstd::
|
||||
)
|
||||
configure_file(zstdConfig.cmake
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake"
|
||||
COPYONLY
|
||||
)
|
||||
|
||||
# A Package Config file that works from the installation directory
|
||||
set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/zstd)
|
||||
@@ -205,8 +204,13 @@ install(EXPORT zstdExports
|
||||
NAMESPACE zstd::
|
||||
DESTINATION ${ConfigPackageLocation}
|
||||
)
|
||||
configure_package_config_file(
|
||||
zstdConfig.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake"
|
||||
INSTALL_DESTINATION ${ConfigPackageLocation}
|
||||
)
|
||||
install(FILES
|
||||
zstdConfig.cmake
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfigVersion.cmake"
|
||||
DESTINATION ${ConfigPackageLocation}
|
||||
)
|
||||
|
||||
@@ -41,6 +41,38 @@ cmake -DZSTD_BUILD_TESTS=ON -DZSTD_LEGACY_SUPPORT=OFF ..
|
||||
make
|
||||
```
|
||||
|
||||
### how to use it with CMake FetchContent
|
||||
|
||||
For all options available, you can see it on <https://github.com/facebook/zstd/blob/dev/build/cmake/lib/CMakeLists.txt>
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
|
||||
set(ZSTD_BUILD_STATIC ON)
|
||||
set(ZSTD_BUILD_SHARED OFF)
|
||||
|
||||
FetchContent_Declare(
|
||||
zstd
|
||||
URL "https://github.com/facebook/zstd/releases/download/v1.5.5/zstd-1.5.5.tar.gz"
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
SOURCE_SUBDIR build/cmake
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(zstd)
|
||||
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
libzstd_static
|
||||
)
|
||||
|
||||
# On windows and macos this is needed
|
||||
target_include_directories(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${zstd_SOURCE_DIR}/lib
|
||||
)
|
||||
```
|
||||
|
||||
### 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)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ set(PZSTD_DIR ${ZSTD_SOURCE_DIR}/contrib/pzstd)
|
||||
include_directories(${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/common ${PZSTD_DIR})
|
||||
|
||||
add_executable(pzstd ${PROGRAMS_DIR}/util.c ${PZSTD_DIR}/main.cpp ${PZSTD_DIR}/Options.cpp ${PZSTD_DIR}/Pzstd.cpp ${PZSTD_DIR}/SkippableFrame.cpp)
|
||||
target_compile_features(pzstd PRIVATE cxx_std_11)
|
||||
set_property(TARGET pzstd APPEND PROPERTY COMPILE_DEFINITIONS "NDEBUG")
|
||||
set_property(TARGET pzstd APPEND PROPERTY COMPILE_OPTIONS "-Wno-shadow")
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ option(ZSTD_BUILD_DECOMPRESSION "BUILD DECOMPRESSION MODULE" ON)
|
||||
option(ZSTD_BUILD_DICTBUILDER "BUILD DICTBUILDER MODULE" ON)
|
||||
option(ZSTD_BUILD_DEPRECATED "BUILD DEPRECATED MODULE" OFF)
|
||||
|
||||
set(ZSTDLIB_VISIBLE "" CACHE STRING "Visiblity for ZSTDLIB API")
|
||||
set(ZSTDERRORLIB_VISIBLE "" CACHE STRING "Visiblity for ZSTDERRORLIB_VISIBLE API")
|
||||
set(ZDICTLIB_VISIBLE "" CACHE STRING "Visiblity for ZDICTLIB_VISIBLE API")
|
||||
set(ZSTDLIB_STATIC_API "" CACHE STRING "Visiblity for ZSTDLIB_STATIC_API API")
|
||||
set(ZDICTLIB_STATIC_API "" CACHE STRING "Visiblity for ZDICTLIB_STATIC_API API")
|
||||
set(ZSTDLIB_VISIBLE "" CACHE STRING "Visibility for ZSTDLIB API")
|
||||
set(ZSTDERRORLIB_VISIBLE "" CACHE STRING "Visibility for ZSTDERRORLIB_VISIBLE API")
|
||||
set(ZDICTLIB_VISIBLE "" CACHE STRING "Visibility for ZDICTLIB_VISIBLE API")
|
||||
set(ZSTDLIB_STATIC_API "" CACHE STRING "Visibility for ZSTDLIB_STATIC_API API")
|
||||
set(ZDICTLIB_STATIC_API "" CACHE STRING "Visibility for ZDICTLIB_STATIC_API API")
|
||||
|
||||
set_property(CACHE ZSTDLIB_VISIBLE PROPERTY STRINGS "" "hidden" "default" "protected" "internal")
|
||||
set_property(CACHE ZSTDERRORLIB_VISIBLE PROPERTY STRINGS "" "hidden" "default" "protected" "internal")
|
||||
@@ -33,20 +33,22 @@ if(NOT ZSTD_BUILD_SHARED AND NOT ZSTD_BUILD_STATIC)
|
||||
message(SEND_ERROR "You need to build at least one flavor of libzstd")
|
||||
endif()
|
||||
|
||||
# Define library directory, where sources and header files are located
|
||||
include_directories(${LIBRARY_DIR} ${LIBRARY_DIR}/common)
|
||||
|
||||
file(GLOB CommonSources ${LIBRARY_DIR}/common/*.c)
|
||||
file(GLOB CompressSources ${LIBRARY_DIR}/compress/*.c)
|
||||
file(GLOB DecompressSources ${LIBRARY_DIR}/decompress/*.c)
|
||||
if (MSVC)
|
||||
file(GLOB DecompressSources ${LIBRARY_DIR}/decompress/*.c)
|
||||
add_compile_options(-DZSTD_DISABLE_ASM)
|
||||
else ()
|
||||
file(GLOB DecompressSources ${LIBRARY_DIR}/decompress/*.c ${LIBRARY_DIR}/decompress/*.S)
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|AMD64.*|x86_64.*|X86_64.*")
|
||||
set(DecompressSources ${DecompressSources} ${LIBRARY_DIR}/decompress/huf_decompress_amd64.S)
|
||||
else()
|
||||
add_compile_options(-DZSTD_DISABLE_ASM)
|
||||
endif()
|
||||
endif ()
|
||||
file(GLOB DictBuilderSources ${LIBRARY_DIR}/dictBuilder/*.c)
|
||||
file(GLOB DeprecatedSources ${LIBRARY_DIR}/deprecated/*.c)
|
||||
|
||||
file(GLOB PublicHeaders ${LIBRARY_DIR}/*.h)
|
||||
file(GLOB CommonHeaders ${LIBRARY_DIR}/common/*.h)
|
||||
file(GLOB CompressHeaders ${LIBRARY_DIR}/compress/*.h)
|
||||
file(GLOB DecompressHeaders ${LIBRARY_DIR}/decompress/*.h)
|
||||
@@ -54,7 +56,7 @@ file(GLOB DictBuilderHeaders ${LIBRARY_DIR}/dictBuilder/*.h)
|
||||
file(GLOB DeprecatedHeaders ${LIBRARY_DIR}/deprecated/*.h)
|
||||
|
||||
set(Sources ${CommonSources})
|
||||
set(Headers ${LIBRARY_DIR}/zstd.h ${CommonHeaders})
|
||||
set(Headers ${PublicHeaders} ${CommonHeaders})
|
||||
if (ZSTD_BUILD_COMPRESSION)
|
||||
set(Sources ${Sources} ${CompressSources})
|
||||
set(Headers ${Headers} ${CompressHeaders})
|
||||
@@ -74,7 +76,6 @@ endif()
|
||||
|
||||
if (ZSTD_LEGACY_SUPPORT)
|
||||
set(LIBRARY_LEGACY_DIR ${LIBRARY_DIR}/legacy)
|
||||
include_directories(${LIBRARY_LEGACY_DIR})
|
||||
|
||||
set(Sources ${Sources}
|
||||
${LIBRARY_LEGACY_DIR}/zstd_v01.c
|
||||
@@ -115,10 +116,14 @@ macro (add_definition target var)
|
||||
endif ()
|
||||
endmacro ()
|
||||
|
||||
# Define directories containing the library's public headers
|
||||
set(PUBLIC_INCLUDE_DIRS ${LIBRARY_DIR})
|
||||
|
||||
# Split project to static and shared libraries build
|
||||
set(library_targets)
|
||||
if (ZSTD_BUILD_SHARED)
|
||||
add_library(libzstd_shared SHARED ${Sources} ${Headers} ${PlatformDependResources})
|
||||
target_include_directories(libzstd_shared INTERFACE $<BUILD_INTERFACE:${PUBLIC_INCLUDE_DIRS}>)
|
||||
list(APPEND library_targets libzstd_shared)
|
||||
if (ZSTD_MULTITHREAD_SUPPORT)
|
||||
set_property(TARGET libzstd_shared APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_MULTITHREAD")
|
||||
@@ -132,6 +137,7 @@ if (ZSTD_BUILD_SHARED)
|
||||
endif ()
|
||||
if (ZSTD_BUILD_STATIC)
|
||||
add_library(libzstd_static STATIC ${Sources} ${Headers})
|
||||
target_include_directories(libzstd_static INTERFACE $<BUILD_INTERFACE:${PUBLIC_INCLUDE_DIRS}>)
|
||||
list(APPEND library_targets libzstd_static)
|
||||
if (ZSTD_MULTITHREAD_SUPPORT)
|
||||
set_property(TARGET libzstd_static APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_MULTITHREAD")
|
||||
@@ -145,6 +151,36 @@ if (ZSTD_BUILD_STATIC)
|
||||
add_definition(libzstd_static ZSTDLIB_STATIC_API)
|
||||
add_definition(libzstd_static ZDICTLIB_STATIC_API)
|
||||
endif ()
|
||||
if (ZSTD_BUILD_SHARED AND NOT ZSTD_BUILD_STATIC)
|
||||
if (NOT BUILD_SHARED_LIBS)
|
||||
message(WARNING "BUILD_SHARED_LIBS is OFF, but ZSTD_BUILD_SHARED is ON and ZSTD_BUILD_STATIC is OFF, which takes precedence, so libzstd is a shared library")
|
||||
endif ()
|
||||
add_library(libzstd INTERFACE)
|
||||
target_link_libraries(libzstd INTERFACE libzstd_shared)
|
||||
list(APPEND library_targets libzstd)
|
||||
endif ()
|
||||
if (ZSTD_BUILD_STATIC AND NOT ZSTD_BUILD_SHARED)
|
||||
if (BUILD_SHARED_LIBS)
|
||||
message(WARNING "BUILD_SHARED_LIBS is ON, but ZSTD_BUILD_SHARED is OFF and ZSTD_BUILD_STATIC is ON, which takes precedence, is set so libzstd is a static library")
|
||||
endif ()
|
||||
add_library(libzstd INTERFACE)
|
||||
target_link_libraries(libzstd INTERFACE libzstd_static)
|
||||
list(APPEND library_targets libzstd)
|
||||
endif ()
|
||||
if (ZSTD_BUILD_SHARED AND ZSTD_BUILD_STATIC)
|
||||
# If both ZSTD_BUILD_SHARED and ZSTD_BUILD_STATIC are set, which is the
|
||||
# default, fallback to using BUILD_SHARED_LIBS to determine whether to
|
||||
# set libzstd to static or shared.
|
||||
if (BUILD_SHARED_LIBS)
|
||||
add_library(libzstd INTERFACE)
|
||||
target_link_libraries(libzstd INTERFACE libzstd_shared)
|
||||
list(APPEND library_targets libzstd)
|
||||
else ()
|
||||
add_library(libzstd INTERFACE)
|
||||
target_link_libraries(libzstd INTERFACE libzstd_static)
|
||||
list(APPEND library_targets libzstd)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Add specific compile definitions for MSVC project
|
||||
if (MSVC)
|
||||
@@ -194,11 +230,7 @@ configure_file("${LIBRARY_DIR}/libzstd.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libzs
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libzstd.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
|
||||
# install target
|
||||
install(FILES
|
||||
"${LIBRARY_DIR}/zstd.h"
|
||||
"${LIBRARY_DIR}/zdict.h"
|
||||
"${LIBRARY_DIR}/zstd_errors.h"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
install(FILES ${PublicHeaders} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
install(TARGETS ${library_targets}
|
||||
EXPORT zstdExports
|
||||
|
||||
@@ -32,12 +32,7 @@ if (MSVC)
|
||||
set(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstd.rc)
|
||||
endif ()
|
||||
|
||||
set(ZSTD_PROGRAM_SRCS ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c
|
||||
${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/fileio.c
|
||||
${PROGRAMS_DIR}/fileio_asyncio.c ${PROGRAMS_DIR}/benchfn.c
|
||||
${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c
|
||||
${PROGRAMS_DIR}/dibio.c ${PROGRAMS_DIR}/zstdcli_trace.c
|
||||
${PlatformDependResources})
|
||||
file(GLOB ZSTD_PROGRAM_SRCS "${PROGRAMS_DIR}/*.c")
|
||||
if (MSVC AND ZSTD_PROGRAMS_LINK_SHARED)
|
||||
list(APPEND ZSTD_PROGRAM_SRCS ${LIBRARY_DIR}/common/pool.c ${LIBRARY_DIR}/common/threading.c)
|
||||
endif ()
|
||||
|
||||
@@ -50,18 +50,18 @@ set(PROGRAMS_DIR ${ZSTD_SOURCE_DIR}/programs)
|
||||
set(TESTS_DIR ${ZSTD_SOURCE_DIR}/tests)
|
||||
include_directories(${TESTS_DIR} ${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/common ${LIBRARY_DIR}/compress ${LIBRARY_DIR}/dictBuilder)
|
||||
|
||||
add_executable(datagen ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/datagencli.c)
|
||||
add_executable(datagen ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/lorem.c ${TESTS_DIR}/loremOut.c ${TESTS_DIR}/datagencli.c)
|
||||
target_link_libraries(datagen libzstd_static)
|
||||
|
||||
#
|
||||
# fullbench
|
||||
#
|
||||
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)
|
||||
add_executable(fullbench ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/lorem.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${TESTS_DIR}/fullbench.c)
|
||||
if (NOT MSVC)
|
||||
target_compile_options(fullbench PRIVATE "-Wno-deprecated-declarations")
|
||||
endif()
|
||||
target_link_libraries(fullbench libzstd_static)
|
||||
add_test(NAME fullbench COMMAND fullbench ${ZSTD_FULLBENCH_FLAGS})
|
||||
add_test(NAME fullbench COMMAND "$<TARGET_FILE:fullbench>" ${ZSTD_FULLBENCH_FLAGS})
|
||||
|
||||
#
|
||||
# fuzzer
|
||||
@@ -73,7 +73,7 @@ endif()
|
||||
target_link_libraries(fuzzer libzstd_static)
|
||||
AddTestFlagsOption(ZSTD_FUZZER_FLAGS "$ENV{FUZZERTEST} $ENV{FUZZER_FLAGS}"
|
||||
"Semicolon-separated list of flags to pass to the fuzzer test (see `fuzzer -h` for usage)")
|
||||
add_test(NAME fuzzer COMMAND fuzzer ${ZSTD_FUZZER_FLAGS})
|
||||
add_test(NAME fuzzer COMMAND "$<TARGET_FILE:fuzzer>" ${ZSTD_FUZZER_FLAGS})
|
||||
# Disable the timeout since the run time is too long for the default timeout of
|
||||
# 1500 seconds and varies considerably between low-end and high-end CPUs.
|
||||
# set_tests_properties(fuzzer PROPERTIES TIMEOUT 0)
|
||||
@@ -88,7 +88,7 @@ endif()
|
||||
target_link_libraries(zstreamtest libzstd_static)
|
||||
AddTestFlagsOption(ZSTD_ZSTREAM_FLAGS "$ENV{ZSTREAM_TESTTIME} $ENV{FUZZER_FLAGS}"
|
||||
"Semicolon-separated list of flags to pass to the zstreamtest test (see `zstreamtest -h` for usage)")
|
||||
add_test(NAME zstreamtest COMMAND zstreamtest ${ZSTD_ZSTREAM_FLAGS})
|
||||
add_test(NAME zstreamtest COMMAND "$<TARGET_FILE:zstreamtest>" ${ZSTD_ZSTREAM_FLAGS})
|
||||
|
||||
#
|
||||
# playTests.sh
|
||||
@@ -110,7 +110,7 @@ endif()
|
||||
# Label the "Medium" set of tests (see TESTING.md)
|
||||
set_property(TEST fuzzer zstreamtest playTests APPEND PROPERTY LABELS Medium)
|
||||
|
||||
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)
|
||||
add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/lorem.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/paramgrill.c)
|
||||
if (UNIX)
|
||||
target_link_libraries(paramgrill libzstd_static m) #m is math library
|
||||
else()
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/zstdTargets.cmake")
|
||||
@@ -0,0 +1,10 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
if(@ZSTD_MULTITHREAD_SUPPORT@ AND "@UNIX@")
|
||||
find_dependency(Threads)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/zstdTargets.cmake")
|
||||
|
||||
check_required_components("zstd")
|
||||
@@ -18,6 +18,7 @@ zstd_programs_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'),
|
||||
join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
||||
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
||||
join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||
join_paths(zstd_rootdir, 'programs/lorem.c'),
|
||||
join_paths(zstd_rootdir, 'programs/dibio.c'),
|
||||
join_paths(zstd_rootdir, 'programs/zstdcli_trace.c')]
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ DECODECORPUS_TESTTIME = '-T30'
|
||||
test_includes = [ include_directories(join_paths(zstd_rootdir, 'programs')) ]
|
||||
|
||||
testcommon_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||
join_paths(zstd_rootdir, 'programs/lorem.c'),
|
||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||
join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
||||
@@ -43,7 +44,8 @@ testcommon_dep = declare_dependency(link_with: testcommon,
|
||||
dependencies: libzstd_deps,
|
||||
include_directories: libzstd_includes)
|
||||
|
||||
datagen_sources = [join_paths(zstd_rootdir, 'tests/datagencli.c')]
|
||||
datagen_sources = [join_paths(zstd_rootdir, 'tests/datagencli.c'),
|
||||
join_paths(zstd_rootdir, 'tests/loremOut.c')]
|
||||
datagen = executable('datagen',
|
||||
datagen_sources,
|
||||
c_args: [ '-DNDEBUG' ],
|
||||
|
||||
@@ -77,7 +77,7 @@ EXPORT_SYMBOL(zstd_init_dstream);
|
||||
|
||||
size_t zstd_reset_dstream(zstd_dstream *dstream)
|
||||
{
|
||||
return ZSTD_resetDStream(dstream);
|
||||
return ZSTD_DCtx_reset(dstream, ZSTD_reset_session_only);
|
||||
}
|
||||
EXPORT_SYMBOL(zstd_reset_dstream);
|
||||
|
||||
|
||||
@@ -115,11 +115,7 @@ static uint64_t ZSTD_div64(uint64_t dividend, uint32_t divisor) {
|
||||
#ifndef ZSTD_DEPS_STDINT
|
||||
#define ZSTD_DEPS_STDINT
|
||||
|
||||
/*
|
||||
* The Linux Kernel doesn't provide intptr_t, only uintptr_t, which
|
||||
* is an unsigned long.
|
||||
*/
|
||||
typedef long intptr_t;
|
||||
/* intptr_t already provided by ZSTD_DEPS_COMMON */
|
||||
|
||||
#endif /* ZSTD_DEPS_STDINT */
|
||||
#endif /* ZSTD_DEPS_NEED_STDINT */
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# Standard variables for installation
|
||||
DESTDIR ?=
|
||||
PREFIX ?= /usr/local
|
||||
BINDIR := $(DESTDIR)$(PREFIX)/bin
|
||||
BINDIR := $(PREFIX)/bin
|
||||
|
||||
ZSTDDIR = ../../lib
|
||||
PROGDIR = ../../programs
|
||||
@@ -37,11 +37,8 @@ CFLAGS += -Wno-deprecated-declarations
|
||||
PZSTD_INC = -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(PROGDIR) -I.
|
||||
GTEST_INC = -isystem googletest/googletest/include
|
||||
|
||||
# If default C++ version is older than C++11, explicitly set C++11, which is the
|
||||
# minimum required by the code.
|
||||
ifeq ($(shell echo "\043if __cplusplus < 201103L\n\043error\n\043endif" | $(CXX) -x c++ -Werror -c - -o /dev/null 2>/dev/null && echo 1 || echo 0),0)
|
||||
PZSTD_CXX_STD := -std=c++11
|
||||
endif
|
||||
# Set the minimum required by gtest
|
||||
PZSTD_CXX_STD := -std=c++14
|
||||
|
||||
PZSTD_CPPFLAGS = $(PZSTD_INC)
|
||||
PZSTD_CCXXFLAGS =
|
||||
@@ -112,12 +109,12 @@ check:
|
||||
.PHONY: install
|
||||
install: PZSTD_CPPFLAGS += -DNDEBUG
|
||||
install: pzstd$(EXT)
|
||||
install -d -m 755 $(BINDIR)/
|
||||
install -m 755 pzstd$(EXT) $(BINDIR)/pzstd$(EXT)
|
||||
install -d -m 755 $(DESTDIR)$(BINDIR)/
|
||||
install -m 755 pzstd$(EXT) $(DESTDIR)$(BINDIR)/pzstd$(EXT)
|
||||
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
||||
$(RM) $(BINDIR)/pzstd$(EXT)
|
||||
$(RM) $(DESTDIR)$(BINDIR)/pzstd$(EXT)
|
||||
|
||||
# Targets for many different builds
|
||||
.PHONY: all
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include <zstd_errors.h>
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
# define SLEEP(x) Sleep(x)
|
||||
#else
|
||||
|
||||
@@ -125,3 +125,24 @@ The total `Block_Content` is `5` bytes, and `Last_Table_Offset` is `2`.
|
||||
See the compressor workaround code:
|
||||
|
||||
https://github.com/facebook/zstd/blob/8814aa5bfa74f05a86e55e9d508da177a893ceeb/lib/compress/zstd_compress.c#L2667-L2682
|
||||
|
||||
Magicless format
|
||||
----------------------
|
||||
|
||||
**Last affected version**: v1.5.5
|
||||
|
||||
**Affected decompressor component(s)**: Library
|
||||
|
||||
**Produced by the reference compressor**: Yes (example: https://gist.github.com/embg/9940726094f4cf2cef162cffe9319232)
|
||||
|
||||
**Example Frame**: `27 b5 2f fd 00 03 19 00 00 66 6f 6f 3f ba c4 59`
|
||||
|
||||
v1.5.6 fixes several bugs in which the magicless-format decoder rejects valid frames.
|
||||
These include but are not limited to:
|
||||
* Valid frames that happen to begin with a legacy magic number (little-endian)
|
||||
* Valid frames that happen to begin with a skippable magic number (little-endian)
|
||||
|
||||
If you are affected by this issue and cannot update to v1.5.6 or later, there is a
|
||||
workaround to recover affected data. Simply prepend the ZSTD magic number
|
||||
`0xFD2FB528` (little-endian) to your data and decompress using the standard-format
|
||||
decoder.
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
Decompressor Permissiveness to Invalid Data
|
||||
===========================================
|
||||
|
||||
This document describes the behavior of the reference decompressor in cases
|
||||
where it accepts formally invalid data instead of reporting an error.
|
||||
|
||||
While the reference decompressor *must* decode any compliant frame following
|
||||
the specification, its ability to detect erroneous data is on a best effort
|
||||
basis: the decoder may accept input data that would be formally invalid,
|
||||
when it causes no risk to the decoder, and which detection would cost too much
|
||||
complexity or speed regression.
|
||||
|
||||
In practice, the vast majority of invalid data are detected, if only because
|
||||
many corruption events are dangerous for the decoder process (such as
|
||||
requesting an out-of-bound memory access) and many more are easy to check.
|
||||
|
||||
This document lists a few known cases where invalid data was formerly accepted
|
||||
by the decoder, and what has changed since.
|
||||
|
||||
|
||||
Offset == 0
|
||||
-----------
|
||||
|
||||
**Last affected version**: v1.5.5
|
||||
|
||||
**Produced by the reference compressor**: No
|
||||
|
||||
**Example Frame**: `28b5 2ffd 0000 4500 0008 0002 002f 430b ae`
|
||||
|
||||
If a sequence is decoded with `literals_length = 0` and `offset_value = 3`
|
||||
while `Repeated_Offset_1 = 1`, the computed offset will be `0`, which is
|
||||
invalid.
|
||||
|
||||
The reference decompressor up to v1.5.5 processes this case as if the computed
|
||||
offset was `1`, including inserting `1` into the repeated offset list.
|
||||
This prevents the output buffer from remaining uninitialized, thus denying a
|
||||
potential attack vector from an untrusted source.
|
||||
However, in the rare case where this scenario would be the outcome of a
|
||||
transmission or storage error, the decoder relies on the checksum to detect
|
||||
the error.
|
||||
|
||||
In newer versions, this case is always detected and reported as a corruption error.
|
||||
|
||||
|
||||
Non-zeroes reserved bits
|
||||
------------------------
|
||||
|
||||
**Last affected version**: v1.5.5
|
||||
|
||||
**Produced by the reference compressor**: No
|
||||
|
||||
The Sequences section of each block has a header, and one of its elements is a
|
||||
byte, which describes the compression mode of each symbol.
|
||||
This byte contains 2 reserved bits which must be set to zero.
|
||||
|
||||
The reference decompressor up to v1.5.5 just ignores these 2 bits.
|
||||
This behavior has no consequence for the rest of the frame decoding process.
|
||||
|
||||
In newer versions, the 2 reserved bits are actively checked for value zero,
|
||||
and the decoder reports a corruption error if they are not.
|
||||
@@ -1213,7 +1213,7 @@ static void decode_seq_table(FSE_dtable *const table, istream_t *const in,
|
||||
break;
|
||||
}
|
||||
case seq_repeat:
|
||||
// "Repeat_Mode : re-use distribution table from previous compressed
|
||||
// "Repeat_Mode : reuse distribution table from previous compressed
|
||||
// block."
|
||||
// Nothing to do here, table will be unchanged
|
||||
if (!table->symbols) {
|
||||
|
||||
@@ -929,7 +929,10 @@ There is an exception though, when current sequence's `literals_length = 0`.
|
||||
In this case, repeated offsets are shifted by one,
|
||||
so an `offset_value` of 1 means `Repeated_Offset2`,
|
||||
an `offset_value` of 2 means `Repeated_Offset3`,
|
||||
and an `offset_value` of 3 means `Repeated_Offset1 - 1_byte`.
|
||||
and an `offset_value` of 3 means `Repeated_Offset1 - 1`.
|
||||
|
||||
In the final case, if `Repeated_Offset1 - 1` evaluates to 0, then the
|
||||
data is considered corrupted.
|
||||
|
||||
For the first block, the starting offset history is populated with following values :
|
||||
`Repeated_Offset1`=1, `Repeated_Offset2`=4, `Repeated_Offset3`=8,
|
||||
@@ -1083,7 +1086,8 @@ It depends on :
|
||||
Presuming an `Accuracy_Log` of 8,
|
||||
and presuming 100 probabilities points have already been distributed,
|
||||
the decoder may read any value from `0` to `256 - 100 + 1 == 157` (inclusive).
|
||||
Therefore, it must read `log2sup(157) == 8` bits.
|
||||
Therefore, it may read up to `log2sup(157) == 8` bits, where `log2sup(N)`
|
||||
is the smallest integer `T` that satisfies `(1 << T) > N`.
|
||||
|
||||
- Value decoded : small values use 1 less bit :
|
||||
__example__ :
|
||||
@@ -1123,6 +1127,9 @@ When last symbol reaches cumulated total of `1 << Accuracy_Log`,
|
||||
decoding is complete.
|
||||
If the last symbol makes cumulated total go above `1 << Accuracy_Log`,
|
||||
distribution is considered corrupted.
|
||||
If this process results in a non-zero probability for a value outside of the
|
||||
valid range of values that the FSE table is defined for, even if that value is
|
||||
not used, then the data is considered corrupted.
|
||||
|
||||
Then the decoder can tell how many bytes were used in this process,
|
||||
and how many symbols are present.
|
||||
@@ -1186,9 +1193,9 @@ Baseline is assigned starting from the higher states using fewer bits,
|
||||
increasing at each state, then resuming at the first state,
|
||||
each state takes its allocated width from Baseline.
|
||||
|
||||
| state value | 1 | 39 | 77 | 84 | 122 |
|
||||
| state order | 0 | 1 | 2 | 3 | 4 |
|
||||
| ---------------- | ----- | ----- | ------ | ---- | ------ |
|
||||
| state value | 1 | 39 | 77 | 84 | 122 |
|
||||
| width | 32 | 32 | 32 | 16 | 16 |
|
||||
| `Number_of_Bits` | 5 | 5 | 5 | 4 | 4 |
|
||||
| range number | 2 | 4 | 6 | 0 | 1 |
|
||||
@@ -1251,7 +1258,9 @@ Number_of_Bits = Weight ? (Max_Number_of_Bits + 1 - Weight) : 0
|
||||
```
|
||||
When a literal value is not present, it receives a `Weight` of 0.
|
||||
The least frequent symbol receives a `Weight` of 1.
|
||||
Consequently, the `Weight` 1 is necessarily present.
|
||||
If no literal has a `Weight` of 1, then the data is considered corrupted.
|
||||
If there are not at least two literals with non-zero `Weight`, then the data
|
||||
is considered corrupted.
|
||||
The most frequent symbol receives a `Weight` anywhere between 1 and 11 (max).
|
||||
The last symbol's `Weight` is deduced from previously retrieved Weights,
|
||||
by completing to the nearest power of 2. It's necessarily non 0.
|
||||
@@ -1352,6 +1361,9 @@ If updating state after decoding a symbol would require more bits than
|
||||
remain in the stream, it is assumed that extra bits are 0. Then,
|
||||
symbols for each of the final states are decoded and the process is complete.
|
||||
|
||||
If this process would produce more weights than the maximum number of decoded
|
||||
weights (255), then the data is considered corrupted.
|
||||
|
||||
#### Conversion from weights to Huffman prefix codes
|
||||
|
||||
All present symbols shall now have a `Weight` value.
|
||||
|
||||
+87
-42
@@ -1,10 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>zstd 1.5.5 Manual</title>
|
||||
<title>zstd 1.5.6 Manual</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>zstd 1.5.5 Manual</h1>
|
||||
<h1>zstd 1.5.6 Manual</h1>
|
||||
<hr>
|
||||
<a name="Contents"></a><h2>Contents</h2>
|
||||
<ol>
|
||||
@@ -156,7 +156,7 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
|
||||
* for example to size a static array on stack.
|
||||
* Will produce constant value 0 if srcSize too large.
|
||||
*/
|
||||
#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00LLU : 0xFF00FF00U)
|
||||
#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00ULL : 0xFF00FF00U)
|
||||
#define ZSTD_COMPRESSBOUND(srcSize) (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (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>
|
||||
</b>/* ZSTD_isError() :<b>
|
||||
@@ -174,7 +174,7 @@ int ZSTD_defaultCLevel(void); </b>/*!< default compression lev
|
||||
|
||||
<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.
|
||||
and reuse it for each successive compression operation.
|
||||
This will make workload friendlier for system's memory.
|
||||
Note : re-using context is just a speed / resource optimization.
|
||||
It doesn't change the compression ratio, which remains identical.
|
||||
@@ -190,9 +190,9 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); </b>/* accept NULL pointer */<b>
|
||||
const void* src, size_t srcSize,
|
||||
int compressionLevel);
|
||||
</b><p> Same as ZSTD_compress(), using an explicit ZSTD_CCtx.
|
||||
Important : in order to behave similarly to `ZSTD_compress()`,
|
||||
this function compresses at requested compression level,
|
||||
__ignoring any other parameter__ .
|
||||
Important : in order to mirror `ZSTD_compress()` behavior,
|
||||
this function compresses at the requested compression level,
|
||||
__ignoring any other advanced parameter__ .
|
||||
If any advanced parameter was set using the advanced API,
|
||||
they will all be reset. Only `compressionLevel` remains.
|
||||
|
||||
@@ -200,7 +200,7 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); </b>/* accept NULL pointer */<b>
|
||||
|
||||
<h3>Decompression context</h3><pre> When decompressing many times,
|
||||
it is recommended to allocate a context only once,
|
||||
and re-use it for each successive compression operation.
|
||||
and reuse it for each successive compression operation.
|
||||
This will make workload friendlier for system's memory.
|
||||
Use one context per thread for parallel execution.
|
||||
</pre><b><pre>typedef struct ZSTD_DCtx_s ZSTD_DCtx;
|
||||
@@ -212,7 +212,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); </b>/* accept NULL pointer */<b>
|
||||
const void* src, size_t srcSize);
|
||||
</b><p> Same as ZSTD_decompress(),
|
||||
requires an allocated ZSTD_DCtx.
|
||||
Compatible with sticky parameters.
|
||||
Compatible with sticky parameters (see below).
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
@@ -296,6 +296,19 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); </b>/* accept NULL pointer */<b>
|
||||
* The higher the value of selected strategy, the more complex it is,
|
||||
* resulting in stronger and slower compression.
|
||||
* Special: value 0 means "use default strategy". */
|
||||
|
||||
ZSTD_c_targetCBlockSize=130, </b>/* v1.5.6+<b>
|
||||
* Attempts to fit compressed block size into approximatively targetCBlockSize.
|
||||
* Bound by ZSTD_TARGETCBLOCKSIZE_MIN and ZSTD_TARGETCBLOCKSIZE_MAX.
|
||||
* Note that it's not a guarantee, just a convergence target (default:0).
|
||||
* No target when targetCBlockSize == 0.
|
||||
* This is helpful in low bandwidth streaming environments to improve end-to-end latency,
|
||||
* when a client can make use of partial documents (a prominent example being Chrome).
|
||||
* Note: this parameter is stable since v1.5.6.
|
||||
* It was present as an experimental parameter in earlier versions,
|
||||
* but it's not recommended using it with earlier library versions
|
||||
* due to massive performance regressions.
|
||||
*/
|
||||
</b>/* LDM mode parameters */<b>
|
||||
ZSTD_c_enableLongDistanceMatching=160, </b>/* Enable long distance matching.<b>
|
||||
* This parameter is designed to improve compression ratio
|
||||
@@ -375,7 +388,6 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); </b>/* accept NULL pointer */<b>
|
||||
* ZSTD_c_forceMaxWindow
|
||||
* ZSTD_c_forceAttachDict
|
||||
* ZSTD_c_literalCompressionMode
|
||||
* ZSTD_c_targetCBlockSize
|
||||
* ZSTD_c_srcSizeHint
|
||||
* ZSTD_c_enableDedicatedDictSearch
|
||||
* ZSTD_c_stableInBuffer
|
||||
@@ -396,7 +408,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); </b>/* accept NULL pointer */<b>
|
||||
ZSTD_c_experimentalParam3=1000,
|
||||
ZSTD_c_experimentalParam4=1001,
|
||||
ZSTD_c_experimentalParam5=1002,
|
||||
ZSTD_c_experimentalParam6=1003,
|
||||
</b>/* was ZSTD_c_experimentalParam6=1003; is now ZSTD_c_targetCBlockSize */<b>
|
||||
ZSTD_c_experimentalParam7=1004,
|
||||
ZSTD_c_experimentalParam8=1005,
|
||||
ZSTD_c_experimentalParam9=1006,
|
||||
@@ -483,6 +495,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); </b>/* accept NULL pointer */<b>
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
</b><p> Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.
|
||||
(note that this entry point doesn't even expose a compression level parameter).
|
||||
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*()
|
||||
@@ -513,6 +526,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); </b>/* accept NULL pointer */<b>
|
||||
* ZSTD_d_forceIgnoreChecksum
|
||||
* ZSTD_d_refMultipleDDicts
|
||||
* ZSTD_d_disableHuffmanAssembly
|
||||
* ZSTD_d_maxBlockSize
|
||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||
* note : never ever use experimentalParam? names directly
|
||||
*/
|
||||
@@ -520,7 +534,8 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); </b>/* accept NULL pointer */<b>
|
||||
ZSTD_d_experimentalParam2=1001,
|
||||
ZSTD_d_experimentalParam3=1002,
|
||||
ZSTD_d_experimentalParam4=1003,
|
||||
ZSTD_d_experimentalParam5=1004
|
||||
ZSTD_d_experimentalParam5=1004,
|
||||
ZSTD_d_experimentalParam6=1005
|
||||
|
||||
} ZSTD_dParameter;
|
||||
</b></pre><BR>
|
||||
@@ -568,14 +583,14 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); </b>/* accept NULL pointer */<b>
|
||||
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.
|
||||
It is recommended to reuse 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.
|
||||
it will reuse 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
|
||||
@@ -666,6 +681,11 @@ size_t ZSTD_freeCStream(ZSTD_CStream* zcs); </b>/* accept NULL pointer */<b>
|
||||
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.
|
||||
- note: if an operation ends with an error, it may leave @cctx in an undefined state.
|
||||
Therefore, it's UB to invoke ZSTD_compressStream2() of ZSTD_compressStream() on such a state.
|
||||
In order to be re-employed after an error, a state must be reset,
|
||||
which can be done explicitly (ZSTD_CCtx_reset()),
|
||||
or is sometimes implied by methods starting a new compression job (ZSTD_initCStream(), ZSTD_compressCCtx())
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
@@ -698,7 +718,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
<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.
|
||||
ZSTD_DStream objects can be reused multiple times.
|
||||
|
||||
Use ZSTD_initDStream() to start a new decompression operation.
|
||||
@return : recommended first input size
|
||||
@@ -751,6 +771,12 @@ size_t ZSTD_freeDStream(ZSTD_DStream* zds); </b>/* accept NULL pointer */<b>
|
||||
@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 some decoding or flushing to do to complete current frame.
|
||||
|
||||
Note: when an operation returns with an error code, the @zds state may be left in undefined state.
|
||||
It's UB to invoke `ZSTD_decompressStream()` on such a state.
|
||||
In order to re-use such a state, it must be first reset,
|
||||
which can be done explicitly (`ZSTD_DCtx_reset()`),
|
||||
or is implied for operations starting some new decompression job (`ZSTD_initDStream`, `ZSTD_decompressDCtx()`, `ZSTD_decompress_usingDict()`)
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
@@ -869,7 +895,7 @@ size_t ZSTD_freeDStream(ZSTD_DStream* zds); </b>/* accept NULL pointer */<b>
|
||||
<a name="Chapter13"></a><h2>Advanced dictionary and prefix API (Requires v1.4.0+)</h2><pre>
|
||||
This API allows dictionaries to be used with ZSTD_compress2(),
|
||||
ZSTD_compressStream2(), and ZSTD_decompressDCtx().
|
||||
Dictionaries are sticky, they remain valid when same context is re-used,
|
||||
Dictionaries are sticky, they remain valid when same context is reused,
|
||||
they only reset when the context is reset
|
||||
with ZSTD_reset_parameters or ZSTD_reset_session_and_parameters.
|
||||
In contrast, Prefixes are single-use.
|
||||
@@ -1386,58 +1412,61 @@ ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize,
|
||||
|
||||
<a name="Chapter16"></a><h2>Memory management</h2><pre></pre>
|
||||
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int maxCompressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void);
|
||||
</b><p> These functions make it possible to estimate memory usage
|
||||
of a future {D,C}Ctx, before its creation.
|
||||
This is useful in combination with ZSTD_initStatic(),
|
||||
which makes it possible to employ a static buffer for ZSTD_CCtx* state.
|
||||
|
||||
ZSTD_estimateCCtxSize() will provide a memory budget large enough
|
||||
for any compression level up to selected one.
|
||||
Note : Unlike ZSTD_estimateCStreamSize*(), this estimate
|
||||
does not include space for a window buffer.
|
||||
Therefore, the estimation is only guaranteed for single-shot compressions, not streaming.
|
||||
to compress data of any size using one-shot compression ZSTD_compressCCtx() or ZSTD_compress2()
|
||||
associated with any compression level up to max specified one.
|
||||
The estimate will assume the input may be arbitrarily large,
|
||||
which is the worst case.
|
||||
|
||||
Note that the size estimation is specific for one-shot compression,
|
||||
it is not valid for streaming (see ZSTD_estimateCStreamSize*())
|
||||
nor other potential ways of using a ZSTD_CCtx* state.
|
||||
|
||||
When srcSize can be bound by a known and rather "small" value,
|
||||
this fact can be used to provide a tighter estimation
|
||||
because the CCtx compression context will need less memory.
|
||||
This tighter estimation can be provided by more advanced functions
|
||||
this knowledge can be used to provide a tighter budget estimation
|
||||
because the ZSTD_CCtx* state will need less memory for small inputs.
|
||||
This tighter estimation can be provided by employing more advanced functions
|
||||
ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(),
|
||||
and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter().
|
||||
Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits.
|
||||
|
||||
Note : only single-threaded compression is supported.
|
||||
ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
|
||||
Note 2 : ZSTD_estimateCCtxSize* functions are not compatible with the Block-Level Sequence Producer API at this time.
|
||||
Size estimates assume that no external sequence producer is registered.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int maxCompressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize(size_t windowSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize(size_t maxWindowSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
|
||||
</b><p> ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one.
|
||||
It will also consider src size to be arbitrarily "large", which is worst case.
|
||||
</b><p> ZSTD_estimateCStreamSize() will provide a memory budget large enough for streaming compression
|
||||
using any compression level up to the max specified one.
|
||||
It will also consider src size to be arbitrarily "large", which is a worst case scenario.
|
||||
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_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.
|
||||
ZSTD_estimateCStreamSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
Note 2 : ZSTD_estimateCStreamSize* functions are not compatible with the Block-Level Sequence Producer API at this time.
|
||||
Size estimates assume that no external sequence producer is registered.
|
||||
|
||||
ZSTD_DStream memory budget depends on frame's window Size.
|
||||
This information can be passed manually, using ZSTD_estimateDStreamSize,
|
||||
or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame();
|
||||
Any frame requesting a window size larger than max specified one will be rejected.
|
||||
Note : if streaming is init with function ZSTD_init?Stream_usingDict(),
|
||||
an internal ?Dict will be created, which additional size is not estimated here.
|
||||
In this case, get total size by adding ZSTD_estimate?DictSize
|
||||
Note 2 : only single-threaded compression is supported.
|
||||
ZSTD_estimateCStreamSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
Note 3 : ZSTD_estimateCStreamSize* functions are not compatible with the Block-Level Sequence Producer API at this time.
|
||||
Size estimates assume that no external sequence producer is registered.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
@@ -1857,7 +1886,7 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
||||
explicitly specified.
|
||||
|
||||
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.
|
||||
This is typically useful to skip dictionary loading stage, since it will reuse 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.
|
||||
If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.
|
||||
@@ -1918,7 +1947,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
</b><p>
|
||||
ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
|
||||
re-use decompression parameters from previous init; saves dictionary loading
|
||||
reuse decompression parameters from previous init; saves dictionary loading
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
@@ -1926,7 +1955,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
ZSTD_registerSequenceProducer(
|
||||
ZSTD_CCtx* cctx,
|
||||
void* sequenceProducerState,
|
||||
ZSTD_sequenceProducer_F* sequenceProducer
|
||||
ZSTD_sequenceProducer_F sequenceProducer
|
||||
);
|
||||
</b><p> Instruct zstd to use a block-level external sequence producer function.
|
||||
|
||||
@@ -1948,6 +1977,22 @@ ZSTD_registerSequenceProducer(
|
||||
calling this function.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTDLIB_STATIC_API void
|
||||
ZSTD_CCtxParams_registerSequenceProducer(
|
||||
ZSTD_CCtx_params* params,
|
||||
void* sequenceProducerState,
|
||||
ZSTD_sequenceProducer_F sequenceProducer
|
||||
);
|
||||
</b><p> Same as ZSTD_registerSequenceProducer(), but operates on ZSTD_CCtx_params.
|
||||
This is used for accurate size estimation with ZSTD_estimateCCtxSize_usingCCtxParams(),
|
||||
which is needed when creating a ZSTD_CCtx with ZSTD_initStaticCCtx().
|
||||
|
||||
If you are using the external sequence producer API in a scenario where ZSTD_initStaticCCtx()
|
||||
is required, then this function is for you. Otherwise, you probably don't need it.
|
||||
|
||||
See tests/zstreamtest.c for example usage.
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter20"></a><h2>Buffer-less and synchronous inner streaming functions (DEPRECATED)</h2><pre>
|
||||
This API is deprecated, and will be removed in a future version.
|
||||
It allows streaming (de)compression with user allocated buffers.
|
||||
@@ -1964,7 +2009,7 @@ ZSTD_registerSequenceProducer(
|
||||
<a name="Chapter21"></a><h2>Buffer-less streaming compression (synchronous mode)</h2><pre>
|
||||
A ZSTD_CCtx object is required to track streaming operations.
|
||||
Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.
|
||||
ZSTD_CCtx object can be re-used multiple times within successive compression operations.
|
||||
ZSTD_CCtx object can be reused multiple times within successive compression operations.
|
||||
|
||||
Start by initializing a context.
|
||||
Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression.
|
||||
@@ -1985,7 +2030,7 @@ ZSTD_registerSequenceProducer(
|
||||
It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.
|
||||
Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders.
|
||||
|
||||
`ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again.
|
||||
`ZSTD_CCtx` object can be reused (ZSTD_compressBegin()) to compress again.
|
||||
<BR></pre>
|
||||
|
||||
<h3>Buffer-less streaming compression functions</h3><pre></pre><b><pre>ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.")
|
||||
@@ -2002,7 +2047,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const Z
|
||||
<a name="Chapter22"></a><h2>Buffer-less streaming decompression (synchronous mode)</h2><pre>
|
||||
A ZSTD_DCtx object is required to track streaming operations.
|
||||
Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
|
||||
A ZSTD_DCtx object can be re-used multiple times.
|
||||
A ZSTD_DCtx object can be reused multiple times.
|
||||
|
||||
First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader().
|
||||
Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough.
|
||||
|
||||
+39
-27
@@ -8,6 +8,9 @@
|
||||
# You may select, at your option, one of the above-listed licenses.
|
||||
# ################################################################
|
||||
|
||||
# default target (when running `make` with no argument)
|
||||
lib-release:
|
||||
|
||||
# Modules
|
||||
ZSTD_LIB_COMPRESSION ?= 1
|
||||
ZSTD_LIB_DECOMPRESSION ?= 1
|
||||
@@ -54,12 +57,11 @@ VERSION := $(ZSTD_VERSION)
|
||||
# Note: by default, the static library is built single-threaded and dynamic library is built
|
||||
# multi-threaded. It is possible to force multi or single threaded builds by appending
|
||||
# -mt or -nomt to the build target (like lib-mt for multi-threaded, lib-nomt for single-threaded).
|
||||
.PHONY: default
|
||||
default: lib-release
|
||||
|
||||
|
||||
CPPFLAGS_DYNLIB += -DZSTD_MULTITHREAD # dynamic library build defaults to multi-threaded
|
||||
LDFLAGS_DYNLIB += -pthread
|
||||
CPPFLAGS_STATLIB += # static library build defaults to single-threaded
|
||||
CPPFLAGS_STATICLIB += # static library build defaults to single-threaded
|
||||
|
||||
|
||||
ifeq ($(findstring GCC,$(CCVER)),GCC)
|
||||
@@ -91,7 +93,7 @@ all: lib
|
||||
|
||||
|
||||
.PHONY: libzstd.a # must be run every time
|
||||
libzstd.a: CPPFLAGS += $(CPPFLAGS_STATLIB)
|
||||
libzstd.a: CPPFLAGS += $(CPPFLAGS_STATICLIB)
|
||||
|
||||
SET_CACHE_DIRECTORY = \
|
||||
+$(MAKE) --no-print-directory $@ \
|
||||
@@ -109,19 +111,19 @@ libzstd.a:
|
||||
else
|
||||
# BUILD_DIR is defined
|
||||
|
||||
ZSTD_STATLIB_DIR := $(BUILD_DIR)/static
|
||||
ZSTD_STATLIB := $(ZSTD_STATLIB_DIR)/libzstd.a
|
||||
ZSTD_STATLIB_OBJ := $(addprefix $(ZSTD_STATLIB_DIR)/,$(ZSTD_LOCAL_OBJ))
|
||||
$(ZSTD_STATLIB): ARFLAGS = rcs
|
||||
$(ZSTD_STATLIB): | $(ZSTD_STATLIB_DIR)
|
||||
$(ZSTD_STATLIB): $(ZSTD_STATLIB_OBJ)
|
||||
ZSTD_STATICLIB_DIR := $(BUILD_DIR)/static
|
||||
ZSTD_STATICLIB := $(ZSTD_STATICLIB_DIR)/libzstd.a
|
||||
ZSTD_STATICLIB_OBJ := $(addprefix $(ZSTD_STATICLIB_DIR)/,$(ZSTD_LOCAL_OBJ))
|
||||
$(ZSTD_STATICLIB): ARFLAGS = rcs
|
||||
$(ZSTD_STATICLIB): | $(ZSTD_STATICLIB_DIR)
|
||||
$(ZSTD_STATICLIB): $(ZSTD_STATICLIB_OBJ)
|
||||
# Check for multithread flag at target execution time
|
||||
$(if $(filter -DZSTD_MULTITHREAD,$(CPPFLAGS)),\
|
||||
@echo compiling multi-threaded static library $(LIBVER),\
|
||||
@echo compiling single-threaded static library $(LIBVER))
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
libzstd.a: $(ZSTD_STATLIB)
|
||||
libzstd.a: $(ZSTD_STATICLIB)
|
||||
cp -f $< $@
|
||||
|
||||
endif
|
||||
@@ -182,14 +184,14 @@ lib : libzstd.a libzstd
|
||||
# make does not consider implicit pattern rule for .PHONY target
|
||||
|
||||
%-mt : CPPFLAGS_DYNLIB := -DZSTD_MULTITHREAD
|
||||
%-mt : CPPFLAGS_STATLIB := -DZSTD_MULTITHREAD
|
||||
%-mt : CPPFLAGS_STATICLIB := -DZSTD_MULTITHREAD
|
||||
%-mt : LDFLAGS_DYNLIB := -pthread
|
||||
%-mt : %
|
||||
@echo multi-threaded build completed
|
||||
|
||||
%-nomt : CPPFLAGS_DYNLIB :=
|
||||
%-nomt : LDFLAGS_DYNLIB :=
|
||||
%-nomt : CPPFLAGS_STATLIB :=
|
||||
%-nomt : CPPFLAGS_STATICLIB :=
|
||||
%-nomt : %
|
||||
@echo single-threaded build completed
|
||||
|
||||
@@ -200,42 +202,52 @@ lib : libzstd.a libzstd
|
||||
|
||||
# Generate .h dependencies automatically
|
||||
|
||||
DEPFLAGS = -MT $@ -MMD -MP -MF
|
||||
# -MMD: compiler generates dependency information as a side-effect of compilation, without system headers
|
||||
# -MP: adds phony target for each dependency other than main file.
|
||||
DEPFLAGS = -MMD -MP
|
||||
|
||||
$(ZSTD_DYNLIB_DIR)/%.o : %.c $(ZSTD_DYNLIB_DIR)/%.d | $(ZSTD_DYNLIB_DIR)
|
||||
# ensure that ZSTD_DYNLIB_DIR exists prior to generating %.o
|
||||
$(ZSTD_DYNLIB_DIR)/%.o : %.c | $(ZSTD_DYNLIB_DIR)
|
||||
@echo CC $@
|
||||
$(COMPILE.c) $(DEPFLAGS) $(ZSTD_DYNLIB_DIR)/$*.d $(OUTPUT_OPTION) $<
|
||||
$(COMPILE.c) $(DEPFLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(ZSTD_STATLIB_DIR)/%.o : %.c $(ZSTD_STATLIB_DIR)/%.d | $(ZSTD_STATLIB_DIR)
|
||||
$(ZSTD_STATICLIB_DIR)/%.o : %.c | $(ZSTD_STATICLIB_DIR)
|
||||
@echo CC $@
|
||||
$(COMPILE.c) $(DEPFLAGS) $(ZSTD_STATLIB_DIR)/$*.d $(OUTPUT_OPTION) $<
|
||||
$(COMPILE.c) $(DEPFLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(ZSTD_DYNLIB_DIR)/%.o : %.S | $(ZSTD_DYNLIB_DIR)
|
||||
@echo AS $@
|
||||
$(COMPILE.S) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(ZSTD_STATLIB_DIR)/%.o : %.S | $(ZSTD_STATLIB_DIR)
|
||||
$(ZSTD_STATICLIB_DIR)/%.o : %.S | $(ZSTD_STATICLIB_DIR)
|
||||
@echo AS $@
|
||||
$(COMPILE.S) $(OUTPUT_OPTION) $<
|
||||
|
||||
MKDIR ?= mkdir
|
||||
$(BUILD_DIR) $(ZSTD_DYNLIB_DIR) $(ZSTD_STATLIB_DIR):
|
||||
$(MKDIR) -p $@
|
||||
MKDIR ?= mkdir -p
|
||||
$(BUILD_DIR) $(ZSTD_DYNLIB_DIR) $(ZSTD_STATICLIB_DIR):
|
||||
$(MKDIR) $@
|
||||
|
||||
DEPFILES := $(ZSTD_DYNLIB_OBJ:.o=.d) $(ZSTD_STATLIB_OBJ:.o=.d)
|
||||
DEPFILES := $(ZSTD_DYNLIB_OBJ:.o=.d) $(ZSTD_STATICLIB_OBJ:.o=.d)
|
||||
$(DEPFILES):
|
||||
|
||||
include $(wildcard $(DEPFILES))
|
||||
# The leading '-' means: do not fail is include fails (ex: directory does not exist yet)
|
||||
-include $(wildcard $(DEPFILES))
|
||||
|
||||
|
||||
# Special case : building library in single-thread mode _and_ without zstdmt_compress.c
|
||||
ZSTDMT_FILES = compress/zstdmt_compress.c
|
||||
ZSTD_NOMT_FILES = $(filter-out $(ZSTDMT_FILES),$(ZSTD_FILES))
|
||||
# Special case : build library in single-thread mode _and_ without zstdmt_compress.c
|
||||
# Note : we still need threading.c and pool.c for the dictionary builder,
|
||||
# but they will correctly behave single-threaded.
|
||||
ZSTDMT_FILES = zstdmt_compress.c
|
||||
ZSTD_NOMT_FILES = $(filter-out $(ZSTDMT_FILES),$(notdir $(ZSTD_FILES)))
|
||||
libzstd-nomt: CFLAGS += -fPIC -fvisibility=hidden
|
||||
libzstd-nomt: LDFLAGS += -shared
|
||||
libzstd-nomt: $(ZSTD_NOMT_FILES)
|
||||
@echo compiling single-thread dynamic library $(LIBVER)
|
||||
@echo files : $(ZSTD_NOMT_FILES)
|
||||
@if echo "$(ZSTD_NOMT_FILES)" | tr ' ' '\n' | $(GREP) -q zstdmt; then \
|
||||
echo "Error: Found zstdmt in list."; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
+5
-1
@@ -88,7 +88,7 @@ The file structure is designed to make this selection manually achievable for an
|
||||
For example, advanced API for version `v0.4` is exposed in `lib/legacy/zstd_v04.h` .
|
||||
|
||||
- While invoking `make libzstd`, it's possible to define build macros
|
||||
`ZSTD_LIB_COMPRESSION, ZSTD_LIB_DECOMPRESSION`, `ZSTD_LIB_DICTBUILDER`,
|
||||
`ZSTD_LIB_COMPRESSION`, `ZSTD_LIB_DECOMPRESSION`, `ZSTD_LIB_DICTBUILDER`,
|
||||
and `ZSTD_LIB_DEPRECATED` as `0` to forgo compilation of the
|
||||
corresponding features. This will also disable compilation of all
|
||||
dependencies (e.g. `ZSTD_LIB_COMPRESSION=0` will also disable
|
||||
@@ -178,6 +178,10 @@ The file structure is designed to make this selection manually achievable for an
|
||||
`ZSTDERRORLIB_VSIBILITY`, and `ZDICTLIB_VISIBILITY` if unset, for backwards compatibility
|
||||
with the old macro names.
|
||||
|
||||
- The C compiler macro `HUF_DISABLE_FAST_DECODE` disables the newer Huffman fast C
|
||||
and assembly decoding loops. You may want to use this macro if these loops are
|
||||
slower on your platform.
|
||||
|
||||
#### Windows : using MinGW+MSYS to create DLL
|
||||
|
||||
DLL can be created using MinGW+MSYS with the `make libzstd` command.
|
||||
|
||||
+87
-16
@@ -11,6 +11,8 @@
|
||||
#ifndef ZSTD_COMPILER_H
|
||||
#define ZSTD_COMPILER_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "portability_macros.h"
|
||||
|
||||
/*-*******************************************************
|
||||
@@ -130,8 +132,8 @@
|
||||
/* prefetch
|
||||
* can be disabled, by declaring NO_PREFETCH build macro */
|
||||
#if defined(NO_PREFETCH)
|
||||
# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
|
||||
# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
|
||||
# define PREFETCH_L1(ptr) do { (void)(ptr); } while (0) /* disabled */
|
||||
# define PREFETCH_L2(ptr) do { (void)(ptr); } while (0) /* disabled */
|
||||
#else
|
||||
# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && !defined(_M_ARM64EC) /* _mm_prefetch() is not defined outside of x86/x64 */
|
||||
# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
|
||||
@@ -141,24 +143,25 @@
|
||||
# define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
|
||||
# define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)
|
||||
# elif defined(__aarch64__)
|
||||
# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr)))
|
||||
# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr)))
|
||||
# define PREFETCH_L1(ptr) do { __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))); } while (0)
|
||||
# define PREFETCH_L2(ptr) do { __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))); } while (0)
|
||||
# else
|
||||
# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
|
||||
# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
|
||||
# define PREFETCH_L1(ptr) do { (void)(ptr); } while (0) /* disabled */
|
||||
# define PREFETCH_L2(ptr) do { (void)(ptr); } while (0) /* disabled */
|
||||
# endif
|
||||
#endif /* NO_PREFETCH */
|
||||
|
||||
#define CACHELINE_SIZE 64
|
||||
|
||||
#define PREFETCH_AREA(p, s) { \
|
||||
const char* const _ptr = (const char*)(p); \
|
||||
size_t const _size = (size_t)(s); \
|
||||
size_t _pos; \
|
||||
for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \
|
||||
PREFETCH_L2(_ptr + _pos); \
|
||||
} \
|
||||
}
|
||||
#define PREFETCH_AREA(p, s) \
|
||||
do { \
|
||||
const char* const _ptr = (const char*)(p); \
|
||||
size_t const _size = (size_t)(s); \
|
||||
size_t _pos; \
|
||||
for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \
|
||||
PREFETCH_L2(_ptr + _pos); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* vectorization
|
||||
* older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax,
|
||||
@@ -187,9 +190,9 @@
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)))
|
||||
# define ZSTD_UNREACHABLE { assert(0), __builtin_unreachable(); }
|
||||
# define ZSTD_UNREACHABLE do { assert(0), __builtin_unreachable(); } while (0)
|
||||
#else
|
||||
# define ZSTD_UNREACHABLE { assert(0); }
|
||||
# define ZSTD_UNREACHABLE do { assert(0); } while (0)
|
||||
#endif
|
||||
|
||||
/* disable warnings */
|
||||
@@ -302,6 +305,74 @@
|
||||
* Sanitizer
|
||||
*****************************************************************/
|
||||
|
||||
/**
|
||||
* Zstd relies on pointer overflow in its decompressor.
|
||||
* We add this attribute to functions that rely on pointer overflow.
|
||||
*/
|
||||
#ifndef ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
# if __has_attribute(no_sanitize)
|
||||
# if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8
|
||||
/* gcc < 8 only has signed-integer-overlow which triggers on pointer overflow */
|
||||
# define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("signed-integer-overflow")))
|
||||
# else
|
||||
/* older versions of clang [3.7, 5.0) will warn that pointer-overflow is ignored. */
|
||||
# define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("pointer-overflow")))
|
||||
# endif
|
||||
# else
|
||||
# define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Helper function to perform a wrapped pointer difference without trigging
|
||||
* UBSAN.
|
||||
*
|
||||
* @returns lhs - rhs with wrapping
|
||||
*/
|
||||
MEM_STATIC
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
ptrdiff_t ZSTD_wrappedPtrDiff(unsigned char const* lhs, unsigned char const* rhs)
|
||||
{
|
||||
return lhs - rhs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to perform a wrapped pointer add without triggering UBSAN.
|
||||
*
|
||||
* @return ptr + add with wrapping
|
||||
*/
|
||||
MEM_STATIC
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
unsigned char const* ZSTD_wrappedPtrAdd(unsigned char const* ptr, ptrdiff_t add)
|
||||
{
|
||||
return ptr + add;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to perform a wrapped pointer subtraction without triggering
|
||||
* UBSAN.
|
||||
*
|
||||
* @return ptr - sub with wrapping
|
||||
*/
|
||||
MEM_STATIC
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
unsigned char const* ZSTD_wrappedPtrSub(unsigned char const* ptr, ptrdiff_t sub)
|
||||
{
|
||||
return ptr - sub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to add to a pointer that works around C's undefined behavior
|
||||
* of adding 0 to NULL.
|
||||
*
|
||||
* @returns `ptr + add` except it defines `NULL + 0 == NULL`.
|
||||
*/
|
||||
MEM_STATIC
|
||||
unsigned char* ZSTD_maybeNullPtrAdd(unsigned char* ptr, ptrdiff_t add)
|
||||
{
|
||||
return add > 0 ? ptr + add : ptr;
|
||||
}
|
||||
|
||||
/* Issue #3240 reports an ASAN failure on an llvm-mingw build. Out of an
|
||||
* abundance of caution, disable our custom poisoning on mingw. */
|
||||
#ifdef __MINGW32__
|
||||
|
||||
@@ -35,6 +35,7 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
|
||||
U32 f7b = 0;
|
||||
U32 f7c = 0;
|
||||
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
|
||||
#if !defined(__clang__)
|
||||
int reg[4];
|
||||
__cpuid((int*)reg, 0);
|
||||
{
|
||||
@@ -50,6 +51,41 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
|
||||
f7c = (U32)reg[2];
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Clang compiler has a bug (fixed in https://reviews.llvm.org/D101338) in
|
||||
* which the `__cpuid` intrinsic does not save and restore `rbx` as it needs
|
||||
* to due to being a reserved register. So in that case, do the `cpuid`
|
||||
* ourselves. Clang supports inline assembly anyway.
|
||||
*/
|
||||
U32 n;
|
||||
__asm__(
|
||||
"pushq %%rbx\n\t"
|
||||
"cpuid\n\t"
|
||||
"popq %%rbx\n\t"
|
||||
: "=a"(n)
|
||||
: "a"(0)
|
||||
: "rcx", "rdx");
|
||||
if (n >= 1) {
|
||||
U32 f1a;
|
||||
__asm__(
|
||||
"pushq %%rbx\n\t"
|
||||
"cpuid\n\t"
|
||||
"popq %%rbx\n\t"
|
||||
: "=a"(f1a), "=c"(f1c), "=d"(f1d)
|
||||
: "a"(1)
|
||||
:);
|
||||
}
|
||||
if (n >= 7) {
|
||||
__asm__(
|
||||
"pushq %%rbx\n\t"
|
||||
"cpuid\n\t"
|
||||
"movq %%rbx, %%rax\n\t"
|
||||
"popq %%rbx"
|
||||
: "=a"(f7b), "=c"(f7c)
|
||||
: "a"(7), "c"(0)
|
||||
: "rdx");
|
||||
}
|
||||
#endif
|
||||
#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
|
||||
/* The following block like the normal cpuid branch below, but gcc
|
||||
* reserves ebx for use of its pic register so we must specially
|
||||
|
||||
@@ -21,4 +21,10 @@
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#if !defined(ZSTD_LINUX_KERNEL) || (DEBUGLEVEL>=2)
|
||||
/* We only use this when DEBUGLEVEL>=2, but we get -Werror=pedantic errors if a
|
||||
* translation unit is empty. So remove this from Linux kernel builds, but
|
||||
* otherwise just leave it in.
|
||||
*/
|
||||
int g_debuglevel = DEBUGLEVEL;
|
||||
#endif
|
||||
|
||||
+20
-11
@@ -85,18 +85,27 @@ extern int g_debuglevel; /* the variable is only declared,
|
||||
It's useful when enabling very verbose levels
|
||||
on selective conditions (such as position in src) */
|
||||
|
||||
# define RAWLOG(l, ...) { \
|
||||
if (l<=g_debuglevel) { \
|
||||
ZSTD_DEBUG_PRINT(__VA_ARGS__); \
|
||||
} }
|
||||
# define DEBUGLOG(l, ...) { \
|
||||
if (l<=g_debuglevel) { \
|
||||
ZSTD_DEBUG_PRINT(__FILE__ ": " __VA_ARGS__); \
|
||||
ZSTD_DEBUG_PRINT(" \n"); \
|
||||
} }
|
||||
# define RAWLOG(l, ...) \
|
||||
do { \
|
||||
if (l<=g_debuglevel) { \
|
||||
ZSTD_DEBUG_PRINT(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#define LINE_AS_STRING TOSTRING(__LINE__)
|
||||
|
||||
# define DEBUGLOG(l, ...) \
|
||||
do { \
|
||||
if (l<=g_debuglevel) { \
|
||||
ZSTD_DEBUG_PRINT(__FILE__ ":" LINE_AS_STRING ": " __VA_ARGS__); \
|
||||
ZSTD_DEBUG_PRINT(" \n"); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
# define RAWLOG(l, ...) {} /* disabled */
|
||||
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||
# define RAWLOG(l, ...) do { } while (0) /* disabled */
|
||||
# define DEBUGLOG(l, ...) do { } while (0) /* disabled */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+45
-36
@@ -60,8 +60,13 @@ ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
|
||||
ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
|
||||
|
||||
/* check and forward error code */
|
||||
#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
|
||||
#define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
|
||||
#define CHECK_V_F(e, f) \
|
||||
size_t const e = f; \
|
||||
do { \
|
||||
if (ERR_isError(e)) \
|
||||
return e; \
|
||||
} while (0)
|
||||
#define CHECK_F(f) do { CHECK_V_F(_var_err__, f); } while (0)
|
||||
|
||||
|
||||
/*-****************************************
|
||||
@@ -95,10 +100,12 @@ void _force_has_format_string(const char *format, ...) {
|
||||
* We want to force this function invocation to be syntactically correct, but
|
||||
* we don't want to force runtime evaluation of its arguments.
|
||||
*/
|
||||
#define _FORCE_HAS_FORMAT_STRING(...) \
|
||||
if (0) { \
|
||||
_force_has_format_string(__VA_ARGS__); \
|
||||
}
|
||||
#define _FORCE_HAS_FORMAT_STRING(...) \
|
||||
do { \
|
||||
if (0) { \
|
||||
_force_has_format_string(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ERR_QUOTE(str) #str
|
||||
|
||||
@@ -109,48 +116,50 @@ void _force_has_format_string(const char *format, ...) {
|
||||
* 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__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
|
||||
_FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
|
||||
RAWLOG(3, ": " __VA_ARGS__); \
|
||||
RAWLOG(3, "\n"); \
|
||||
return ERROR(err); \
|
||||
}
|
||||
#define RETURN_ERROR_IF(cond, err, ...) \
|
||||
do { \
|
||||
if (cond) { \
|
||||
RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
|
||||
__FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
|
||||
_FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
|
||||
RAWLOG(3, ": " __VA_ARGS__); \
|
||||
RAWLOG(3, "\n"); \
|
||||
return ERROR(err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* 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__, ERR_QUOTE(ERROR(err))); \
|
||||
_FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
|
||||
RAWLOG(3, ": " __VA_ARGS__); \
|
||||
RAWLOG(3, "\n"); \
|
||||
return ERROR(err); \
|
||||
} while(0);
|
||||
#define RETURN_ERROR(err, ...) \
|
||||
do { \
|
||||
RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
|
||||
__FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \
|
||||
_FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
|
||||
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__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
|
||||
_FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
|
||||
RAWLOG(3, ": " __VA_ARGS__); \
|
||||
RAWLOG(3, "\n"); \
|
||||
return err_code; \
|
||||
} \
|
||||
} while(0);
|
||||
#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__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
|
||||
_FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
|
||||
RAWLOG(3, ": " __VA_ARGS__); \
|
||||
RAWLOG(3, "\n"); \
|
||||
return err_code; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
||||
+3
-2
@@ -229,6 +229,7 @@ If there is an error, the function will return an error code, which can be teste
|
||||
|
||||
#endif /* FSE_H */
|
||||
|
||||
|
||||
#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
|
||||
#define FSE_H_FSE_STATIC_LINKING_ONLY
|
||||
|
||||
@@ -464,13 +465,13 @@ MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, un
|
||||
FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
|
||||
const U16* const stateTable = (const U16*)(statePtr->stateTable);
|
||||
U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
|
||||
BIT_addBits(bitC, statePtr->value, nbBitsOut);
|
||||
BIT_addBits(bitC, (size_t)statePtr->value, nbBitsOut);
|
||||
statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
|
||||
}
|
||||
|
||||
MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)
|
||||
{
|
||||
BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
|
||||
BIT_addBits(bitC, (size_t)statePtr->value, statePtr->stateLog);
|
||||
BIT_flushBits(bitC);
|
||||
}
|
||||
|
||||
|
||||
+19
-17
@@ -22,8 +22,7 @@
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "fse.h"
|
||||
#include "error_private.h"
|
||||
#define ZSTD_DEPS_NEED_MALLOC
|
||||
#include "zstd_deps.h"
|
||||
#include "zstd_deps.h" /* ZSTD_memcpy */
|
||||
#include "bits.h" /* ZSTD_highbit32 */
|
||||
|
||||
|
||||
@@ -84,7 +83,7 @@ static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCo
|
||||
symbolNext[s] = 1;
|
||||
} else {
|
||||
if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
|
||||
symbolNext[s] = normalizedCounter[s];
|
||||
symbolNext[s] = (U16)normalizedCounter[s];
|
||||
} } }
|
||||
ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));
|
||||
}
|
||||
@@ -99,8 +98,7 @@ static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCo
|
||||
* all symbols have counts <= 8. We ensure we have 8 bytes at the end of
|
||||
* our buffer to handle the over-write.
|
||||
*/
|
||||
{
|
||||
U64 const add = 0x0101010101010101ull;
|
||||
{ U64 const add = 0x0101010101010101ull;
|
||||
size_t pos = 0;
|
||||
U64 sv = 0;
|
||||
U32 s;
|
||||
@@ -111,9 +109,8 @@ static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCo
|
||||
for (i = 8; i < n; i += 8) {
|
||||
MEM_write64(spread + pos + i, sv);
|
||||
}
|
||||
pos += n;
|
||||
}
|
||||
}
|
||||
pos += (size_t)n;
|
||||
} }
|
||||
/* Now we spread those positions across the table.
|
||||
* The benefit of doing it in two stages is that we avoid the
|
||||
* variable size inner loop, which caused lots of branch misses.
|
||||
@@ -232,12 +229,12 @@ FORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(
|
||||
break;
|
||||
} }
|
||||
|
||||
return op-ostart;
|
||||
assert(op >= ostart);
|
||||
return (size_t)(op-ostart);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
short ncount[FSE_MAX_SYMBOL_VALUE + 1];
|
||||
FSE_DTable dtable[1]; /* Dynamically sized */
|
||||
} FSE_DecompressWksp;
|
||||
|
||||
|
||||
@@ -252,13 +249,18 @@ FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(
|
||||
unsigned tableLog;
|
||||
unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
|
||||
FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace;
|
||||
size_t const dtablePos = sizeof(FSE_DecompressWksp) / sizeof(FSE_DTable);
|
||||
FSE_DTable* const dtable = (FSE_DTable*)workSpace + dtablePos;
|
||||
|
||||
DEBUG_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0);
|
||||
FSE_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0);
|
||||
if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC);
|
||||
|
||||
/* correct offset to dtable depends on this property */
|
||||
FSE_STATIC_ASSERT(sizeof(FSE_DecompressWksp) % sizeof(FSE_DTable) == 0);
|
||||
|
||||
/* normal FSE decoding mode */
|
||||
{
|
||||
size_t const NCountLength = FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);
|
||||
{ size_t const NCountLength =
|
||||
FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);
|
||||
if (FSE_isError(NCountLength)) return NCountLength;
|
||||
if (tableLog > maxLog) return ERROR(tableLog_tooLarge);
|
||||
assert(NCountLength <= cSrcSize);
|
||||
@@ -271,16 +273,16 @@ FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(
|
||||
workSpace = (BYTE*)workSpace + sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);
|
||||
wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);
|
||||
|
||||
CHECK_F( FSE_buildDTable_internal(wksp->dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) );
|
||||
CHECK_F( FSE_buildDTable_internal(dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) );
|
||||
|
||||
{
|
||||
const void* ptr = wksp->dtable;
|
||||
const void* ptr = dtable;
|
||||
const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
|
||||
const U32 fastMode = DTableH->fastMode;
|
||||
|
||||
/* select fast mode (static) */
|
||||
if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 1);
|
||||
return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 0);
|
||||
if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 1);
|
||||
return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)
|
||||
{ ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
|
||||
if (!threadPool) return 1;
|
||||
/* replace existing thread pool */
|
||||
ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool));
|
||||
ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(ZSTD_pthread_t));
|
||||
ZSTD_customFree(ctx->threads, ctx->customMem);
|
||||
ctx->threads = threadPool;
|
||||
/* Initialize additional threads */
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ void POOL_joinJobs(POOL_ctx* ctx);
|
||||
/*! POOL_resize() :
|
||||
* Expands or shrinks pool's number of threads.
|
||||
* This is more efficient than releasing + creating a new context,
|
||||
* since it tries to preserve and re-use existing threads.
|
||||
* since it tries to preserve and reuse existing threads.
|
||||
* `numThreads` must be at least 1.
|
||||
* @return : 0 when resize was successful,
|
||||
* !0 (typically 1) if there is an error.
|
||||
|
||||
+5
-11
@@ -1,24 +1,18 @@
|
||||
/*
|
||||
* xxHash - Fast Hash algorithm
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - xxHash homepage: https://cyan4973.github.io/xxHash/
|
||||
* - xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||
* xxHash - Extremely Fast Hash algorithm
|
||||
* Copyright (c) Yann Collet - Meta Platforms, Inc
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* xxhash.c instantiates functions defined in xxhash.h
|
||||
*/
|
||||
|
||||
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
|
||||
#define XXH_IMPLEMENTATION /* access definitions */
|
||||
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
|
||||
#define XXH_IMPLEMENTATION /* access definitions */
|
||||
|
||||
#include "xxhash.h"
|
||||
|
||||
+2327
-993
File diff suppressed because it is too large
Load Diff
@@ -178,7 +178,7 @@ static void ZSTD_copy8(void* dst, const void* src) {
|
||||
ZSTD_memcpy(dst, src, 8);
|
||||
#endif
|
||||
}
|
||||
#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }
|
||||
#define COPY8(d,s) do { ZSTD_copy8(d,s); d+=8; s+=8; } while (0)
|
||||
|
||||
/* Need to use memmove here since the literal buffer can now be located within
|
||||
the dst buffer. In circumstances where the op "catches up" to where the
|
||||
@@ -198,7 +198,7 @@ static void ZSTD_copy16(void* dst, const void* src) {
|
||||
ZSTD_memcpy(dst, copy16_buf, 16);
|
||||
#endif
|
||||
}
|
||||
#define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; }
|
||||
#define COPY16(d,s) do { ZSTD_copy16(d,s); d+=16; s+=16; } while (0)
|
||||
|
||||
#define WILDCOPY_OVERLENGTH 32
|
||||
#define WILDCOPY_VECLEN 16
|
||||
@@ -227,7 +227,7 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e
|
||||
if (ovtype == ZSTD_overlap_src_before_dst && diff < WILDCOPY_VECLEN) {
|
||||
/* Handle short offset copies. */
|
||||
do {
|
||||
COPY8(op, ip)
|
||||
COPY8(op, ip);
|
||||
} while (op < oend);
|
||||
} else {
|
||||
assert(diff >= WILDCOPY_VECLEN || diff <= -WILDCOPY_VECLEN);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "../common/error_private.h"
|
||||
#define ZSTD_DEPS_NEED_MALLOC
|
||||
#define ZSTD_DEPS_NEED_MATH64
|
||||
#include "../common/zstd_deps.h" /* ZSTD_malloc, ZSTD_free, ZSTD_memcpy, ZSTD_memset */
|
||||
#include "../common/zstd_deps.h" /* ZSTD_memset */
|
||||
#include "../common/bits.h" /* ZSTD_highbit32 */
|
||||
|
||||
|
||||
@@ -225,8 +225,8 @@ size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)
|
||||
size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog
|
||||
+ 4 /* bitCount initialized at 4 */
|
||||
+ 2 /* first two symbols may use one additional bit each */) / 8)
|
||||
+ 1 /* round up to whole nb bytes */
|
||||
+ 2 /* additional two bytes for bitstream flush */;
|
||||
+ 1 /* round up to whole nb bytes */
|
||||
+ 2 /* additional two bytes for bitstream flush */;
|
||||
return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ FSE_writeNCount_generic (void* header, size_t headerBufferSize,
|
||||
/* Init */
|
||||
remaining = tableSize+1; /* +1 for extra accuracy */
|
||||
threshold = tableSize;
|
||||
nbBits = tableLog+1;
|
||||
nbBits = (int)tableLog+1;
|
||||
|
||||
while ((symbol < alphabetSize) && (remaining>1)) { /* stops at 1 */
|
||||
if (previousIs0) {
|
||||
@@ -274,7 +274,7 @@ FSE_writeNCount_generic (void* header, size_t headerBufferSize,
|
||||
}
|
||||
while (symbol >= start+3) {
|
||||
start+=3;
|
||||
bitStream += 3 << bitCount;
|
||||
bitStream += 3U << bitCount;
|
||||
bitCount += 2;
|
||||
}
|
||||
bitStream += (symbol-start) << bitCount;
|
||||
@@ -294,7 +294,7 @@ FSE_writeNCount_generic (void* header, size_t headerBufferSize,
|
||||
count++; /* +1 for extra accuracy */
|
||||
if (count>=threshold)
|
||||
count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */
|
||||
bitStream += count << bitCount;
|
||||
bitStream += (U32)count << bitCount;
|
||||
bitCount += nbBits;
|
||||
bitCount -= (count<max);
|
||||
previousIs0 = (count==1);
|
||||
@@ -322,7 +322,8 @@ FSE_writeNCount_generic (void* header, size_t headerBufferSize,
|
||||
out[1] = (BYTE)(bitStream>>8);
|
||||
out+= (bitCount+7) /8;
|
||||
|
||||
return (out-ostart);
|
||||
assert(out >= ostart);
|
||||
return (size_t)(out-ostart);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1062,12 +1062,12 @@ HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,
|
||||
const BYTE* ip = (const BYTE*) src;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
BYTE* op = ostart;
|
||||
HUF_CStream_t bitC;
|
||||
|
||||
/* init */
|
||||
if (dstSize < 8) return 0; /* not enough space to compress */
|
||||
{ size_t const initErr = HUF_initCStream(&bitC, op, (size_t)(oend-op));
|
||||
{ BYTE* op = ostart;
|
||||
size_t const initErr = HUF_initCStream(&bitC, op, (size_t)(oend-op));
|
||||
if (HUF_isError(initErr)) return 0; }
|
||||
|
||||
if (dstSize < HUF_tightCompressBound(srcSize, (size_t)tableLog) || tableLog > 11)
|
||||
@@ -1288,7 +1288,7 @@ unsigned HUF_optimalTableLog(
|
||||
|
||||
{ BYTE* dst = (BYTE*)workSpace + sizeof(HUF_WriteCTableWksp);
|
||||
size_t dstSize = wkspSize - sizeof(HUF_WriteCTableWksp);
|
||||
size_t maxBits, hSize, newSize;
|
||||
size_t hSize, newSize;
|
||||
const unsigned symbolCardinality = HUF_cardinality(count, maxSymbolValue);
|
||||
const unsigned minTableLog = HUF_minTableLog(symbolCardinality);
|
||||
size_t optSize = ((size_t) ~0) - 1;
|
||||
@@ -1299,12 +1299,14 @@ unsigned HUF_optimalTableLog(
|
||||
/* Search until size increases */
|
||||
for (optLogGuess = minTableLog; optLogGuess <= maxTableLog; optLogGuess++) {
|
||||
DEBUGLOG(7, "checking for huffLog=%u", optLogGuess);
|
||||
maxBits = HUF_buildCTable_wksp(table, count, maxSymbolValue, optLogGuess, workSpace, wkspSize);
|
||||
if (ERR_isError(maxBits)) continue;
|
||||
|
||||
if (maxBits < optLogGuess && optLogGuess > minTableLog) break;
|
||||
{ size_t maxBits = HUF_buildCTable_wksp(table, count, maxSymbolValue, optLogGuess, workSpace, wkspSize);
|
||||
if (ERR_isError(maxBits)) continue;
|
||||
|
||||
hSize = HUF_writeCTable_wksp(dst, dstSize, table, maxSymbolValue, (U32)maxBits, workSpace, wkspSize);
|
||||
if (maxBits < optLogGuess && optLogGuess > minTableLog) break;
|
||||
|
||||
hSize = HUF_writeCTable_wksp(dst, dstSize, table, maxSymbolValue, (U32)maxBits, workSpace, wkspSize);
|
||||
}
|
||||
|
||||
if (ERR_isError(hSize)) continue;
|
||||
|
||||
@@ -1447,7 +1449,7 @@ size_t HUF_compress1X_repeat (void* dst, size_t dstSize,
|
||||
/* HUF_compress4X_repeat():
|
||||
* compress input using 4 streams.
|
||||
* consider skipping quickly
|
||||
* re-use an existing huffman compression table */
|
||||
* reuse an existing huffman compression table */
|
||||
size_t HUF_compress4X_repeat (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog,
|
||||
|
||||
+157
-104
@@ -178,6 +178,7 @@ static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
|
||||
|
||||
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
||||
{
|
||||
DEBUGLOG(3, "ZSTD_freeCCtx (address: %p)", (void*)cctx);
|
||||
if (cctx==NULL) return 0; /* support free on NULL */
|
||||
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
|
||||
"not compatible with static CCtx");
|
||||
@@ -649,10 +650,11 @@ static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define BOUNDCHECK(cParam, val) { \
|
||||
RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
|
||||
parameter_outOfBound, "Param out of bounds"); \
|
||||
}
|
||||
#define BOUNDCHECK(cParam, val) \
|
||||
do { \
|
||||
RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
|
||||
parameter_outOfBound, "Param out of bounds"); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
|
||||
@@ -868,7 +870,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
#else
|
||||
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
|
||||
CCtxParams->nbWorkers = value;
|
||||
return CCtxParams->nbWorkers;
|
||||
return (size_t)(CCtxParams->nbWorkers);
|
||||
#endif
|
||||
|
||||
case ZSTD_c_jobSize :
|
||||
@@ -892,7 +894,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
#else
|
||||
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
|
||||
CCtxParams->overlapLog = value;
|
||||
return CCtxParams->overlapLog;
|
||||
return (size_t)CCtxParams->overlapLog;
|
||||
#endif
|
||||
|
||||
case ZSTD_c_rsyncable :
|
||||
@@ -902,7 +904,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
#else
|
||||
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
|
||||
CCtxParams->rsyncable = value;
|
||||
return CCtxParams->rsyncable;
|
||||
return (size_t)CCtxParams->rsyncable;
|
||||
#endif
|
||||
|
||||
case ZSTD_c_enableDedicatedDictSearch :
|
||||
@@ -939,8 +941,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
return CCtxParams->ldmParams.hashRateLog;
|
||||
|
||||
case ZSTD_c_targetCBlockSize :
|
||||
if (value!=0) /* 0 ==> default */
|
||||
if (value!=0) { /* 0 ==> default */
|
||||
value = MAX(value, ZSTD_TARGETCBLOCKSIZE_MIN);
|
||||
BOUNDCHECK(ZSTD_c_targetCBlockSize, value);
|
||||
}
|
||||
CCtxParams->targetCBlockSize = (U32)value;
|
||||
return CCtxParams->targetCBlockSize;
|
||||
|
||||
@@ -968,7 +972,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
case ZSTD_c_validateSequences:
|
||||
BOUNDCHECK(ZSTD_c_validateSequences, value);
|
||||
CCtxParams->validateSequences = value;
|
||||
return CCtxParams->validateSequences;
|
||||
return (size_t)CCtxParams->validateSequences;
|
||||
|
||||
case ZSTD_c_useBlockSplitter:
|
||||
BOUNDCHECK(ZSTD_c_useBlockSplitter, value);
|
||||
@@ -983,7 +987,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
case ZSTD_c_deterministicRefPrefix:
|
||||
BOUNDCHECK(ZSTD_c_deterministicRefPrefix, value);
|
||||
CCtxParams->deterministicRefPrefix = !!value;
|
||||
return CCtxParams->deterministicRefPrefix;
|
||||
return (size_t)CCtxParams->deterministicRefPrefix;
|
||||
|
||||
case ZSTD_c_prefetchCDictTables:
|
||||
BOUNDCHECK(ZSTD_c_prefetchCDictTables, value);
|
||||
@@ -993,7 +997,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
case ZSTD_c_enableSeqProducerFallback:
|
||||
BOUNDCHECK(ZSTD_c_enableSeqProducerFallback, value);
|
||||
CCtxParams->enableMatchFinderFallback = value;
|
||||
return CCtxParams->enableMatchFinderFallback;
|
||||
return (size_t)CCtxParams->enableMatchFinderFallback;
|
||||
|
||||
case ZSTD_c_maxBlockSize:
|
||||
if (value!=0) /* 0 ==> default */
|
||||
@@ -1363,7 +1367,6 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
|
||||
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
||||
"Reset parameters is only possible during init stage.");
|
||||
ZSTD_clearAllDicts(cctx);
|
||||
ZSTD_memset(&cctx->externalMatchCtx, 0, sizeof(cctx->externalMatchCtx));
|
||||
return ZSTD_CCtxParams_reset(&cctx->requestedParams);
|
||||
}
|
||||
return 0;
|
||||
@@ -1391,11 +1394,12 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
|
||||
static ZSTD_compressionParameters
|
||||
ZSTD_clampCParams(ZSTD_compressionParameters cParams)
|
||||
{
|
||||
# define CLAMP_TYPE(cParam, val, type) { \
|
||||
ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \
|
||||
if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
|
||||
else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
|
||||
}
|
||||
# define CLAMP_TYPE(cParam, val, type) \
|
||||
do { \
|
||||
ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \
|
||||
if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
|
||||
else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
|
||||
} while (0)
|
||||
# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
|
||||
CLAMP(ZSTD_c_windowLog, cParams.windowLog);
|
||||
CLAMP(ZSTD_c_chainLog, cParams.chainLog);
|
||||
@@ -1659,8 +1663,8 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
|
||||
+ ZSTD_cwksp_aligned_alloc_size((MaxLL+1) * sizeof(U32))
|
||||
+ ZSTD_cwksp_aligned_alloc_size((MaxOff+1) * sizeof(U32))
|
||||
+ ZSTD_cwksp_aligned_alloc_size((1<<Litbits) * sizeof(U32))
|
||||
+ ZSTD_cwksp_aligned_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t))
|
||||
+ ZSTD_cwksp_aligned_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
|
||||
+ ZSTD_cwksp_aligned_alloc_size(ZSTD_OPT_SIZE * sizeof(ZSTD_match_t))
|
||||
+ ZSTD_cwksp_aligned_alloc_size(ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t));
|
||||
size_t const lazyAdditionalSpace = ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)
|
||||
? ZSTD_cwksp_aligned_alloc_size(hSize)
|
||||
: 0;
|
||||
@@ -1749,7 +1753,7 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
||||
* be needed. However, we still allocate two 0-sized buffers, which can
|
||||
* take space under ASAN. */
|
||||
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
&cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, params->useSequenceProducer, params->maxBlockSize);
|
||||
&cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);
|
||||
}
|
||||
|
||||
size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
|
||||
@@ -1810,7 +1814,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
||||
|
||||
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
&cParams, ¶ms->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,
|
||||
ZSTD_CONTENTSIZE_UNKNOWN, params->useSequenceProducer, params->maxBlockSize);
|
||||
ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2043,8 +2047,8 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
||||
ms->opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned));
|
||||
ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned));
|
||||
ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned));
|
||||
ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t));
|
||||
ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
|
||||
ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_match_t));
|
||||
ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t));
|
||||
}
|
||||
|
||||
ms->cParams = *cParams;
|
||||
@@ -2116,7 +2120,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
|
||||
{ size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize));
|
||||
size_t const blockSize = MIN(params->maxBlockSize, windowSize);
|
||||
size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, params->useSequenceProducer);
|
||||
size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, ZSTD_hasExtSeqProd(params));
|
||||
size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered)
|
||||
? ZSTD_compressBound(blockSize) + 1
|
||||
: 0;
|
||||
@@ -2133,8 +2137,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
size_t const neededSpace =
|
||||
ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
¶ms->cParams, ¶ms->ldmParams, zc->staticSize != 0, params->useRowMatchFinder,
|
||||
buffInSize, buffOutSize, pledgedSrcSize, params->useSequenceProducer, params->maxBlockSize);
|
||||
int resizeWorkspace;
|
||||
buffInSize, buffOutSize, pledgedSrcSize, ZSTD_hasExtSeqProd(params), params->maxBlockSize);
|
||||
|
||||
FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!");
|
||||
|
||||
@@ -2143,7 +2146,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
{ /* Check if workspace is large enough, alloc a new one if needed */
|
||||
int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
|
||||
int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
|
||||
resizeWorkspace = workspaceTooSmall || workspaceWasteful;
|
||||
int resizeWorkspace = workspaceTooSmall || workspaceWasteful;
|
||||
DEBUGLOG(4, "Need %zu B workspace", neededSpace);
|
||||
DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
|
||||
|
||||
@@ -2218,10 +2221,10 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
}
|
||||
|
||||
/* reserve space for block-level external sequences */
|
||||
if (params->useSequenceProducer) {
|
||||
if (ZSTD_hasExtSeqProd(params)) {
|
||||
size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);
|
||||
zc->externalMatchCtx.seqBufferCapacity = maxNbExternalSeq;
|
||||
zc->externalMatchCtx.seqBuffer =
|
||||
zc->extSeqBufCapacity = maxNbExternalSeq;
|
||||
zc->extSeqBuf =
|
||||
(ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence));
|
||||
}
|
||||
|
||||
@@ -2606,7 +2609,7 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
|
||||
assert(size < (1U<<31)); /* can be casted to int */
|
||||
|
||||
#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
|
||||
/* To validate that the table re-use logic is sound, and that we don't
|
||||
/* To validate that the table reuse logic is sound, and that we don't
|
||||
* access table space that we haven't cleaned, we re-"poison" the table
|
||||
* space every time we mark it dirty.
|
||||
*
|
||||
@@ -3245,7 +3248,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
/* External matchfinder + LDM is technically possible, just not implemented yet.
|
||||
* We need to revisit soon and implement it. */
|
||||
RETURN_ERROR_IF(
|
||||
zc->appliedParams.useSequenceProducer,
|
||||
ZSTD_hasExtSeqProd(&zc->appliedParams),
|
||||
parameter_combination_unsupported,
|
||||
"Long-distance matching with external sequence producer enabled is not currently supported."
|
||||
);
|
||||
@@ -3264,7 +3267,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
/* External matchfinder + LDM is technically possible, just not implemented yet.
|
||||
* We need to revisit soon and implement it. */
|
||||
RETURN_ERROR_IF(
|
||||
zc->appliedParams.useSequenceProducer,
|
||||
ZSTD_hasExtSeqProd(&zc->appliedParams),
|
||||
parameter_combination_unsupported,
|
||||
"Long-distance matching with external sequence producer enabled is not currently supported."
|
||||
);
|
||||
@@ -3283,18 +3286,18 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
zc->appliedParams.useRowMatchFinder,
|
||||
src, srcSize);
|
||||
assert(ldmSeqStore.pos == ldmSeqStore.size);
|
||||
} else if (zc->appliedParams.useSequenceProducer) {
|
||||
} else if (ZSTD_hasExtSeqProd(&zc->appliedParams)) {
|
||||
assert(
|
||||
zc->externalMatchCtx.seqBufferCapacity >= ZSTD_sequenceBound(srcSize)
|
||||
zc->extSeqBufCapacity >= ZSTD_sequenceBound(srcSize)
|
||||
);
|
||||
assert(zc->externalMatchCtx.mFinder != NULL);
|
||||
assert(zc->appliedParams.extSeqProdFunc != NULL);
|
||||
|
||||
{ U32 const windowSize = (U32)1 << zc->appliedParams.cParams.windowLog;
|
||||
|
||||
size_t const nbExternalSeqs = (zc->externalMatchCtx.mFinder)(
|
||||
zc->externalMatchCtx.mState,
|
||||
zc->externalMatchCtx.seqBuffer,
|
||||
zc->externalMatchCtx.seqBufferCapacity,
|
||||
size_t const nbExternalSeqs = (zc->appliedParams.extSeqProdFunc)(
|
||||
zc->appliedParams.extSeqProdState,
|
||||
zc->extSeqBuf,
|
||||
zc->extSeqBufCapacity,
|
||||
src, srcSize,
|
||||
NULL, 0, /* dict and dictSize, currently not supported */
|
||||
zc->appliedParams.compressionLevel,
|
||||
@@ -3302,21 +3305,21 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
);
|
||||
|
||||
size_t const nbPostProcessedSeqs = ZSTD_postProcessSequenceProducerResult(
|
||||
zc->externalMatchCtx.seqBuffer,
|
||||
zc->extSeqBuf,
|
||||
nbExternalSeqs,
|
||||
zc->externalMatchCtx.seqBufferCapacity,
|
||||
zc->extSeqBufCapacity,
|
||||
srcSize
|
||||
);
|
||||
|
||||
/* Return early if there is no error, since we don't need to worry about last literals */
|
||||
if (!ZSTD_isError(nbPostProcessedSeqs)) {
|
||||
ZSTD_sequencePosition seqPos = {0,0,0};
|
||||
size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->externalMatchCtx.seqBuffer, nbPostProcessedSeqs);
|
||||
size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->extSeqBuf, nbPostProcessedSeqs);
|
||||
RETURN_ERROR_IF(seqLenSum > srcSize, externalSequences_invalid, "External sequences imply too large a block!");
|
||||
FORWARD_IF_ERROR(
|
||||
ZSTD_copySequencesToSeqStoreExplicitBlockDelim(
|
||||
zc, &seqPos,
|
||||
zc->externalMatchCtx.seqBuffer, nbPostProcessedSeqs,
|
||||
zc->extSeqBuf, nbPostProcessedSeqs,
|
||||
src, srcSize,
|
||||
zc->appliedParams.searchForExternalRepcodes
|
||||
),
|
||||
@@ -3360,29 +3363,38 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
return ZSTDbss_compress;
|
||||
}
|
||||
|
||||
static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
|
||||
static size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const seqStore_t* seqStore, const U32 prevRepcodes[ZSTD_REP_NUM])
|
||||
{
|
||||
const seqStore_t* seqStore = ZSTD_getSeqStore(zc);
|
||||
const seqDef* seqStoreSeqs = seqStore->sequencesStart;
|
||||
size_t seqStoreSeqSize = seqStore->sequences - seqStoreSeqs;
|
||||
size_t seqStoreLiteralsSize = (size_t)(seqStore->lit - seqStore->litStart);
|
||||
size_t literalsRead = 0;
|
||||
size_t lastLLSize;
|
||||
const seqDef* inSeqs = seqStore->sequencesStart;
|
||||
const size_t nbInSequences = seqStore->sequences - inSeqs;
|
||||
const size_t nbInLiterals = (size_t)(seqStore->lit - seqStore->litStart);
|
||||
|
||||
ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex];
|
||||
ZSTD_Sequence* outSeqs = seqCollector->seqIndex == 0 ? seqCollector->seqStart : seqCollector->seqStart + seqCollector->seqIndex;
|
||||
const size_t nbOutSequences = nbInSequences + 1;
|
||||
size_t nbOutLiterals = 0;
|
||||
repcodes_t repcodes;
|
||||
size_t i;
|
||||
repcodes_t updatedRepcodes;
|
||||
|
||||
assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences);
|
||||
/* Ensure we have enough space for last literals "sequence" */
|
||||
assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1);
|
||||
ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
|
||||
for (i = 0; i < seqStoreSeqSize; ++i) {
|
||||
U32 rawOffset = seqStoreSeqs[i].offBase - ZSTD_REP_NUM;
|
||||
outSeqs[i].litLength = seqStoreSeqs[i].litLength;
|
||||
outSeqs[i].matchLength = seqStoreSeqs[i].mlBase + MINMATCH;
|
||||
/* Bounds check that we have enough space for every input sequence
|
||||
* and the block delimiter
|
||||
*/
|
||||
assert(seqCollector->seqIndex <= seqCollector->maxSequences);
|
||||
RETURN_ERROR_IF(
|
||||
nbOutSequences > (size_t)(seqCollector->maxSequences - seqCollector->seqIndex),
|
||||
dstSize_tooSmall,
|
||||
"Not enough space to copy sequences");
|
||||
|
||||
ZSTD_memcpy(&repcodes, prevRepcodes, sizeof(repcodes));
|
||||
for (i = 0; i < nbInSequences; ++i) {
|
||||
U32 rawOffset;
|
||||
outSeqs[i].litLength = inSeqs[i].litLength;
|
||||
outSeqs[i].matchLength = inSeqs[i].mlBase + MINMATCH;
|
||||
outSeqs[i].rep = 0;
|
||||
|
||||
/* Handle the possible single length >= 64K
|
||||
* There can only be one because we add MINMATCH to every match length,
|
||||
* and blocks are at most 128K.
|
||||
*/
|
||||
if (i == seqStore->longLengthPos) {
|
||||
if (seqStore->longLengthType == ZSTD_llt_literalLength) {
|
||||
outSeqs[i].litLength += 0x10000;
|
||||
@@ -3391,41 +3403,55 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
|
||||
}
|
||||
}
|
||||
|
||||
if (seqStoreSeqs[i].offBase <= ZSTD_REP_NUM) {
|
||||
/* Derive the correct offset corresponding to a repcode */
|
||||
outSeqs[i].rep = seqStoreSeqs[i].offBase;
|
||||
/* Determine the raw offset given the offBase, which may be a repcode. */
|
||||
if (OFFBASE_IS_REPCODE(inSeqs[i].offBase)) {
|
||||
const U32 repcode = OFFBASE_TO_REPCODE(inSeqs[i].offBase);
|
||||
assert(repcode > 0);
|
||||
outSeqs[i].rep = repcode;
|
||||
if (outSeqs[i].litLength != 0) {
|
||||
rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1];
|
||||
rawOffset = repcodes.rep[repcode - 1];
|
||||
} else {
|
||||
if (outSeqs[i].rep == 3) {
|
||||
rawOffset = updatedRepcodes.rep[0] - 1;
|
||||
if (repcode == 3) {
|
||||
assert(repcodes.rep[0] > 1);
|
||||
rawOffset = repcodes.rep[0] - 1;
|
||||
} else {
|
||||
rawOffset = updatedRepcodes.rep[outSeqs[i].rep];
|
||||
rawOffset = repcodes.rep[repcode];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rawOffset = OFFBASE_TO_OFFSET(inSeqs[i].offBase);
|
||||
}
|
||||
outSeqs[i].offset = rawOffset;
|
||||
/* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode
|
||||
so we provide seqStoreSeqs[i].offset - 1 */
|
||||
ZSTD_updateRep(updatedRepcodes.rep,
|
||||
seqStoreSeqs[i].offBase,
|
||||
seqStoreSeqs[i].litLength == 0);
|
||||
literalsRead += outSeqs[i].litLength;
|
||||
|
||||
/* Update repcode history for the sequence */
|
||||
ZSTD_updateRep(repcodes.rep,
|
||||
inSeqs[i].offBase,
|
||||
inSeqs[i].litLength == 0);
|
||||
|
||||
nbOutLiterals += outSeqs[i].litLength;
|
||||
}
|
||||
/* Insert last literals (if any exist) in the block as a sequence with ml == off == 0.
|
||||
* If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker
|
||||
* for the block boundary, according to the API.
|
||||
*/
|
||||
assert(seqStoreLiteralsSize >= literalsRead);
|
||||
lastLLSize = seqStoreLiteralsSize - literalsRead;
|
||||
outSeqs[i].litLength = (U32)lastLLSize;
|
||||
outSeqs[i].matchLength = outSeqs[i].offset = outSeqs[i].rep = 0;
|
||||
seqStoreSeqSize++;
|
||||
zc->seqCollector.seqIndex += seqStoreSeqSize;
|
||||
assert(nbInLiterals >= nbOutLiterals);
|
||||
{
|
||||
const size_t lastLLSize = nbInLiterals - nbOutLiterals;
|
||||
outSeqs[nbInSequences].litLength = (U32)lastLLSize;
|
||||
outSeqs[nbInSequences].matchLength = 0;
|
||||
outSeqs[nbInSequences].offset = 0;
|
||||
assert(nbOutSequences == nbInSequences + 1);
|
||||
}
|
||||
seqCollector->seqIndex += nbOutSequences;
|
||||
assert(seqCollector->seqIndex <= seqCollector->maxSequences);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTD_sequenceBound(size_t srcSize) {
|
||||
return (srcSize / ZSTD_MINMATCH_MIN) + 1;
|
||||
const size_t maxNbSeq = (srcSize / ZSTD_MINMATCH_MIN) + 1;
|
||||
const size_t maxNbDelims = (srcSize / ZSTD_BLOCKSIZE_MAX_MIN) + 1;
|
||||
return maxNbSeq + maxNbDelims;
|
||||
}
|
||||
|
||||
size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
||||
@@ -3434,6 +3460,16 @@ size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
||||
const size_t dstCapacity = ZSTD_compressBound(srcSize);
|
||||
void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);
|
||||
SeqCollector seqCollector;
|
||||
{
|
||||
int targetCBlockSize;
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_targetCBlockSize, &targetCBlockSize), "");
|
||||
RETURN_ERROR_IF(targetCBlockSize != 0, parameter_unsupported, "targetCBlockSize != 0");
|
||||
}
|
||||
{
|
||||
int nbWorkers;
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_nbWorkers, &nbWorkers), "");
|
||||
RETURN_ERROR_IF(nbWorkers != 0, parameter_unsupported, "nbWorkers != 0");
|
||||
}
|
||||
|
||||
RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
|
||||
|
||||
@@ -3443,8 +3479,12 @@ size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
||||
seqCollector.maxSequences = outSeqsSize;
|
||||
zc->seqCollector = seqCollector;
|
||||
|
||||
ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
|
||||
ZSTD_customFree(dst, ZSTD_defaultCMem);
|
||||
{
|
||||
const size_t ret = ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
|
||||
ZSTD_customFree(dst, ZSTD_defaultCMem);
|
||||
FORWARD_IF_ERROR(ret, "ZSTD_compress2 failed");
|
||||
}
|
||||
assert(zc->seqCollector.seqIndex <= ZSTD_sequenceBound(srcSize));
|
||||
return zc->seqCollector.seqIndex;
|
||||
}
|
||||
|
||||
@@ -4037,8 +4077,9 @@ ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc,
|
||||
cSeqsSize = 1;
|
||||
}
|
||||
|
||||
/* Sequence collection not supported when block splitting */
|
||||
if (zc->seqCollector.collectSequences) {
|
||||
ZSTD_copyBlockSequences(zc);
|
||||
FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, seqStore, dRepOriginal.rep), "copyBlockSequences failed");
|
||||
ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
|
||||
return 0;
|
||||
}
|
||||
@@ -4260,6 +4301,7 @@ ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
|
||||
if (bss == ZSTDbss_noCompress) {
|
||||
if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
|
||||
zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
|
||||
RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, "Uncompressible block");
|
||||
cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);
|
||||
FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
|
||||
DEBUGLOG(4, "ZSTD_compressBlock_splitBlock: Nocompress block");
|
||||
@@ -4292,11 +4334,15 @@ ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
||||
|
||||
{ const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
|
||||
FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
|
||||
if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; }
|
||||
if (bss == ZSTDbss_noCompress) {
|
||||
RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, "Uncompressible block");
|
||||
cSize = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (zc->seqCollector.collectSequences) {
|
||||
ZSTD_copyBlockSequences(zc);
|
||||
FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, ZSTD_getSeqStore(zc), zc->blockState.prevCBlock->rep), "copyBlockSequences failed");
|
||||
ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
|
||||
return 0;
|
||||
}
|
||||
@@ -5174,14 +5220,13 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* op = ostart;
|
||||
size_t fhSize = 0;
|
||||
|
||||
DEBUGLOG(4, "ZSTD_writeEpilogue");
|
||||
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);
|
||||
size_t fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);
|
||||
FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
|
||||
dstCapacity -= fhSize;
|
||||
op += fhSize;
|
||||
@@ -5523,7 +5568,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced2(
|
||||
cctxParams.useRowMatchFinder, cctxParams.enableDedicatedDictSearch,
|
||||
customMem);
|
||||
|
||||
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
||||
if (!cdict || ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
||||
dict, dictSize,
|
||||
dictLoadMethod, dictContentType,
|
||||
cctxParams) )) {
|
||||
@@ -6206,7 +6251,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
/* If external matchfinder is enabled, make sure to fail before checking job size (for consistency) */
|
||||
RETURN_ERROR_IF(
|
||||
params.useSequenceProducer == 1 && params.nbWorkers >= 1,
|
||||
ZSTD_hasExtSeqProd(¶ms) && params.nbWorkers >= 1,
|
||||
parameter_combination_unsupported,
|
||||
"External sequence producer isn't supported with nbWorkers >= 1"
|
||||
);
|
||||
@@ -6498,7 +6543,7 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
|
||||
if (cctx->appliedParams.validateSequences) {
|
||||
seqPos->posInSrc += litLength + matchLength;
|
||||
FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,
|
||||
cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useSequenceProducer),
|
||||
cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)),
|
||||
"Sequence validation failed");
|
||||
}
|
||||
RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid,
|
||||
@@ -6636,7 +6681,7 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition*
|
||||
if (cctx->appliedParams.validateSequences) {
|
||||
seqPos->posInSrc += litLength + matchLength;
|
||||
FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,
|
||||
cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useSequenceProducer),
|
||||
cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)),
|
||||
"Sequence validation failed");
|
||||
}
|
||||
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength);
|
||||
@@ -7082,19 +7127,27 @@ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeH
|
||||
}
|
||||
|
||||
void ZSTD_registerSequenceProducer(
|
||||
ZSTD_CCtx* zc, void* mState,
|
||||
ZSTD_sequenceProducer_F* mFinder
|
||||
ZSTD_CCtx* zc,
|
||||
void* extSeqProdState,
|
||||
ZSTD_sequenceProducer_F extSeqProdFunc
|
||||
) {
|
||||
if (mFinder != NULL) {
|
||||
ZSTD_externalMatchCtx emctx;
|
||||
emctx.mState = mState;
|
||||
emctx.mFinder = mFinder;
|
||||
emctx.seqBuffer = NULL;
|
||||
emctx.seqBufferCapacity = 0;
|
||||
zc->externalMatchCtx = emctx;
|
||||
zc->requestedParams.useSequenceProducer = 1;
|
||||
assert(zc != NULL);
|
||||
ZSTD_CCtxParams_registerSequenceProducer(
|
||||
&zc->requestedParams, extSeqProdState, extSeqProdFunc
|
||||
);
|
||||
}
|
||||
|
||||
void ZSTD_CCtxParams_registerSequenceProducer(
|
||||
ZSTD_CCtx_params* params,
|
||||
void* extSeqProdState,
|
||||
ZSTD_sequenceProducer_F extSeqProdFunc
|
||||
) {
|
||||
assert(params != NULL);
|
||||
if (extSeqProdFunc != NULL) {
|
||||
params->extSeqProdFunc = extSeqProdFunc;
|
||||
params->extSeqProdState = extSeqProdState;
|
||||
} else {
|
||||
ZSTD_memset(&zc->externalMatchCtx, 0, sizeof(zc->externalMatchCtx));
|
||||
zc->requestedParams.useSequenceProducer = 0;
|
||||
params->extSeqProdFunc = NULL;
|
||||
params->extSeqProdState = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ extern "C" {
|
||||
It's not a big deal though : candidate will just be sorted again.
|
||||
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 mishandled after table re-use with a different strategy.
|
||||
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table reuse with a different strategy.
|
||||
This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
|
||||
|
||||
|
||||
@@ -159,23 +159,24 @@ typedef struct {
|
||||
UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
|
||||
|
||||
typedef struct {
|
||||
int price;
|
||||
U32 off;
|
||||
U32 mlen;
|
||||
U32 litlen;
|
||||
U32 rep[ZSTD_REP_NUM];
|
||||
int price; /* price from beginning of segment to this position */
|
||||
U32 off; /* offset of previous match */
|
||||
U32 mlen; /* length of previous match */
|
||||
U32 litlen; /* nb of literals since previous match */
|
||||
U32 rep[ZSTD_REP_NUM]; /* offset history after previous match */
|
||||
} ZSTD_optimal_t;
|
||||
|
||||
typedef enum { zop_dynamic=0, zop_predef } ZSTD_OptPrice_e;
|
||||
|
||||
#define ZSTD_OPT_SIZE (ZSTD_OPT_NUM+3)
|
||||
typedef struct {
|
||||
/* All tables are allocated inside cctx->workspace by ZSTD_resetCCtx_internal() */
|
||||
unsigned* litFreq; /* table of literals statistics, of size 256 */
|
||||
unsigned* litLengthFreq; /* table of litLength statistics, of size (MaxLL+1) */
|
||||
unsigned* matchLengthFreq; /* table of matchLength statistics, of size (MaxML+1) */
|
||||
unsigned* offCodeFreq; /* table of offCode statistics, of size (MaxOff+1) */
|
||||
ZSTD_match_t* matchTable; /* list of found matches, of size ZSTD_OPT_NUM+1 */
|
||||
ZSTD_optimal_t* priceTable; /* All positions tracked by optimal parser, of size ZSTD_OPT_NUM+1 */
|
||||
ZSTD_match_t* matchTable; /* list of found matches, of size ZSTD_OPT_SIZE */
|
||||
ZSTD_optimal_t* priceTable; /* All positions tracked by optimal parser, of size ZSTD_OPT_SIZE */
|
||||
|
||||
U32 litSum; /* nb of literals */
|
||||
U32 litLengthSum; /* nb of litLength codes */
|
||||
@@ -228,7 +229,7 @@ struct ZSTD_matchState_t {
|
||||
U32 rowHashLog; /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/
|
||||
BYTE* tagTable; /* For row-based matchFinder: A row-based table containing the hashes and head index. */
|
||||
U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */
|
||||
U64 hashSalt; /* For row-based matchFinder: salts the hash for re-use of tag table */
|
||||
U64 hashSalt; /* For row-based matchFinder: salts the hash for reuse of tag table */
|
||||
U32 hashSaltEntropy; /* For row-based matchFinder: collects entropy for salt generation */
|
||||
|
||||
U32* hashTable;
|
||||
@@ -360,10 +361,11 @@ struct ZSTD_CCtx_params_s {
|
||||
* if the external matchfinder returns an error code. */
|
||||
int enableMatchFinderFallback;
|
||||
|
||||
/* Indicates whether an external matchfinder has been referenced.
|
||||
* Users can't set this externally.
|
||||
* It is set internally in ZSTD_registerSequenceProducer(). */
|
||||
int useSequenceProducer;
|
||||
/* Parameters for the external sequence producer API.
|
||||
* Users set these parameters through ZSTD_registerSequenceProducer().
|
||||
* It is not possible to set these parameters individually through the public API. */
|
||||
void* extSeqProdState;
|
||||
ZSTD_sequenceProducer_F extSeqProdFunc;
|
||||
|
||||
/* Adjust the max block size*/
|
||||
size_t maxBlockSize;
|
||||
@@ -401,14 +403,6 @@ typedef struct {
|
||||
ZSTD_entropyCTablesMetadata_t entropyMetadata;
|
||||
} ZSTD_blockSplitCtx;
|
||||
|
||||
/* Context for block-level external matchfinder API */
|
||||
typedef struct {
|
||||
void* mState;
|
||||
ZSTD_sequenceProducer_F* mFinder;
|
||||
ZSTD_Sequence* seqBuffer;
|
||||
size_t seqBufferCapacity;
|
||||
} ZSTD_externalMatchCtx;
|
||||
|
||||
struct ZSTD_CCtx_s {
|
||||
ZSTD_compressionStage_e stage;
|
||||
int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */
|
||||
@@ -479,8 +473,9 @@ struct ZSTD_CCtx_s {
|
||||
/* Workspace for block splitter */
|
||||
ZSTD_blockSplitCtx blockSplitCtx;
|
||||
|
||||
/* Workspace for external matchfinder */
|
||||
ZSTD_externalMatchCtx externalMatchCtx;
|
||||
/* Buffer for output from external sequence producer */
|
||||
ZSTD_Sequence* extSeqBuf;
|
||||
size_t extSeqBufCapacity;
|
||||
};
|
||||
|
||||
typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
|
||||
@@ -1053,7 +1048,9 @@ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
|
||||
* The least significant cycleLog bits of the indices must remain the same,
|
||||
* which may be 0. Every index up to maxDist in the past must be valid.
|
||||
*/
|
||||
MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
||||
MEM_STATIC
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
||||
U32 maxDist, void const* src)
|
||||
{
|
||||
/* preemptive overflow correction:
|
||||
@@ -1246,7 +1243,9 @@ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
|
||||
* forget about the extDict. Handles overlap of the prefix and extDict.
|
||||
* Returns non-zero if the segment is contiguous.
|
||||
*/
|
||||
MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
|
||||
MEM_STATIC
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
U32 ZSTD_window_update(ZSTD_window_t* window,
|
||||
void const* src, size_t srcSize,
|
||||
int forceNonContiguous)
|
||||
{
|
||||
@@ -1508,6 +1507,10 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition*
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch);
|
||||
|
||||
/* Returns 1 if an external sequence producer is registered, otherwise returns 0. */
|
||||
MEM_STATIC int ZSTD_hasExtSeqProd(const ZSTD_CCtx_params* params) {
|
||||
return params->extSeqProdFunc != NULL;
|
||||
}
|
||||
|
||||
/* ===============================================================
|
||||
* Deprecated definitions that are still used internally to avoid
|
||||
|
||||
@@ -76,8 +76,8 @@ ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
|
||||
}
|
||||
|
||||
{ int const flags = bmi2 ? HUF_flags_bmi2 : 0;
|
||||
const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, oend-op, literals, litSize, hufTable, flags)
|
||||
: HUF_compress4X_usingCTable(op, oend-op, literals, litSize, hufTable, flags);
|
||||
const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags)
|
||||
: HUF_compress4X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags);
|
||||
op += cSize;
|
||||
cLitSize += cSize;
|
||||
if (cSize == 0 || ERR_isError(cSize)) {
|
||||
@@ -102,7 +102,7 @@ ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
|
||||
switch(lhSize)
|
||||
{
|
||||
case 3: /* 2 - 2 - 10 - 10 */
|
||||
{ U32 const lhc = hType + ((!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14);
|
||||
{ U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14);
|
||||
MEM_writeLE24(ostart, lhc);
|
||||
break;
|
||||
}
|
||||
@@ -122,30 +122,30 @@ ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
|
||||
}
|
||||
*entropyWritten = 1;
|
||||
DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)litSize, (U32)(op-ostart));
|
||||
return op-ostart;
|
||||
return (size_t)(op-ostart);
|
||||
}
|
||||
|
||||
static size_t
|
||||
ZSTD_seqDecompressedSize(seqStore_t const* seqStore,
|
||||
const seqDef* sequences, size_t nbSeq,
|
||||
size_t litSize, int lastSequence)
|
||||
const seqDef* sequences, size_t nbSeqs,
|
||||
size_t litSize, int lastSubBlock)
|
||||
{
|
||||
const seqDef* const sstart = sequences;
|
||||
const seqDef* const send = sequences + nbSeq;
|
||||
const seqDef* sp = sstart;
|
||||
size_t matchLengthSum = 0;
|
||||
size_t litLengthSum = 0;
|
||||
(void)(litLengthSum); /* suppress unused variable warning on some environments */
|
||||
while (send-sp > 0) {
|
||||
ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp);
|
||||
size_t n;
|
||||
for (n=0; n<nbSeqs; n++) {
|
||||
const ZSTD_sequenceLength seqLen = ZSTD_getSequenceLength(seqStore, sequences+n);
|
||||
litLengthSum += seqLen.litLength;
|
||||
matchLengthSum += seqLen.matchLength;
|
||||
sp++;
|
||||
}
|
||||
assert(litLengthSum <= litSize);
|
||||
if (!lastSequence) {
|
||||
DEBUGLOG(5, "ZSTD_seqDecompressedSize: %u sequences from %p: %u literals + %u matchlength",
|
||||
(unsigned)nbSeqs, (const void*)sequences,
|
||||
(unsigned)litLengthSum, (unsigned)matchLengthSum);
|
||||
if (!lastSubBlock)
|
||||
assert(litLengthSum == litSize);
|
||||
}
|
||||
else
|
||||
assert(litLengthSum <= litSize);
|
||||
(void)litLengthSum;
|
||||
return matchLengthSum + litSize;
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,
|
||||
else
|
||||
op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
|
||||
if (nbSeq==0) {
|
||||
return op - ostart;
|
||||
return (size_t)(op - ostart);
|
||||
}
|
||||
|
||||
/* seqHead : flags for FSE encoding type */
|
||||
@@ -209,7 +209,7 @@ ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,
|
||||
}
|
||||
|
||||
{ size_t const bitstreamSize = ZSTD_encodeSequences(
|
||||
op, oend - op,
|
||||
op, (size_t)(oend - op),
|
||||
fseTables->matchlengthCTable, mlCode,
|
||||
fseTables->offcodeCTable, ofCode,
|
||||
fseTables->litlengthCTable, llCode,
|
||||
@@ -253,7 +253,7 @@ ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,
|
||||
#endif
|
||||
|
||||
*entropyWritten = 1;
|
||||
return op - ostart;
|
||||
return (size_t)(op - ostart);
|
||||
}
|
||||
|
||||
/** ZSTD_compressSubBlock() :
|
||||
@@ -279,7 +279,8 @@ static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy,
|
||||
litSize, nbSeq, writeLitEntropy, writeSeqEntropy, lastBlock);
|
||||
{ size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable,
|
||||
&entropyMetadata->hufMetadata, literals, litSize,
|
||||
op, oend-op, bmi2, writeLitEntropy, litEntropyWritten);
|
||||
op, (size_t)(oend-op),
|
||||
bmi2, writeLitEntropy, litEntropyWritten);
|
||||
FORWARD_IF_ERROR(cLitSize, "ZSTD_compressSubBlock_literal failed");
|
||||
if (cLitSize == 0) return 0;
|
||||
op += cLitSize;
|
||||
@@ -289,18 +290,18 @@ static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy,
|
||||
sequences, nbSeq,
|
||||
llCode, mlCode, ofCode,
|
||||
cctxParams,
|
||||
op, oend-op,
|
||||
op, (size_t)(oend-op),
|
||||
bmi2, writeSeqEntropy, seqEntropyWritten);
|
||||
FORWARD_IF_ERROR(cSeqSize, "ZSTD_compressSubBlock_sequences failed");
|
||||
if (cSeqSize == 0) return 0;
|
||||
op += cSeqSize;
|
||||
}
|
||||
/* Write block header */
|
||||
{ size_t cSize = (op-ostart)-ZSTD_blockHeaderSize;
|
||||
{ size_t cSize = (size_t)(op-ostart) - ZSTD_blockHeaderSize;
|
||||
U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
|
||||
MEM_writeLE24(ostart, cBlockHeader24);
|
||||
}
|
||||
return op-ostart;
|
||||
return (size_t)(op-ostart);
|
||||
}
|
||||
|
||||
static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t litSize,
|
||||
@@ -389,7 +390,11 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
|
||||
return cSeqSizeEstimate + sequencesSectionHeaderSize;
|
||||
}
|
||||
|
||||
static size_t ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,
|
||||
typedef struct {
|
||||
size_t estLitSize;
|
||||
size_t estBlockSize;
|
||||
} EstimatedBlockSize;
|
||||
static EstimatedBlockSize ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,
|
||||
const BYTE* ofCodeTable,
|
||||
const BYTE* llCodeTable,
|
||||
const BYTE* mlCodeTable,
|
||||
@@ -397,15 +402,17 @@ static size_t ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,
|
||||
const ZSTD_entropyCTables_t* entropy,
|
||||
const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
|
||||
void* workspace, size_t wkspSize,
|
||||
int writeLitEntropy, int writeSeqEntropy) {
|
||||
size_t cSizeEstimate = 0;
|
||||
cSizeEstimate += ZSTD_estimateSubBlockSize_literal(literals, litSize,
|
||||
&entropy->huf, &entropyMetadata->hufMetadata,
|
||||
workspace, wkspSize, writeLitEntropy);
|
||||
cSizeEstimate += ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,
|
||||
int writeLitEntropy, int writeSeqEntropy)
|
||||
{
|
||||
EstimatedBlockSize ebs;
|
||||
ebs.estLitSize = ZSTD_estimateSubBlockSize_literal(literals, litSize,
|
||||
&entropy->huf, &entropyMetadata->hufMetadata,
|
||||
workspace, wkspSize, writeLitEntropy);
|
||||
ebs.estBlockSize = ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,
|
||||
nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,
|
||||
workspace, wkspSize, writeSeqEntropy);
|
||||
return cSizeEstimate + ZSTD_blockHeaderSize;
|
||||
ebs.estBlockSize += ebs.estLitSize + ZSTD_blockHeaderSize;
|
||||
return ebs;
|
||||
}
|
||||
|
||||
static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMetadata)
|
||||
@@ -419,13 +426,56 @@ static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMe
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t countLiterals(seqStore_t const* seqStore, const seqDef* sp, size_t seqCount)
|
||||
{
|
||||
size_t n, total = 0;
|
||||
assert(sp != NULL);
|
||||
for (n=0; n<seqCount; n++) {
|
||||
total += ZSTD_getSequenceLength(seqStore, sp+n).litLength;
|
||||
}
|
||||
DEBUGLOG(6, "countLiterals for %zu sequences from %p => %zu bytes", seqCount, (const void*)sp, total);
|
||||
return total;
|
||||
}
|
||||
|
||||
#define BYTESCALE 256
|
||||
|
||||
static size_t sizeBlockSequences(const seqDef* sp, size_t nbSeqs,
|
||||
size_t targetBudget, size_t avgLitCost, size_t avgSeqCost,
|
||||
int firstSubBlock)
|
||||
{
|
||||
size_t n, budget = 0, inSize=0;
|
||||
/* entropy headers */
|
||||
size_t const headerSize = (size_t)firstSubBlock * 120 * BYTESCALE; /* generous estimate */
|
||||
assert(firstSubBlock==0 || firstSubBlock==1);
|
||||
budget += headerSize;
|
||||
|
||||
/* first sequence => at least one sequence*/
|
||||
budget += sp[0].litLength * avgLitCost + avgSeqCost;
|
||||
if (budget > targetBudget) return 1;
|
||||
inSize = sp[0].litLength + (sp[0].mlBase+MINMATCH);
|
||||
|
||||
/* loop over sequences */
|
||||
for (n=1; n<nbSeqs; n++) {
|
||||
size_t currentCost = sp[n].litLength * avgLitCost + avgSeqCost;
|
||||
budget += currentCost;
|
||||
inSize += sp[n].litLength + (sp[n].mlBase+MINMATCH);
|
||||
/* stop when sub-block budget is reached */
|
||||
if ( (budget > targetBudget)
|
||||
/* though continue to expand until the sub-block is deemed compressible */
|
||||
&& (budget < inSize * BYTESCALE) )
|
||||
break;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/** ZSTD_compressSubBlock_multi() :
|
||||
* Breaks super-block into multiple sub-blocks and compresses them.
|
||||
* Entropy will be written to the first block.
|
||||
* The following blocks will use repeat mode to compress.
|
||||
* All sub-blocks are compressed blocks (no raw or rle blocks).
|
||||
* @return : compressed size of the super block (which is multiple ZSTD blocks)
|
||||
* Or 0 if it failed to compress. */
|
||||
* Entropy will be written into the first block.
|
||||
* The following blocks use repeat_mode to compress.
|
||||
* Sub-blocks are all compressed, except the last one when beneficial.
|
||||
* @return : compressed size of the super block (which features multiple ZSTD blocks)
|
||||
* or 0 if it failed to compress. */
|
||||
static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
|
||||
const ZSTD_compressedBlockState_t* prevCBlock,
|
||||
ZSTD_compressedBlockState_t* nextCBlock,
|
||||
@@ -438,10 +488,12 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
|
||||
{
|
||||
const seqDef* const sstart = seqStorePtr->sequencesStart;
|
||||
const seqDef* const send = seqStorePtr->sequences;
|
||||
const seqDef* sp = sstart;
|
||||
const seqDef* sp = sstart; /* tracks progresses within seqStorePtr->sequences */
|
||||
size_t const nbSeqs = (size_t)(send - sstart);
|
||||
const BYTE* const lstart = seqStorePtr->litStart;
|
||||
const BYTE* const lend = seqStorePtr->lit;
|
||||
const BYTE* lp = lstart;
|
||||
size_t const nbLiterals = (size_t)(lend - lstart);
|
||||
BYTE const* ip = (BYTE const*)src;
|
||||
BYTE const* const iend = ip + srcSize;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
@@ -450,96 +502,152 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
|
||||
const BYTE* llCodePtr = seqStorePtr->llCode;
|
||||
const BYTE* mlCodePtr = seqStorePtr->mlCode;
|
||||
const BYTE* ofCodePtr = seqStorePtr->ofCode;
|
||||
size_t targetCBlockSize = cctxParams->targetCBlockSize;
|
||||
size_t litSize, seqCount;
|
||||
int writeLitEntropy = entropyMetadata->hufMetadata.hType == set_compressed;
|
||||
size_t const minTarget = ZSTD_TARGETCBLOCKSIZE_MIN; /* enforce minimum size, to reduce undesirable side effects */
|
||||
size_t const targetCBlockSize = MAX(minTarget, cctxParams->targetCBlockSize);
|
||||
int writeLitEntropy = (entropyMetadata->hufMetadata.hType == set_compressed);
|
||||
int writeSeqEntropy = 1;
|
||||
int lastSequence = 0;
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressSubBlock_multi (litSize=%u, nbSeq=%u)",
|
||||
(unsigned)(lend-lp), (unsigned)(send-sstart));
|
||||
DEBUGLOG(5, "ZSTD_compressSubBlock_multi (srcSize=%u, litSize=%u, nbSeq=%u)",
|
||||
(unsigned)srcSize, (unsigned)(lend-lstart), (unsigned)(send-sstart));
|
||||
|
||||
litSize = 0;
|
||||
seqCount = 0;
|
||||
do {
|
||||
size_t cBlockSizeEstimate = 0;
|
||||
if (sstart == send) {
|
||||
lastSequence = 1;
|
||||
} else {
|
||||
const seqDef* const sequence = sp + seqCount;
|
||||
lastSequence = sequence == send - 1;
|
||||
litSize += ZSTD_getSequenceLength(seqStorePtr, sequence).litLength;
|
||||
seqCount++;
|
||||
/* let's start by a general estimation for the full block */
|
||||
if (nbSeqs > 0) {
|
||||
EstimatedBlockSize const ebs =
|
||||
ZSTD_estimateSubBlockSize(lp, nbLiterals,
|
||||
ofCodePtr, llCodePtr, mlCodePtr, nbSeqs,
|
||||
&nextCBlock->entropy, entropyMetadata,
|
||||
workspace, wkspSize,
|
||||
writeLitEntropy, writeSeqEntropy);
|
||||
/* quick estimation */
|
||||
size_t const avgLitCost = nbLiterals ? (ebs.estLitSize * BYTESCALE) / nbLiterals : BYTESCALE;
|
||||
size_t const avgSeqCost = ((ebs.estBlockSize - ebs.estLitSize) * BYTESCALE) / nbSeqs;
|
||||
const size_t nbSubBlocks = MAX((ebs.estBlockSize + (targetCBlockSize/2)) / targetCBlockSize, 1);
|
||||
size_t n, avgBlockBudget, blockBudgetSupp=0;
|
||||
avgBlockBudget = (ebs.estBlockSize * BYTESCALE) / nbSubBlocks;
|
||||
DEBUGLOG(5, "estimated fullblock size=%u bytes ; avgLitCost=%.2f ; avgSeqCost=%.2f ; targetCBlockSize=%u, nbSubBlocks=%u ; avgBlockBudget=%.0f bytes",
|
||||
(unsigned)ebs.estBlockSize, (double)avgLitCost/BYTESCALE, (double)avgSeqCost/BYTESCALE,
|
||||
(unsigned)targetCBlockSize, (unsigned)nbSubBlocks, (double)avgBlockBudget/BYTESCALE);
|
||||
/* simplification: if estimates states that the full superblock doesn't compress, just bail out immediately
|
||||
* this will result in the production of a single uncompressed block covering @srcSize.*/
|
||||
if (ebs.estBlockSize > srcSize) return 0;
|
||||
|
||||
/* compress and write sub-blocks */
|
||||
assert(nbSubBlocks>0);
|
||||
for (n=0; n < nbSubBlocks-1; n++) {
|
||||
/* determine nb of sequences for current sub-block + nbLiterals from next sequence */
|
||||
size_t const seqCount = sizeBlockSequences(sp, (size_t)(send-sp),
|
||||
avgBlockBudget + blockBudgetSupp, avgLitCost, avgSeqCost, n==0);
|
||||
/* if reached last sequence : break to last sub-block (simplification) */
|
||||
assert(seqCount <= (size_t)(send-sp));
|
||||
if (sp + seqCount == send) break;
|
||||
assert(seqCount > 0);
|
||||
/* compress sub-block */
|
||||
{ int litEntropyWritten = 0;
|
||||
int seqEntropyWritten = 0;
|
||||
size_t litSize = countLiterals(seqStorePtr, sp, seqCount);
|
||||
const size_t decompressedSize =
|
||||
ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 0);
|
||||
size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
|
||||
sp, seqCount,
|
||||
lp, litSize,
|
||||
llCodePtr, mlCodePtr, ofCodePtr,
|
||||
cctxParams,
|
||||
op, (size_t)(oend-op),
|
||||
bmi2, writeLitEntropy, writeSeqEntropy,
|
||||
&litEntropyWritten, &seqEntropyWritten,
|
||||
0);
|
||||
FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
|
||||
|
||||
/* check compressibility, update state components */
|
||||
if (cSize > 0 && cSize < decompressedSize) {
|
||||
DEBUGLOG(5, "Committed sub-block compressing %u bytes => %u bytes",
|
||||
(unsigned)decompressedSize, (unsigned)cSize);
|
||||
assert(ip + decompressedSize <= iend);
|
||||
ip += decompressedSize;
|
||||
lp += litSize;
|
||||
op += cSize;
|
||||
llCodePtr += seqCount;
|
||||
mlCodePtr += seqCount;
|
||||
ofCodePtr += seqCount;
|
||||
/* Entropy only needs to be written once */
|
||||
if (litEntropyWritten) {
|
||||
writeLitEntropy = 0;
|
||||
}
|
||||
if (seqEntropyWritten) {
|
||||
writeSeqEntropy = 0;
|
||||
}
|
||||
sp += seqCount;
|
||||
blockBudgetSupp = 0;
|
||||
} }
|
||||
/* otherwise : do not compress yet, coalesce current sub-block with following one */
|
||||
}
|
||||
if (lastSequence) {
|
||||
assert(lp <= lend);
|
||||
assert(litSize <= (size_t)(lend - lp));
|
||||
litSize = (size_t)(lend - lp);
|
||||
}
|
||||
/* I think there is an optimization opportunity here.
|
||||
* Calling ZSTD_estimateSubBlockSize for every sequence can be wasteful
|
||||
* since it recalculates estimate from scratch.
|
||||
* For example, it would recount literal distribution and symbol codes every time.
|
||||
*/
|
||||
cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount,
|
||||
&nextCBlock->entropy, entropyMetadata,
|
||||
workspace, wkspSize, writeLitEntropy, writeSeqEntropy);
|
||||
if (cBlockSizeEstimate > targetCBlockSize || lastSequence) {
|
||||
int litEntropyWritten = 0;
|
||||
int seqEntropyWritten = 0;
|
||||
const size_t decompressedSize = ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, lastSequence);
|
||||
const size_t cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
|
||||
sp, seqCount,
|
||||
lp, litSize,
|
||||
llCodePtr, mlCodePtr, ofCodePtr,
|
||||
cctxParams,
|
||||
op, oend-op,
|
||||
bmi2, writeLitEntropy, writeSeqEntropy,
|
||||
&litEntropyWritten, &seqEntropyWritten,
|
||||
lastBlock && lastSequence);
|
||||
FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
|
||||
if (cSize > 0 && cSize < decompressedSize) {
|
||||
DEBUGLOG(5, "Committed the sub-block");
|
||||
assert(ip + decompressedSize <= iend);
|
||||
ip += decompressedSize;
|
||||
sp += seqCount;
|
||||
lp += litSize;
|
||||
op += cSize;
|
||||
llCodePtr += seqCount;
|
||||
mlCodePtr += seqCount;
|
||||
ofCodePtr += seqCount;
|
||||
litSize = 0;
|
||||
seqCount = 0;
|
||||
/* Entropy only needs to be written once */
|
||||
if (litEntropyWritten) {
|
||||
writeLitEntropy = 0;
|
||||
}
|
||||
if (seqEntropyWritten) {
|
||||
writeSeqEntropy = 0;
|
||||
}
|
||||
} /* if (nbSeqs > 0) */
|
||||
|
||||
/* write last block */
|
||||
DEBUGLOG(5, "Generate last sub-block: %u sequences remaining", (unsigned)(send - sp));
|
||||
{ int litEntropyWritten = 0;
|
||||
int seqEntropyWritten = 0;
|
||||
size_t litSize = (size_t)(lend - lp);
|
||||
size_t seqCount = (size_t)(send - sp);
|
||||
const size_t decompressedSize =
|
||||
ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 1);
|
||||
size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
|
||||
sp, seqCount,
|
||||
lp, litSize,
|
||||
llCodePtr, mlCodePtr, ofCodePtr,
|
||||
cctxParams,
|
||||
op, (size_t)(oend-op),
|
||||
bmi2, writeLitEntropy, writeSeqEntropy,
|
||||
&litEntropyWritten, &seqEntropyWritten,
|
||||
lastBlock);
|
||||
FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
|
||||
|
||||
/* update pointers, the nb of literals borrowed from next sequence must be preserved */
|
||||
if (cSize > 0 && cSize < decompressedSize) {
|
||||
DEBUGLOG(5, "Last sub-block compressed %u bytes => %u bytes",
|
||||
(unsigned)decompressedSize, (unsigned)cSize);
|
||||
assert(ip + decompressedSize <= iend);
|
||||
ip += decompressedSize;
|
||||
lp += litSize;
|
||||
op += cSize;
|
||||
llCodePtr += seqCount;
|
||||
mlCodePtr += seqCount;
|
||||
ofCodePtr += seqCount;
|
||||
/* Entropy only needs to be written once */
|
||||
if (litEntropyWritten) {
|
||||
writeLitEntropy = 0;
|
||||
}
|
||||
if (seqEntropyWritten) {
|
||||
writeSeqEntropy = 0;
|
||||
}
|
||||
sp += seqCount;
|
||||
}
|
||||
} while (!lastSequence);
|
||||
}
|
||||
|
||||
|
||||
if (writeLitEntropy) {
|
||||
DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten");
|
||||
DEBUGLOG(5, "Literal entropy tables were never written");
|
||||
ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));
|
||||
}
|
||||
if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) {
|
||||
/* If we haven't written our entropy tables, then we've violated our contract and
|
||||
* must emit an uncompressed block.
|
||||
*/
|
||||
DEBUGLOG(5, "ZSTD_compressSubBlock_multi has sequence entropy tables unwritten");
|
||||
DEBUGLOG(5, "Sequence entropy tables were never written => cancel, emit an uncompressed block");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ip < iend) {
|
||||
size_t const cSize = ZSTD_noCompressBlock(op, oend - op, ip, iend - ip, lastBlock);
|
||||
DEBUGLOG(5, "ZSTD_compressSubBlock_multi last sub-block uncompressed, %zu bytes", (size_t)(iend - ip));
|
||||
/* some data left : last part of the block sent uncompressed */
|
||||
size_t const rSize = (size_t)((iend - ip));
|
||||
size_t const cSize = ZSTD_noCompressBlock(op, (size_t)(oend - op), ip, rSize, lastBlock);
|
||||
DEBUGLOG(5, "Generate last uncompressed sub-block of %u bytes", (unsigned)(rSize));
|
||||
FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
|
||||
assert(cSize != 0);
|
||||
op += cSize;
|
||||
/* We have to regenerate the repcodes because we've skipped some sequences */
|
||||
if (sp < send) {
|
||||
seqDef const* seq;
|
||||
const seqDef* seq;
|
||||
repcodes_t rep;
|
||||
ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
|
||||
for (seq = sstart; seq < sp; ++seq) {
|
||||
@@ -548,14 +656,17 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
|
||||
ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
|
||||
}
|
||||
}
|
||||
DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed");
|
||||
return op-ostart;
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed all subBlocks: total compressed size = %u",
|
||||
(unsigned)(op-ostart));
|
||||
return (size_t)(op-ostart);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
void const* src, size_t srcSize,
|
||||
unsigned lastBlock) {
|
||||
const void* src, size_t srcSize,
|
||||
unsigned lastBlock)
|
||||
{
|
||||
ZSTD_entropyCTablesMetadata_t entropyMetadata;
|
||||
|
||||
FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(&zc->seqStore,
|
||||
|
||||
@@ -434,7 +434,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes)
|
||||
|
||||
/**
|
||||
* Aligned on 64 bytes. These buffers have the special property that
|
||||
* their values remain constrained, allowing us to re-use them without
|
||||
* their values remain constrained, allowing us to reuse them without
|
||||
* memset()-ing them.
|
||||
*/
|
||||
MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes)
|
||||
@@ -526,7 +526,7 @@ MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws)
|
||||
DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty");
|
||||
|
||||
#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
|
||||
/* To validate that the table re-use logic is sound, and that we don't
|
||||
/* To validate that the table reuse logic is sound, and that we don't
|
||||
* access table space that we haven't cleaned, we re-"poison" the table
|
||||
* space every time we mark it dirty.
|
||||
* Since tableValidEnd space and initOnce space may overlap we don't poison
|
||||
@@ -603,9 +603,9 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
|
||||
DEBUGLOG(4, "cwksp: clearing!");
|
||||
|
||||
#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
|
||||
/* To validate that the context re-use logic is sound, and that we don't
|
||||
/* To validate that the context reuse logic is sound, and that we don't
|
||||
* access stuff that this compression hasn't initialized, we re-"poison"
|
||||
* the workspace except for the areas in which we expect memory re-use
|
||||
* the workspace except for the areas in which we expect memory reuse
|
||||
* without initialization (objects, valid tables area and init once
|
||||
* memory). */
|
||||
{
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
|
||||
#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR
|
||||
|
||||
static void ZSTD_fillDoubleHashTableForCDict(ZSTD_matchState_t* ms,
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_fillDoubleHashTableForCDict(ZSTD_matchState_t* ms,
|
||||
void const* end, ZSTD_dictTableLoadMethod_e dtlm)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
@@ -49,7 +51,9 @@ static void ZSTD_fillDoubleHashTableForCDict(ZSTD_matchState_t* ms,
|
||||
} }
|
||||
}
|
||||
|
||||
static void ZSTD_fillDoubleHashTableForCCtx(ZSTD_matchState_t* ms,
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_fillDoubleHashTableForCCtx(ZSTD_matchState_t* ms,
|
||||
void const* end, ZSTD_dictTableLoadMethod_e dtlm)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
@@ -97,6 +101,7 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_compressBlock_doubleFast_noDict_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize, U32 const mls /* template */)
|
||||
@@ -307,6 +312,7 @@ _match_stored:
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize,
|
||||
@@ -350,8 +356,8 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic(
|
||||
if (ms->prefetchCDictTables) {
|
||||
size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32);
|
||||
size_t const chainTableBytes = (((size_t)1) << dictCParams->chainLog) * sizeof(U32);
|
||||
PREFETCH_AREA(dictHashLong, hashTableBytes)
|
||||
PREFETCH_AREA(dictHashSmall, chainTableBytes)
|
||||
PREFETCH_AREA(dictHashLong, hashTableBytes);
|
||||
PREFETCH_AREA(dictHashSmall, chainTableBytes);
|
||||
}
|
||||
|
||||
/* init */
|
||||
@@ -591,7 +597,9 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState(
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize,
|
||||
U32 const mls /* template */)
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#include "zstd_compress_internal.h" /* ZSTD_hashPtr, ZSTD_count, ZSTD_storeSeq */
|
||||
#include "zstd_fast.h"
|
||||
|
||||
static void ZSTD_fillHashTableForCDict(ZSTD_matchState_t* ms,
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_fillHashTableForCDict(ZSTD_matchState_t* ms,
|
||||
const void* const end,
|
||||
ZSTD_dictTableLoadMethod_e dtlm)
|
||||
{
|
||||
@@ -46,7 +48,9 @@ static void ZSTD_fillHashTableForCDict(ZSTD_matchState_t* ms,
|
||||
} } } }
|
||||
}
|
||||
|
||||
static void ZSTD_fillHashTableForCCtx(ZSTD_matchState_t* ms,
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_fillHashTableForCCtx(ZSTD_matchState_t* ms,
|
||||
const void* const end,
|
||||
ZSTD_dictTableLoadMethod_e dtlm)
|
||||
{
|
||||
@@ -139,8 +143,9 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
|
||||
*
|
||||
* This is also the work we do at the beginning to enter the loop initially.
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
ZSTD_compressBlock_fast_noDict_generic(
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_compressBlock_fast_noDict_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize,
|
||||
U32 const mls, U32 const hasStep)
|
||||
@@ -456,6 +461,7 @@ size_t ZSTD_compressBlock_fast(
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
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, U32 const hasStep)
|
||||
@@ -502,7 +508,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||
|
||||
if (ms->prefetchCDictTables) {
|
||||
size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32);
|
||||
PREFETCH_AREA(dictHashTable, hashTableBytes)
|
||||
PREFETCH_AREA(dictHashTable, hashTableBytes);
|
||||
}
|
||||
|
||||
/* init */
|
||||
@@ -681,7 +687,9 @@ size_t ZSTD_compressBlock_fast_dictMatchState(
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize, U32 const mls, U32 const hasStep)
|
||||
{
|
||||
|
||||
+50
-31
@@ -24,8 +24,9 @@
|
||||
* Binary Tree search
|
||||
***************************************/
|
||||
|
||||
static void
|
||||
ZSTD_updateDUBT(ZSTD_matchState_t* ms,
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_updateDUBT(ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* iend,
|
||||
U32 mls)
|
||||
{
|
||||
@@ -68,8 +69,9 @@ ZSTD_updateDUBT(ZSTD_matchState_t* ms,
|
||||
* sort one already inserted but unsorted position
|
||||
* assumption : curr >= btlow == (curr - btmask)
|
||||
* doesn't fail */
|
||||
static void
|
||||
ZSTD_insertDUBT1(const ZSTD_matchState_t* ms,
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_insertDUBT1(const ZSTD_matchState_t* ms,
|
||||
U32 curr, const BYTE* inputEnd,
|
||||
U32 nbCompares, U32 btLow,
|
||||
const ZSTD_dictMode_e dictMode)
|
||||
@@ -157,8 +159,9 @@ ZSTD_insertDUBT1(const ZSTD_matchState_t* ms,
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
ZSTD_DUBT_findBetterDictMatch (
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_DUBT_findBetterDictMatch (
|
||||
const ZSTD_matchState_t* ms,
|
||||
const BYTE* const ip, const BYTE* const iend,
|
||||
size_t* offsetPtr,
|
||||
@@ -235,8 +238,9 @@ ZSTD_DUBT_findBetterDictMatch (
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
|
||||
const BYTE* const ip, const BYTE* const iend,
|
||||
size_t* offBasePtr,
|
||||
U32 const mls,
|
||||
@@ -386,8 +390,9 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
|
||||
|
||||
|
||||
/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms,
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms,
|
||||
const BYTE* const ip, const BYTE* const iLimit,
|
||||
size_t* offBasePtr,
|
||||
const U32 mls /* template */,
|
||||
@@ -622,7 +627,9 @@ size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nb
|
||||
|
||||
/* Update chains up to ip (excluded)
|
||||
Assumption : always within prefix (i.e. not within extDict) */
|
||||
FORCE_INLINE_TEMPLATE U32 ZSTD_insertAndFindFirstIndex_internal(
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
U32 ZSTD_insertAndFindFirstIndex_internal(
|
||||
ZSTD_matchState_t* ms,
|
||||
const ZSTD_compressionParameters* const cParams,
|
||||
const BYTE* ip, U32 const mls, U32 const lazySkipping)
|
||||
@@ -656,6 +663,7 @@ U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) {
|
||||
|
||||
/* inlining is important to hardwire a hot branch (template emulation) */
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_HcFindBestMatch(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* const ip, const BYTE* const iLimit,
|
||||
@@ -824,7 +832,9 @@ FORCE_INLINE_TEMPLATE void ZSTD_row_prefetch(U32 const* hashTable, BYTE const* t
|
||||
* Fill up the hash cache starting at idx, prefetching up to ZSTD_ROW_HASH_CACHE_SIZE entries,
|
||||
* but not beyond iLimit.
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE void ZSTD_row_fillHashCache(ZSTD_matchState_t* ms, const BYTE* base,
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_row_fillHashCache(ZSTD_matchState_t* ms, const BYTE* base,
|
||||
U32 const rowLog, U32 const mls,
|
||||
U32 idx, const BYTE* const iLimit)
|
||||
{
|
||||
@@ -850,7 +860,9 @@ FORCE_INLINE_TEMPLATE void ZSTD_row_fillHashCache(ZSTD_matchState_t* ms, const B
|
||||
* Returns the hash of base + idx, and replaces the hash in the hash cache with the byte at
|
||||
* base + idx + ZSTD_ROW_HASH_CACHE_SIZE. Also prefetches the appropriate rows from hashTable and tagTable.
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE U32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTable,
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
U32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTable,
|
||||
BYTE const* tagTable, BYTE const* base,
|
||||
U32 idx, U32 const hashLog,
|
||||
U32 const rowLog, U32 const mls,
|
||||
@@ -868,10 +880,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTab
|
||||
/* ZSTD_row_update_internalImpl():
|
||||
* Updates the hash table with positions starting from updateStartIdx until updateEndIdx.
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE void ZSTD_row_update_internalImpl(ZSTD_matchState_t* ms,
|
||||
U32 updateStartIdx, U32 const updateEndIdx,
|
||||
U32 const mls, U32 const rowLog,
|
||||
U32 const rowMask, U32 const useCache)
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_row_update_internalImpl(ZSTD_matchState_t* ms,
|
||||
U32 updateStartIdx, U32 const updateEndIdx,
|
||||
U32 const mls, U32 const rowLog,
|
||||
U32 const rowMask, U32 const useCache)
|
||||
{
|
||||
U32* const hashTable = ms->hashTable;
|
||||
BYTE* const tagTable = ms->tagTable;
|
||||
@@ -897,9 +911,11 @@ FORCE_INLINE_TEMPLATE void ZSTD_row_update_internalImpl(ZSTD_matchState_t* ms,
|
||||
* Inserts the byte at ip into the appropriate position in the hash table, and updates ms->nextToUpdate.
|
||||
* Skips sections of long matches as is necessary.
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const BYTE* ip,
|
||||
U32 const mls, U32 const rowLog,
|
||||
U32 const rowMask, U32 const useCache)
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const BYTE* ip,
|
||||
U32 const mls, U32 const rowLog,
|
||||
U32 const rowMask, U32 const useCache)
|
||||
{
|
||||
U32 idx = ms->nextToUpdate;
|
||||
const BYTE* const base = ms->window.base;
|
||||
@@ -1107,20 +1123,21 @@ ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 headGr
|
||||
|
||||
/* The high-level approach of the SIMD row based match finder is as follows:
|
||||
* - Figure out where to insert the new entry:
|
||||
* - Generate a hash from a byte along with an additional 1-byte "short hash". The additional byte is our "tag"
|
||||
* - The hashTable is effectively split into groups or "rows" of 16 or 32 entries of U32, and the hash determines
|
||||
* - Generate a hash for current input posistion and split it into a one byte of tag and `rowHashLog` bits of index.
|
||||
* - The hash is salted by a value that changes on every contex reset, so when the same table is used
|
||||
* we will avoid collisions that would otherwise slow us down by intorducing phantom matches.
|
||||
* - The hashTable is effectively split into groups or "rows" of 15 or 31 entries of U32, and the index determines
|
||||
* which row to insert into.
|
||||
* - Determine the correct position within the row to insert the entry into. Each row of 16 or 32 can
|
||||
* be considered as a circular buffer with a "head" index that resides in the tagTable.
|
||||
* - Also insert the "tag" into the equivalent row and position in the tagTable.
|
||||
* - Note: The tagTable has 17 or 33 1-byte entries per row, due to 16 or 32 tags, and 1 "head" entry.
|
||||
* The 17 or 33 entry rows are spaced out to occur every 32 or 64 bytes, respectively,
|
||||
* for alignment/performance reasons, leaving some bytes unused.
|
||||
* - Use SIMD to efficiently compare the tags in the tagTable to the 1-byte "short hash" and
|
||||
* - Determine the correct position within the row to insert the entry into. Each row of 15 or 31 can
|
||||
* be considered as a circular buffer with a "head" index that resides in the tagTable (overall 16 or 32 bytes
|
||||
* per row).
|
||||
* - Use SIMD to efficiently compare the tags in the tagTable to the 1-byte tag calculated for the position and
|
||||
* generate a bitfield that we can cycle through to check the collisions in the hash table.
|
||||
* - Pick the longest match.
|
||||
* - Insert the tag into the equivalent row and position in the tagTable.
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_RowFindBestMatch(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* const ip, const BYTE* const iLimit,
|
||||
@@ -1494,8 +1511,9 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_searchMax(
|
||||
* Common parser - lazy strategy
|
||||
*********************************/
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
ZSTD_compressBlock_lazy_generic(
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_compressBlock_lazy_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore,
|
||||
U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize,
|
||||
@@ -1915,6 +1933,7 @@ size_t ZSTD_compressBlock_btlazy2_dictMatchState(
|
||||
|| !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \
|
||||
|| !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR)
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_compressBlock_lazy_extDict_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore,
|
||||
U32 rep[ZSTD_REP_NUM],
|
||||
|
||||
@@ -322,7 +322,9 @@ static void ZSTD_ldm_limitTableUpdate(ZSTD_matchState_t* ms, const BYTE* anchor)
|
||||
}
|
||||
}
|
||||
|
||||
static size_t ZSTD_ldm_generateSequences_internal(
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_ldm_generateSequences_internal(
|
||||
ldmState_t* ldmState, rawSeqStore_t* rawSeqStore,
|
||||
ldmParams_t const* params, void const* src, size_t srcSize)
|
||||
{
|
||||
@@ -693,7 +695,6 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
|
||||
/* maybeSplitSequence updates rawSeqStore->pos */
|
||||
rawSeq const sequence = maybeSplitSequence(rawSeqStore,
|
||||
(U32)(iend - ip), minMatch);
|
||||
int i;
|
||||
/* End signal */
|
||||
if (sequence.offset == 0)
|
||||
break;
|
||||
@@ -706,6 +707,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
|
||||
/* Run the block compressor */
|
||||
DEBUGLOG(5, "pos %u : calling block compressor on segment of size %u", (unsigned)(ip-istart), sequence.litLength);
|
||||
{
|
||||
int i;
|
||||
size_t const newLitLength =
|
||||
blockCompressor(ms, seqStore, rep, ip, sequence.litLength);
|
||||
ip += sequence.litLength;
|
||||
|
||||
+195
-107
@@ -267,6 +267,7 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
|
||||
const optState_t* const optPtr,
|
||||
int optLevel)
|
||||
{
|
||||
DEBUGLOG(8, "ZSTD_rawLiteralsCost (%u literals)", litLength);
|
||||
if (litLength == 0) return 0;
|
||||
|
||||
if (!ZSTD_compressedLiterals(optPtr))
|
||||
@@ -405,9 +406,11 @@ 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 (const ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
const BYTE* const ip)
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
U32 ZSTD_insertAndFindFirstIndexHash3 (const ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
const BYTE* const ip)
|
||||
{
|
||||
U32* const hashTable3 = ms->hashTable3;
|
||||
U32 const hashLog3 = ms->hashLog3;
|
||||
@@ -434,7 +437,9 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (const ZSTD_matchState_t* ms,
|
||||
* @param ip assumed <= iend-8 .
|
||||
* @param target The target of ZSTD_updateTree_internal() - we are filling to this position
|
||||
* @return : nb of positions added */
|
||||
static U32 ZSTD_insertBt1(
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
U32 ZSTD_insertBt1(
|
||||
const ZSTD_matchState_t* ms,
|
||||
const BYTE* const ip, const BYTE* const iend,
|
||||
U32 const target,
|
||||
@@ -553,6 +558,7 @@ static U32 ZSTD_insertBt1(
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_updateTree_internal(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* const ip, const BYTE* const iend,
|
||||
@@ -561,7 +567,7 @@ void ZSTD_updateTree_internal(
|
||||
const BYTE* const base = ms->window.base;
|
||||
U32 const target = (U32)(ip - base);
|
||||
U32 idx = ms->nextToUpdate;
|
||||
DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
|
||||
DEBUGLOG(7, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
|
||||
idx, target, dictMode);
|
||||
|
||||
while(idx < target) {
|
||||
@@ -578,7 +584,9 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
|
||||
ZSTD_updateTree_internal(ms, ip, iend, ms->cParams.minMatch, ZSTD_noDict);
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE U32
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
U32
|
||||
ZSTD_insertBtAndGetAllMatches (
|
||||
ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
|
||||
ZSTD_matchState_t* ms,
|
||||
@@ -819,7 +827,9 @@ typedef U32 (*ZSTD_getAllMatchesFn)(
|
||||
U32 const ll0,
|
||||
U32 const lengthToBeat);
|
||||
|
||||
FORCE_INLINE_TEMPLATE U32 ZSTD_btGetAllMatches_internal(
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
U32 ZSTD_btGetAllMatches_internal(
|
||||
ZSTD_match_t* matches,
|
||||
ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
@@ -1038,11 +1048,6 @@ ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm,
|
||||
* Optimal parser
|
||||
*********************************/
|
||||
|
||||
static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
|
||||
{
|
||||
return sol.litlen + sol.mlen;
|
||||
}
|
||||
|
||||
#if 0 /* debug */
|
||||
|
||||
static void
|
||||
@@ -1060,7 +1065,13 @@ listStats(const U32* table, int lastEltID)
|
||||
|
||||
#endif
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
#define LIT_PRICE(_p) (int)ZSTD_rawLiteralsCost(_p, 1, optStatePtr, optLevel)
|
||||
#define LL_PRICE(_l) (int)ZSTD_litLengthPrice(_l, optStatePtr, optLevel)
|
||||
#define LL_INCPRICE(_l) (LL_PRICE(_l) - LL_PRICE(_l-1))
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t
|
||||
ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
seqStore_t* seqStore,
|
||||
U32 rep[ZSTD_REP_NUM],
|
||||
@@ -1086,10 +1097,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
|
||||
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
|
||||
ZSTD_match_t* const matches = optStatePtr->matchTable;
|
||||
ZSTD_optimal_t lastSequence;
|
||||
ZSTD_optimal_t lastStretch;
|
||||
ZSTD_optLdm_t optLdm;
|
||||
|
||||
ZSTD_memset(&lastSequence, 0, sizeof(ZSTD_optimal_t));
|
||||
ZSTD_memset(&lastStretch, 0, sizeof(ZSTD_optimal_t));
|
||||
|
||||
optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore;
|
||||
optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0;
|
||||
@@ -1111,19 +1122,31 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
U32 const ll0 = !litlen;
|
||||
U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, ip, iend, rep, ll0, minMatch);
|
||||
ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
|
||||
(U32)(ip-istart), (U32)(iend - ip));
|
||||
if (!nbMatches) { ip++; continue; }
|
||||
(U32)(ip-istart), (U32)(iend-ip));
|
||||
if (!nbMatches) {
|
||||
DEBUGLOG(8, "no match found at cPos %u", (unsigned)(ip-istart));
|
||||
ip++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Match found: let's store this solution, and eventually find more candidates.
|
||||
* During this forward pass, @opt is used to store stretches,
|
||||
* defined as "a match followed by N literals".
|
||||
* Note how this is different from a Sequence, which is "N literals followed by a match".
|
||||
* Storing stretches allows us to store different match predecessors
|
||||
* for each literal position part of a literals run. */
|
||||
|
||||
/* initialize opt[0] */
|
||||
{ U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
|
||||
opt[0].mlen = 0; /* means is_a_literal */
|
||||
opt[0].mlen = 0; /* there are only literals so far */
|
||||
opt[0].litlen = litlen;
|
||||
/* We don't need to include the actual price of the literals because
|
||||
* it is static for the duration of the forward pass, and is included
|
||||
* in every price. We include the literal length to avoid negative
|
||||
* prices when we subtract the previous literal length.
|
||||
/* No need to include the actual price of the literals before the first match
|
||||
* because it is static for the duration of the forward pass, and is included
|
||||
* in every subsequent price. But, we include the literal length because
|
||||
* the cost variation of litlen depends on the value of litlen.
|
||||
*/
|
||||
opt[0].price = (int)ZSTD_litLengthPrice(litlen, optStatePtr, optLevel);
|
||||
opt[0].price = LL_PRICE(litlen);
|
||||
ZSTD_STATIC_ASSERT(sizeof(opt[0].rep[0]) == sizeof(rep[0]));
|
||||
ZSTD_memcpy(&opt[0].rep, rep, sizeof(opt[0].rep));
|
||||
|
||||
/* large match -> immediate encoding */
|
||||
{ U32 const maxML = matches[nbMatches-1].len;
|
||||
@@ -1132,82 +1155,106 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
nbMatches, maxML, maxOffBase, (U32)(ip-prefixStart));
|
||||
|
||||
if (maxML > sufficient_len) {
|
||||
lastSequence.litlen = litlen;
|
||||
lastSequence.mlen = maxML;
|
||||
lastSequence.off = maxOffBase;
|
||||
DEBUGLOG(6, "large match (%u>%u), immediate encoding",
|
||||
lastStretch.litlen = 0;
|
||||
lastStretch.mlen = maxML;
|
||||
lastStretch.off = maxOffBase;
|
||||
DEBUGLOG(6, "large match (%u>%u) => immediate encoding",
|
||||
maxML, sufficient_len);
|
||||
cur = 0;
|
||||
last_pos = ZSTD_totalLen(lastSequence);
|
||||
last_pos = maxML;
|
||||
goto _shortestPath;
|
||||
} }
|
||||
|
||||
/* set prices for first matches starting position == 0 */
|
||||
assert(opt[0].price >= 0);
|
||||
{ U32 const literalsPrice = (U32)opt[0].price + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
|
||||
U32 pos;
|
||||
{ U32 pos;
|
||||
U32 matchNb;
|
||||
for (pos = 1; pos < minMatch; pos++) {
|
||||
opt[pos].price = ZSTD_MAX_PRICE; /* mlen, litlen and price will be fixed during forward scanning */
|
||||
opt[pos].price = ZSTD_MAX_PRICE;
|
||||
opt[pos].mlen = 0;
|
||||
opt[pos].litlen = litlen + pos;
|
||||
}
|
||||
for (matchNb = 0; matchNb < nbMatches; matchNb++) {
|
||||
U32 const offBase = matches[matchNb].off;
|
||||
U32 const end = matches[matchNb].len;
|
||||
for ( ; pos <= end ; pos++ ) {
|
||||
U32 const matchPrice = ZSTD_getMatchPrice(offBase, pos, optStatePtr, optLevel);
|
||||
U32 const sequencePrice = literalsPrice + matchPrice;
|
||||
int const matchPrice = (int)ZSTD_getMatchPrice(offBase, pos, optStatePtr, optLevel);
|
||||
int const sequencePrice = opt[0].price + matchPrice;
|
||||
DEBUGLOG(7, "rPos:%u => set initial price : %.2f",
|
||||
pos, ZSTD_fCost((int)sequencePrice));
|
||||
pos, ZSTD_fCost(sequencePrice));
|
||||
opt[pos].mlen = pos;
|
||||
opt[pos].off = offBase;
|
||||
opt[pos].litlen = litlen;
|
||||
opt[pos].price = (int)sequencePrice;
|
||||
} }
|
||||
opt[pos].litlen = 0; /* end of match */
|
||||
opt[pos].price = sequencePrice + LL_PRICE(0);
|
||||
}
|
||||
}
|
||||
last_pos = pos-1;
|
||||
opt[pos].price = ZSTD_MAX_PRICE;
|
||||
}
|
||||
}
|
||||
|
||||
/* check further positions */
|
||||
for (cur = 1; cur <= last_pos; cur++) {
|
||||
const BYTE* const inr = ip + cur;
|
||||
assert(cur < ZSTD_OPT_NUM);
|
||||
DEBUGLOG(7, "cPos:%zi==rPos:%u", inr-istart, cur)
|
||||
assert(cur <= ZSTD_OPT_NUM);
|
||||
DEBUGLOG(7, "cPos:%zi==rPos:%u", inr-istart, cur);
|
||||
|
||||
/* Fix current position with one literal if cheaper */
|
||||
{ U32 const litlen = (opt[cur-1].mlen == 0) ? opt[cur-1].litlen + 1 : 1;
|
||||
{ U32 const litlen = opt[cur-1].litlen + 1;
|
||||
int const price = opt[cur-1].price
|
||||
+ (int)ZSTD_rawLiteralsCost(ip+cur-1, 1, optStatePtr, optLevel)
|
||||
+ (int)ZSTD_litLengthPrice(litlen, optStatePtr, optLevel)
|
||||
- (int)ZSTD_litLengthPrice(litlen-1, optStatePtr, optLevel);
|
||||
+ LIT_PRICE(ip+cur-1)
|
||||
+ LL_INCPRICE(litlen);
|
||||
assert(price < 1000000000); /* overflow check */
|
||||
if (price <= opt[cur].price) {
|
||||
ZSTD_optimal_t const prevMatch = opt[cur];
|
||||
DEBUGLOG(7, "cPos:%zi==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)",
|
||||
inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen,
|
||||
opt[cur-1].rep[0], opt[cur-1].rep[1], opt[cur-1].rep[2]);
|
||||
opt[cur].mlen = 0;
|
||||
opt[cur].off = 0;
|
||||
opt[cur] = opt[cur-1];
|
||||
opt[cur].litlen = litlen;
|
||||
opt[cur].price = price;
|
||||
if ( (optLevel >= 1) /* additional check only for higher modes */
|
||||
&& (prevMatch.litlen == 0) /* replace a match */
|
||||
&& (LL_INCPRICE(1) < 0) /* ll1 is cheaper than ll0 */
|
||||
&& LIKELY(ip + cur < iend)
|
||||
) {
|
||||
/* check next position, in case it would be cheaper */
|
||||
int with1literal = prevMatch.price + LIT_PRICE(ip+cur) + LL_INCPRICE(1);
|
||||
int withMoreLiterals = price + LIT_PRICE(ip+cur) + LL_INCPRICE(litlen+1);
|
||||
DEBUGLOG(7, "then at next rPos %u : match+1lit %.2f vs %ulits %.2f",
|
||||
cur+1, ZSTD_fCost(with1literal), litlen+1, ZSTD_fCost(withMoreLiterals));
|
||||
if ( (with1literal < withMoreLiterals)
|
||||
&& (with1literal < opt[cur+1].price) ) {
|
||||
/* update offset history - before it disappears */
|
||||
U32 const prev = cur - prevMatch.mlen;
|
||||
repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, prevMatch.off, opt[prev].litlen==0);
|
||||
assert(cur >= prevMatch.mlen);
|
||||
DEBUGLOG(7, "==> match+1lit is cheaper (%.2f < %.2f) (hist:%u,%u,%u) !",
|
||||
ZSTD_fCost(with1literal), ZSTD_fCost(withMoreLiterals),
|
||||
newReps.rep[0], newReps.rep[1], newReps.rep[2] );
|
||||
opt[cur+1] = prevMatch; /* mlen & offbase */
|
||||
ZSTD_memcpy(opt[cur+1].rep, &newReps, sizeof(repcodes_t));
|
||||
opt[cur+1].litlen = 1;
|
||||
opt[cur+1].price = with1literal;
|
||||
if (last_pos < cur+1) last_pos = cur+1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
|
||||
inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
|
||||
opt[cur].rep[0], opt[cur].rep[1], opt[cur].rep[2]);
|
||||
DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f)",
|
||||
inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price));
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the repcodes of the current position. We must do it here
|
||||
* because we rely on the repcodes of the 2nd to last sequence being
|
||||
* correct to set the next chunks repcodes during the backward
|
||||
* traversal.
|
||||
/* Offset history is not updated during match comparison.
|
||||
* Do it here, now that the match is selected and confirmed.
|
||||
*/
|
||||
ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(repcodes_t));
|
||||
assert(cur >= opt[cur].mlen);
|
||||
if (opt[cur].mlen != 0) {
|
||||
if (opt[cur].litlen == 0) {
|
||||
/* just finished a match => alter offset history */
|
||||
U32 const prev = cur - opt[cur].mlen;
|
||||
repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
|
||||
repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[prev].litlen==0);
|
||||
ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
|
||||
} else {
|
||||
ZSTD_memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
|
||||
}
|
||||
|
||||
/* last match must start at a minimum distance of 8 from oend */
|
||||
@@ -1217,15 +1264,14 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
|
||||
if ( (optLevel==0) /*static_test*/
|
||||
&& (opt[cur+1].price <= opt[cur].price + (BITCOST_MULTIPLIER/2)) ) {
|
||||
DEBUGLOG(7, "move to next rPos:%u : price is <=", cur+1);
|
||||
DEBUGLOG(7, "skip current position : next rPos(%u) price is cheaper", cur+1);
|
||||
continue; /* skip unpromising positions; about ~+6% speed, -0.01 ratio */
|
||||
}
|
||||
|
||||
assert(opt[cur].price >= 0);
|
||||
{ U32 const ll0 = (opt[cur].mlen != 0);
|
||||
U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
|
||||
U32 const previousPrice = (U32)opt[cur].price;
|
||||
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
|
||||
{ U32 const ll0 = (opt[cur].litlen == 0);
|
||||
int const previousPrice = opt[cur].price;
|
||||
int const basePrice = previousPrice + LL_PRICE(0);
|
||||
U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, inr, iend, opt[cur].rep, ll0, minMatch);
|
||||
U32 matchNb;
|
||||
|
||||
@@ -1237,18 +1283,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
continue;
|
||||
}
|
||||
|
||||
{ U32 const maxML = matches[nbMatches-1].len;
|
||||
DEBUGLOG(7, "cPos:%zi==rPos:%u, found %u matches, of maxLength=%u",
|
||||
inr-istart, cur, nbMatches, maxML);
|
||||
{ U32 const longestML = matches[nbMatches-1].len;
|
||||
DEBUGLOG(7, "cPos:%zi==rPos:%u, found %u matches, of longest ML=%u",
|
||||
inr-istart, cur, nbMatches, longestML);
|
||||
|
||||
if ( (maxML > sufficient_len)
|
||||
|| (cur + maxML >= ZSTD_OPT_NUM) ) {
|
||||
lastSequence.mlen = maxML;
|
||||
lastSequence.off = matches[nbMatches-1].off;
|
||||
lastSequence.litlen = litlen;
|
||||
cur -= (opt[cur].mlen==0) ? opt[cur].litlen : 0; /* last sequence is actually only literals, fix cur to last match - note : may underflow, in which case, it's first sequence, and it's okay */
|
||||
last_pos = cur + ZSTD_totalLen(lastSequence);
|
||||
if (cur > ZSTD_OPT_NUM) cur = 0; /* underflow => first match */
|
||||
if ( (longestML > sufficient_len)
|
||||
|| (cur + longestML >= ZSTD_OPT_NUM)
|
||||
|| (ip + cur + longestML >= iend) ) {
|
||||
lastStretch.mlen = longestML;
|
||||
lastStretch.off = matches[nbMatches-1].off;
|
||||
lastStretch.litlen = 0;
|
||||
last_pos = cur + longestML;
|
||||
goto _shortestPath;
|
||||
} }
|
||||
|
||||
@@ -1260,19 +1305,24 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
U32 mlen;
|
||||
|
||||
DEBUGLOG(7, "testing match %u => offBase=%4u, mlen=%2u, llen=%2u",
|
||||
matchNb, matches[matchNb].off, lastML, litlen);
|
||||
matchNb, matches[matchNb].off, lastML, opt[cur].litlen);
|
||||
|
||||
for (mlen = lastML; mlen >= startML; mlen--) { /* scan downward */
|
||||
U32 const pos = cur + mlen;
|
||||
int const price = (int)basePrice + (int)ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel);
|
||||
int const price = basePrice + (int)ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel);
|
||||
|
||||
if ((pos > last_pos) || (price < opt[pos].price)) {
|
||||
DEBUGLOG(7, "rPos:%u (ml=%2u) => new better price (%.2f<%.2f)",
|
||||
pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
|
||||
while (last_pos < pos) { opt[last_pos+1].price = ZSTD_MAX_PRICE; last_pos++; } /* fill empty positions */
|
||||
while (last_pos < pos) {
|
||||
/* fill empty positions, for future comparisons */
|
||||
last_pos++;
|
||||
opt[last_pos].price = ZSTD_MAX_PRICE;
|
||||
opt[last_pos].litlen = !0; /* just needs to be != 0, to mean "not an end of match" */
|
||||
}
|
||||
opt[pos].mlen = mlen;
|
||||
opt[pos].off = offset;
|
||||
opt[pos].litlen = litlen;
|
||||
opt[pos].litlen = 0;
|
||||
opt[pos].price = price;
|
||||
} else {
|
||||
DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
|
||||
@@ -1280,47 +1330,81 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
if (optLevel==0) break; /* early update abort; gets ~+10% speed for about -0.01 ratio loss */
|
||||
}
|
||||
} } }
|
||||
opt[last_pos+1].price = ZSTD_MAX_PRICE;
|
||||
} /* for (cur = 1; cur <= last_pos; cur++) */
|
||||
|
||||
lastSequence = opt[last_pos];
|
||||
cur = last_pos > ZSTD_totalLen(lastSequence) ? last_pos - ZSTD_totalLen(lastSequence) : 0; /* single sequence, and it starts before `ip` */
|
||||
assert(cur < ZSTD_OPT_NUM); /* control overflow*/
|
||||
lastStretch = opt[last_pos];
|
||||
assert(cur >= lastStretch.mlen);
|
||||
cur = last_pos - lastStretch.mlen;
|
||||
|
||||
_shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
||||
assert(opt[0].mlen == 0);
|
||||
assert(last_pos >= lastStretch.mlen);
|
||||
assert(cur == last_pos - lastStretch.mlen);
|
||||
|
||||
/* Set the next chunk's repcodes based on the repcodes of the beginning
|
||||
* of the last match, and the last sequence. This avoids us having to
|
||||
* update them while traversing the sequences.
|
||||
*/
|
||||
if (lastSequence.mlen != 0) {
|
||||
repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
|
||||
ZSTD_memcpy(rep, &reps, sizeof(reps));
|
||||
if (lastStretch.mlen==0) {
|
||||
/* no solution : all matches have been converted into literals */
|
||||
assert(lastStretch.litlen == (ip - anchor) + last_pos);
|
||||
ip += last_pos;
|
||||
continue;
|
||||
}
|
||||
assert(lastStretch.off > 0);
|
||||
|
||||
/* Update offset history */
|
||||
if (lastStretch.litlen == 0) {
|
||||
/* finishing on a match : update offset history */
|
||||
repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastStretch.off, opt[cur].litlen==0);
|
||||
ZSTD_memcpy(rep, &reps, sizeof(repcodes_t));
|
||||
} else {
|
||||
ZSTD_memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
|
||||
ZSTD_memcpy(rep, lastStretch.rep, sizeof(repcodes_t));
|
||||
assert(cur >= lastStretch.litlen);
|
||||
cur -= lastStretch.litlen;
|
||||
}
|
||||
|
||||
{ U32 const storeEnd = cur + 1;
|
||||
/* Let's write the shortest path solution.
|
||||
* It is stored in @opt in reverse order,
|
||||
* starting from @storeEnd (==cur+2),
|
||||
* effectively partially @opt overwriting.
|
||||
* Content is changed too:
|
||||
* - So far, @opt stored stretches, aka a match followed by literals
|
||||
* - Now, it will store sequences, aka literals followed by a match
|
||||
*/
|
||||
{ U32 const storeEnd = cur + 2;
|
||||
U32 storeStart = storeEnd;
|
||||
U32 seqPos = cur;
|
||||
U32 stretchPos = cur;
|
||||
|
||||
DEBUGLOG(6, "start reverse traversal (last_pos:%u, cur:%u)",
|
||||
last_pos, cur); (void)last_pos;
|
||||
assert(storeEnd < ZSTD_OPT_NUM);
|
||||
DEBUGLOG(6, "last sequence copied into pos=%u (llen=%u,mlen=%u,ofc=%u)",
|
||||
storeEnd, lastSequence.litlen, lastSequence.mlen, lastSequence.off);
|
||||
opt[storeEnd] = lastSequence;
|
||||
while (seqPos > 0) {
|
||||
U32 const backDist = ZSTD_totalLen(opt[seqPos]);
|
||||
assert(storeEnd < ZSTD_OPT_SIZE);
|
||||
DEBUGLOG(6, "last stretch copied into pos=%u (llen=%u,mlen=%u,ofc=%u)",
|
||||
storeEnd, lastStretch.litlen, lastStretch.mlen, lastStretch.off);
|
||||
if (lastStretch.litlen > 0) {
|
||||
/* last "sequence" is unfinished: just a bunch of literals */
|
||||
opt[storeEnd].litlen = lastStretch.litlen;
|
||||
opt[storeEnd].mlen = 0;
|
||||
storeStart = storeEnd-1;
|
||||
opt[storeStart] = lastStretch;
|
||||
} {
|
||||
opt[storeEnd] = lastStretch; /* note: litlen will be fixed */
|
||||
storeStart = storeEnd;
|
||||
}
|
||||
while (1) {
|
||||
ZSTD_optimal_t nextStretch = opt[stretchPos];
|
||||
opt[storeStart].litlen = nextStretch.litlen;
|
||||
DEBUGLOG(6, "selected sequence (llen=%u,mlen=%u,ofc=%u)",
|
||||
opt[storeStart].litlen, opt[storeStart].mlen, opt[storeStart].off);
|
||||
if (nextStretch.mlen == 0) {
|
||||
/* reaching beginning of segment */
|
||||
break;
|
||||
}
|
||||
storeStart--;
|
||||
DEBUGLOG(6, "sequence from rPos=%u copied into pos=%u (llen=%u,mlen=%u,ofc=%u)",
|
||||
seqPos, storeStart, opt[seqPos].litlen, opt[seqPos].mlen, opt[seqPos].off);
|
||||
opt[storeStart] = opt[seqPos];
|
||||
seqPos = (seqPos > backDist) ? seqPos - backDist : 0;
|
||||
opt[storeStart] = nextStretch; /* note: litlen will be fixed */
|
||||
assert(nextStretch.litlen + nextStretch.mlen <= stretchPos);
|
||||
stretchPos -= nextStretch.litlen + nextStretch.mlen;
|
||||
}
|
||||
|
||||
/* save sequences */
|
||||
DEBUGLOG(6, "sending selected sequences into seqStore")
|
||||
DEBUGLOG(6, "sending selected sequences into seqStore");
|
||||
{ U32 storePos;
|
||||
for (storePos=storeStart; storePos <= storeEnd; storePos++) {
|
||||
U32 const llen = opt[storePos].litlen;
|
||||
@@ -1342,6 +1426,9 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
||||
anchor += advance;
|
||||
ip = anchor;
|
||||
} }
|
||||
DEBUGLOG(7, "new offset history : %u, %u, %u", rep[0], rep[1], rep[2]);
|
||||
|
||||
/* update all costs */
|
||||
ZSTD_setBasePrices(optStatePtr, optLevel);
|
||||
}
|
||||
} /* while (ip < ilimit) */
|
||||
@@ -1388,11 +1475,12 @@ size_t ZSTD_compressBlock_btopt(
|
||||
* only works on first block, with no dictionary and no ldm.
|
||||
* this function cannot error out, its narrow contract must be respected.
|
||||
*/
|
||||
static void
|
||||
ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||
seqStore_t* seqStore,
|
||||
U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||
seqStore_t* seqStore,
|
||||
U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */
|
||||
ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep));
|
||||
@@ -1436,7 +1524,7 @@ size_t ZSTD_compressBlock_btultra2(
|
||||
* Consequently, this can only work if no data has been previously loaded in tables,
|
||||
* aka, no dictionary, no prefix, no ldm preprocessing.
|
||||
* The compression ratio gain is generally small (~0.5% on first block),
|
||||
** the cost is 2x cpu time on first block. */
|
||||
* the cost is 2x cpu time on first block. */
|
||||
assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
|
||||
if ( (ms->opt.litLengthSum==0) /* first block */
|
||||
&& (seqStore->sequences == seqStore->sequencesStart) /* no ldm */
|
||||
|
||||
@@ -15,17 +15,13 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* ====== Constants ====== */
|
||||
#define ZSTDMT_OVERLAPLOG_DEFAULT 0
|
||||
|
||||
|
||||
/* ====== Dependencies ====== */
|
||||
#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
|
||||
#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
|
||||
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset, INT_MAX, UINT_MAX */
|
||||
#include "../common/mem.h" /* MEM_STATIC */
|
||||
#include "../common/pool.h" /* threadpool */
|
||||
#include "../common/threading.h" /* mutex */
|
||||
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
||||
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
||||
#include "zstd_ldm.h"
|
||||
#include "zstdmt_compress.h"
|
||||
|
||||
@@ -44,12 +40,13 @@
|
||||
# include <unistd.h>
|
||||
# include <sys/times.h>
|
||||
|
||||
# define DEBUG_PRINTHEX(l,p,n) { \
|
||||
unsigned debug_u; \
|
||||
for (debug_u=0; debug_u<(n); debug_u++) \
|
||||
RAWLOG(l, "%02X ", ((const unsigned char*)(p))[debug_u]); \
|
||||
RAWLOG(l, " \n"); \
|
||||
}
|
||||
# define DEBUG_PRINTHEX(l,p,n) \
|
||||
do { \
|
||||
unsigned debug_u; \
|
||||
for (debug_u=0; debug_u<(n); debug_u++) \
|
||||
RAWLOG(l, "%02X ", ((const unsigned char*)(p))[debug_u]); \
|
||||
RAWLOG(l, " \n"); \
|
||||
} while (0)
|
||||
|
||||
static unsigned long long GetCurrentClockTimeMicroseconds(void)
|
||||
{
|
||||
@@ -61,25 +58,28 @@ static unsigned long long GetCurrentClockTimeMicroseconds(void)
|
||||
} }
|
||||
|
||||
#define MUTEX_WAIT_TIME_DLEVEL 6
|
||||
#define ZSTD_PTHREAD_MUTEX_LOCK(mutex) { \
|
||||
if (DEBUGLEVEL >= MUTEX_WAIT_TIME_DLEVEL) { \
|
||||
unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \
|
||||
ZSTD_pthread_mutex_lock(mutex); \
|
||||
{ unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \
|
||||
unsigned long long const elapsedTime = (afterTime-beforeTime); \
|
||||
if (elapsedTime > 1000) { /* or whatever threshold you like; I'm using 1 millisecond here */ \
|
||||
DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
|
||||
elapsedTime, #mutex); \
|
||||
} } \
|
||||
} else { \
|
||||
ZSTD_pthread_mutex_lock(mutex); \
|
||||
} \
|
||||
}
|
||||
#define ZSTD_PTHREAD_MUTEX_LOCK(mutex) \
|
||||
do { \
|
||||
if (DEBUGLEVEL >= MUTEX_WAIT_TIME_DLEVEL) { \
|
||||
unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \
|
||||
ZSTD_pthread_mutex_lock(mutex); \
|
||||
{ unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \
|
||||
unsigned long long const elapsedTime = (afterTime-beforeTime); \
|
||||
if (elapsedTime > 1000) { \
|
||||
/* or whatever threshold you like; I'm using 1 millisecond here */ \
|
||||
DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, \
|
||||
"Thread took %llu microseconds to acquire mutex %s \n", \
|
||||
elapsedTime, #mutex); \
|
||||
} } \
|
||||
} else { \
|
||||
ZSTD_pthread_mutex_lock(mutex); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
# define ZSTD_PTHREAD_MUTEX_LOCK(m) ZSTD_pthread_mutex_lock(m)
|
||||
# define DEBUG_PRINTHEX(l,p,n) {}
|
||||
# define DEBUG_PRINTHEX(l,p,n) do { } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -100,18 +100,39 @@ typedef struct ZSTDMT_bufferPool_s {
|
||||
unsigned totalBuffers;
|
||||
unsigned nbBuffers;
|
||||
ZSTD_customMem cMem;
|
||||
buffer_t bTable[1]; /* variable size */
|
||||
buffer_t* buffers;
|
||||
} ZSTDMT_bufferPool;
|
||||
|
||||
static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
|
||||
{
|
||||
DEBUGLOG(3, "ZSTDMT_freeBufferPool (address:%08X)", (U32)(size_t)bufPool);
|
||||
if (!bufPool) return; /* compatibility with free on NULL */
|
||||
if (bufPool->buffers) {
|
||||
unsigned u;
|
||||
for (u=0; u<bufPool->totalBuffers; u++) {
|
||||
DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->buffers[u].start);
|
||||
ZSTD_customFree(bufPool->buffers[u].start, bufPool->cMem);
|
||||
}
|
||||
ZSTD_customFree(bufPool->buffers, bufPool->cMem);
|
||||
}
|
||||
ZSTD_pthread_mutex_destroy(&bufPool->poolMutex);
|
||||
ZSTD_customFree(bufPool, bufPool->cMem);
|
||||
}
|
||||
|
||||
static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_customMem cMem)
|
||||
{
|
||||
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_customCalloc(
|
||||
sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
|
||||
ZSTDMT_bufferPool* const bufPool =
|
||||
(ZSTDMT_bufferPool*)ZSTD_customCalloc(sizeof(ZSTDMT_bufferPool), cMem);
|
||||
if (bufPool==NULL) return NULL;
|
||||
if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) {
|
||||
ZSTD_customFree(bufPool, cMem);
|
||||
return NULL;
|
||||
}
|
||||
bufPool->buffers = (buffer_t*)ZSTD_customCalloc(maxNbBuffers * sizeof(buffer_t), cMem);
|
||||
if (bufPool->buffers==NULL) {
|
||||
ZSTDMT_freeBufferPool(bufPool);
|
||||
return NULL;
|
||||
}
|
||||
bufPool->bufferSize = 64 KB;
|
||||
bufPool->totalBuffers = maxNbBuffers;
|
||||
bufPool->nbBuffers = 0;
|
||||
@@ -119,32 +140,19 @@ static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_cu
|
||||
return bufPool;
|
||||
}
|
||||
|
||||
static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
|
||||
{
|
||||
unsigned u;
|
||||
DEBUGLOG(3, "ZSTDMT_freeBufferPool (address:%08X)", (U32)(size_t)bufPool);
|
||||
if (!bufPool) return; /* compatibility with free on NULL */
|
||||
for (u=0; u<bufPool->totalBuffers; u++) {
|
||||
DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->bTable[u].start);
|
||||
ZSTD_customFree(bufPool->bTable[u].start, bufPool->cMem);
|
||||
}
|
||||
ZSTD_pthread_mutex_destroy(&bufPool->poolMutex);
|
||||
ZSTD_customFree(bufPool, bufPool->cMem);
|
||||
}
|
||||
|
||||
/* only works at initialization, not during compression */
|
||||
static size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool)
|
||||
{
|
||||
size_t const poolSize = sizeof(*bufPool)
|
||||
+ (bufPool->totalBuffers - 1) * sizeof(buffer_t);
|
||||
size_t const poolSize = sizeof(*bufPool);
|
||||
size_t const arraySize = bufPool->totalBuffers * sizeof(buffer_t);
|
||||
unsigned u;
|
||||
size_t totalBufferSize = 0;
|
||||
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
|
||||
for (u=0; u<bufPool->totalBuffers; u++)
|
||||
totalBufferSize += bufPool->bTable[u].capacity;
|
||||
totalBufferSize += bufPool->buffers[u].capacity;
|
||||
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
||||
|
||||
return poolSize + totalBufferSize;
|
||||
return poolSize + arraySize + totalBufferSize;
|
||||
}
|
||||
|
||||
/* ZSTDMT_setBufferSize() :
|
||||
@@ -187,9 +195,9 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
|
||||
DEBUGLOG(5, "ZSTDMT_getBuffer: bSize = %u", (U32)bufPool->bufferSize);
|
||||
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
|
||||
if (bufPool->nbBuffers) { /* try to use an existing buffer */
|
||||
buffer_t const buf = bufPool->bTable[--(bufPool->nbBuffers)];
|
||||
buffer_t const buf = bufPool->buffers[--(bufPool->nbBuffers)];
|
||||
size_t const availBufferSize = buf.capacity;
|
||||
bufPool->bTable[bufPool->nbBuffers] = g_nullBuffer;
|
||||
bufPool->buffers[bufPool->nbBuffers] = g_nullBuffer;
|
||||
if ((availBufferSize >= bSize) & ((availBufferSize>>3) <= bSize)) {
|
||||
/* large enough, but not too much */
|
||||
DEBUGLOG(5, "ZSTDMT_getBuffer: provide buffer %u of size %u",
|
||||
@@ -250,14 +258,14 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
|
||||
if (buf.start == NULL) return; /* compatible with release on NULL */
|
||||
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
|
||||
if (bufPool->nbBuffers < bufPool->totalBuffers) {
|
||||
bufPool->bTable[bufPool->nbBuffers++] = buf; /* stored for later use */
|
||||
bufPool->buffers[bufPool->nbBuffers++] = buf; /* stored for later use */
|
||||
DEBUGLOG(5, "ZSTDMT_releaseBuffer: stored buffer of size %u in slot %u",
|
||||
(U32)buf.capacity, (U32)(bufPool->nbBuffers-1));
|
||||
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
||||
return;
|
||||
}
|
||||
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
||||
/* Reached bufferPool capacity (should not happen) */
|
||||
/* Reached bufferPool capacity (note: should not happen) */
|
||||
DEBUGLOG(5, "ZSTDMT_releaseBuffer: pool capacity reached => freeing ");
|
||||
ZSTD_customFree(buf.start, bufPool->cMem);
|
||||
}
|
||||
@@ -350,16 +358,20 @@ typedef struct {
|
||||
int totalCCtx;
|
||||
int availCCtx;
|
||||
ZSTD_customMem cMem;
|
||||
ZSTD_CCtx* cctx[1]; /* variable size */
|
||||
ZSTD_CCtx** cctxs;
|
||||
} ZSTDMT_CCtxPool;
|
||||
|
||||
/* note : all CCtx borrowed from the pool should be released back to the pool _before_ freeing the pool */
|
||||
/* note : all CCtx borrowed from the pool must be reverted back to the pool _before_ freeing the pool */
|
||||
static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
|
||||
{
|
||||
int cid;
|
||||
for (cid=0; cid<pool->totalCCtx; cid++)
|
||||
ZSTD_freeCCtx(pool->cctx[cid]); /* note : compatible with free on NULL */
|
||||
if (!pool) return;
|
||||
ZSTD_pthread_mutex_destroy(&pool->poolMutex);
|
||||
if (pool->cctxs) {
|
||||
int cid;
|
||||
for (cid=0; cid<pool->totalCCtx; cid++)
|
||||
ZSTD_freeCCtx(pool->cctxs[cid]); /* free compatible with NULL */
|
||||
ZSTD_customFree(pool->cctxs, pool->cMem);
|
||||
}
|
||||
ZSTD_customFree(pool, pool->cMem);
|
||||
}
|
||||
|
||||
@@ -368,19 +380,24 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
|
||||
static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers,
|
||||
ZSTD_customMem cMem)
|
||||
{
|
||||
ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_customCalloc(
|
||||
sizeof(ZSTDMT_CCtxPool) + (nbWorkers-1)*sizeof(ZSTD_CCtx*), cMem);
|
||||
ZSTDMT_CCtxPool* const cctxPool =
|
||||
(ZSTDMT_CCtxPool*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtxPool), cMem);
|
||||
assert(nbWorkers > 0);
|
||||
if (!cctxPool) return NULL;
|
||||
if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
|
||||
ZSTD_customFree(cctxPool, cMem);
|
||||
return NULL;
|
||||
}
|
||||
cctxPool->cMem = cMem;
|
||||
cctxPool->totalCCtx = nbWorkers;
|
||||
cctxPool->cctxs = (ZSTD_CCtx**)ZSTD_customCalloc(nbWorkers * sizeof(ZSTD_CCtx*), cMem);
|
||||
if (!cctxPool->cctxs) {
|
||||
ZSTDMT_freeCCtxPool(cctxPool);
|
||||
return NULL;
|
||||
}
|
||||
cctxPool->cMem = cMem;
|
||||
cctxPool->cctxs[0] = ZSTD_createCCtx_advanced(cMem);
|
||||
if (!cctxPool->cctxs[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; }
|
||||
cctxPool->availCCtx = 1; /* at least one cctx for single-thread mode */
|
||||
cctxPool->cctx[0] = ZSTD_createCCtx_advanced(cMem);
|
||||
if (!cctxPool->cctx[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; }
|
||||
DEBUGLOG(3, "cctxPool created, with %u workers", nbWorkers);
|
||||
return cctxPool;
|
||||
}
|
||||
@@ -402,16 +419,16 @@ static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
|
||||
{
|
||||
ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);
|
||||
{ unsigned const nbWorkers = cctxPool->totalCCtx;
|
||||
size_t const poolSize = sizeof(*cctxPool)
|
||||
+ (nbWorkers-1) * sizeof(ZSTD_CCtx*);
|
||||
unsigned u;
|
||||
size_t const poolSize = sizeof(*cctxPool);
|
||||
size_t const arraySize = cctxPool->totalCCtx * sizeof(ZSTD_CCtx*);
|
||||
size_t totalCCtxSize = 0;
|
||||
unsigned u;
|
||||
for (u=0; u<nbWorkers; u++) {
|
||||
totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctx[u]);
|
||||
totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctxs[u]);
|
||||
}
|
||||
ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
|
||||
assert(nbWorkers > 0);
|
||||
return poolSize + totalCCtxSize;
|
||||
return poolSize + arraySize + totalCCtxSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,7 +438,7 @@ static ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* cctxPool)
|
||||
ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);
|
||||
if (cctxPool->availCCtx) {
|
||||
cctxPool->availCCtx--;
|
||||
{ ZSTD_CCtx* const cctx = cctxPool->cctx[cctxPool->availCCtx];
|
||||
{ ZSTD_CCtx* const cctx = cctxPool->cctxs[cctxPool->availCCtx];
|
||||
ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
|
||||
return cctx;
|
||||
} }
|
||||
@@ -435,7 +452,7 @@ static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)
|
||||
if (cctx==NULL) return; /* compatibility with release on NULL */
|
||||
ZSTD_pthread_mutex_lock(&pool->poolMutex);
|
||||
if (pool->availCCtx < pool->totalCCtx)
|
||||
pool->cctx[pool->availCCtx++] = cctx;
|
||||
pool->cctxs[pool->availCCtx++] = cctx;
|
||||
else {
|
||||
/* pool overflow : should not happen, since totalCCtx==nbWorkers */
|
||||
DEBUGLOG(4, "CCtx pool overflow : free cctx");
|
||||
@@ -654,12 +671,13 @@ typedef struct {
|
||||
unsigned frameChecksumNeeded; /* used only by mtctx */
|
||||
} ZSTDMT_jobDescription;
|
||||
|
||||
#define JOB_ERROR(e) { \
|
||||
ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex); \
|
||||
job->cSize = e; \
|
||||
ZSTD_pthread_mutex_unlock(&job->job_mutex); \
|
||||
goto _endJob; \
|
||||
}
|
||||
#define JOB_ERROR(e) \
|
||||
do { \
|
||||
ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex); \
|
||||
job->cSize = e; \
|
||||
ZSTD_pthread_mutex_unlock(&job->job_mutex); \
|
||||
goto _endJob; \
|
||||
} while (0)
|
||||
|
||||
/* ZSTDMT_compressionJob() is a POOL_function type */
|
||||
static void ZSTDMT_compressionJob(void* jobDescription)
|
||||
@@ -1088,7 +1106,7 @@ ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx)
|
||||
{ unsigned jobNb;
|
||||
unsigned lastJobNb = mtctx->nextJobID + mtctx->jobReady; assert(mtctx->jobReady <= 1);
|
||||
DEBUGLOG(6, "ZSTDMT_getFrameProgression: jobs: from %u to <%u (jobReady:%u)",
|
||||
mtctx->doneJobID, lastJobNb, mtctx->jobReady)
|
||||
mtctx->doneJobID, lastJobNb, mtctx->jobReady);
|
||||
for (jobNb = mtctx->doneJobID ; jobNb < lastJobNb ; jobNb++) {
|
||||
unsigned const wJobID = jobNb & mtctx->jobIDMask;
|
||||
ZSTDMT_jobDescription* jobPtr = &mtctx->jobs[wJobID];
|
||||
|
||||
+188
-126
@@ -34,6 +34,12 @@
|
||||
* Macros
|
||||
****************************************************************/
|
||||
|
||||
#ifdef HUF_DISABLE_FAST_DECODE
|
||||
# define HUF_ENABLE_FAST_DECODE 0
|
||||
#else
|
||||
# define HUF_ENABLE_FAST_DECODE 1
|
||||
#endif
|
||||
|
||||
/* These two optional macros force the use one way or another of the two
|
||||
* Huffman decompression implementations. You can't force in both directions
|
||||
* at the same time.
|
||||
@@ -158,17 +164,18 @@ static size_t HUF_initFastDStream(BYTE const* ip) {
|
||||
* op [in/out] - The output pointers, must be updated to reflect what is written.
|
||||
* bits [in/out] - The bitstream containers, must be updated to reflect the current state.
|
||||
* dt [in] - The decoding table.
|
||||
* ilimit [in] - The input limit, stop when any input pointer is below ilimit.
|
||||
* ilowest [in] - The beginning of the valid range of the input. Decoders may read
|
||||
* down to this pointer. It may be below iend[0].
|
||||
* oend [in] - The end of the output stream. op[3] must not cross oend.
|
||||
* iend [in] - The end of each input stream. ip[i] may cross iend[i],
|
||||
* as long as it is above ilimit, but that indicates corruption.
|
||||
* as long as it is above ilowest, but that indicates corruption.
|
||||
*/
|
||||
typedef struct {
|
||||
BYTE const* ip[4];
|
||||
BYTE* op[4];
|
||||
U64 bits[4];
|
||||
void const* dt;
|
||||
BYTE const* ilimit;
|
||||
BYTE const* ilowest;
|
||||
BYTE* oend;
|
||||
BYTE const* iend[4];
|
||||
} HUF_DecompressFastArgs;
|
||||
@@ -186,9 +193,9 @@ static size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* ds
|
||||
void const* dt = DTable + 1;
|
||||
U32 const dtLog = HUF_getDTableDesc(DTable).tableLog;
|
||||
|
||||
const BYTE* const ilimit = (const BYTE*)src + 6 + 8;
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
|
||||
BYTE* const oend = (BYTE*)dst + dstSize;
|
||||
BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize);
|
||||
|
||||
/* The fast decoding loop assumes 64-bit little-endian.
|
||||
* This condition is false on x32.
|
||||
@@ -196,6 +203,11 @@ static size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* ds
|
||||
if (!MEM_isLittleEndian() || MEM_32bits())
|
||||
return 0;
|
||||
|
||||
/* Avoid nullptr addition */
|
||||
if (dstSize == 0)
|
||||
return 0;
|
||||
assert(dst != NULL);
|
||||
|
||||
/* strict minimum : jump table + 1 byte per stream */
|
||||
if (srcSize < 10)
|
||||
return ERROR(corruption_detected);
|
||||
@@ -209,7 +221,6 @@ static size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* ds
|
||||
|
||||
/* Read the jump table. */
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
size_t const length1 = MEM_readLE16(istart);
|
||||
size_t const length2 = MEM_readLE16(istart+2);
|
||||
size_t const length3 = MEM_readLE16(istart+4);
|
||||
@@ -221,10 +232,8 @@ static size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* ds
|
||||
|
||||
/* HUF_initFastDStream() requires this, and this small of an input
|
||||
* won't benefit from the ASM loop anyways.
|
||||
* length1 must be >= 16 so that ip[0] >= ilimit before the loop
|
||||
* starts.
|
||||
*/
|
||||
if (length1 < 16 || length2 < 8 || length3 < 8 || length4 < 8)
|
||||
if (length1 < 8 || length2 < 8 || length3 < 8 || length4 < 8)
|
||||
return 0;
|
||||
if (length4 > srcSize) return ERROR(corruption_detected); /* overflow */
|
||||
}
|
||||
@@ -256,11 +265,12 @@ static size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* ds
|
||||
args->bits[2] = HUF_initFastDStream(args->ip[2]);
|
||||
args->bits[3] = HUF_initFastDStream(args->ip[3]);
|
||||
|
||||
/* If ip[] >= ilimit, it is guaranteed to be safe to
|
||||
* reload bits[]. It may be beyond its section, but is
|
||||
* guaranteed to be valid (>= istart).
|
||||
*/
|
||||
args->ilimit = ilimit;
|
||||
/* The decoders must be sure to never read beyond ilowest.
|
||||
* This is lower than iend[0], but allowing decoders to read
|
||||
* down to ilowest can allow an extra iteration or two in the
|
||||
* fast loop.
|
||||
*/
|
||||
args->ilowest = istart;
|
||||
|
||||
args->oend = oend;
|
||||
args->dt = dt;
|
||||
@@ -285,13 +295,31 @@ static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressFastArg
|
||||
assert(sizeof(size_t) == 8);
|
||||
bit->bitContainer = MEM_readLEST(args->ip[stream]);
|
||||
bit->bitsConsumed = ZSTD_countTrailingZeros64(args->bits[stream]);
|
||||
bit->start = (const char*)args->iend[0];
|
||||
bit->start = (const char*)args->ilowest;
|
||||
bit->limitPtr = bit->start + sizeof(size_t);
|
||||
bit->ptr = (const char*)args->ip[stream];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calls X(N) for each stream 0, 1, 2, 3. */
|
||||
#define HUF_4X_FOR_EACH_STREAM(X) \
|
||||
do { \
|
||||
X(0); \
|
||||
X(1); \
|
||||
X(2); \
|
||||
X(3); \
|
||||
} while (0)
|
||||
|
||||
/* Calls X(N, var) for each stream 0, 1, 2, 3. */
|
||||
#define HUF_4X_FOR_EACH_STREAM_WITH_VAR(X, var) \
|
||||
do { \
|
||||
X(0, (var)); \
|
||||
X(1, (var)); \
|
||||
X(2, (var)); \
|
||||
X(3, (var)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
|
||||
@@ -500,15 +528,19 @@ HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog
|
||||
}
|
||||
|
||||
#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \
|
||||
*ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog)
|
||||
do { *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog); } while (0)
|
||||
|
||||
#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr) \
|
||||
if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
|
||||
HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
|
||||
#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr) \
|
||||
do { \
|
||||
if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
|
||||
HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \
|
||||
} while (0)
|
||||
|
||||
#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \
|
||||
if (MEM_64bits()) \
|
||||
HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
|
||||
#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \
|
||||
do { \
|
||||
if (MEM_64bits()) \
|
||||
HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \
|
||||
} while (0)
|
||||
|
||||
HINT_INLINE size_t
|
||||
HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog)
|
||||
@@ -546,7 +578,7 @@ HUF_decompress1X1_usingDTable_internal_body(
|
||||
const HUF_DTable* DTable)
|
||||
{
|
||||
BYTE* op = (BYTE*)dst;
|
||||
BYTE* const oend = op + dstSize;
|
||||
BYTE* const oend = ZSTD_maybeNullPtrAdd(op, dstSize);
|
||||
const void* dtPtr = DTable + 1;
|
||||
const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
|
||||
BIT_DStream_t bitD;
|
||||
@@ -574,6 +606,7 @@ HUF_decompress4X1_usingDTable_internal_body(
|
||||
{
|
||||
/* Check */
|
||||
if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
|
||||
if (dstSize < 6) return ERROR(corruption_detected); /* stream 4-split doesn't work */
|
||||
|
||||
{ const BYTE* const istart = (const BYTE*) cSrc;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
@@ -609,7 +642,7 @@ HUF_decompress4X1_usingDTable_internal_body(
|
||||
|
||||
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
||||
if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */
|
||||
if (dstSize < 6) return ERROR(corruption_detected); /* stream 4-split doesn't work */
|
||||
assert(dstSize >= 6); /* validated above */
|
||||
CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
|
||||
CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
|
||||
CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
|
||||
@@ -692,7 +725,7 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
BYTE* op[4];
|
||||
U16 const* const dtable = (U16 const*)args->dt;
|
||||
BYTE* const oend = args->oend;
|
||||
BYTE const* const ilimit = args->ilimit;
|
||||
BYTE const* const ilowest = args->ilowest;
|
||||
|
||||
/* Copy the arguments to local variables */
|
||||
ZSTD_memcpy(&bits, &args->bits, sizeof(bits));
|
||||
@@ -705,13 +738,12 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
for (;;) {
|
||||
BYTE* olimit;
|
||||
int stream;
|
||||
int symbol;
|
||||
|
||||
/* Assert loop preconditions */
|
||||
#ifndef NDEBUG
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
assert(op[stream] <= (stream == 3 ? oend : op[stream + 1]));
|
||||
assert(ip[stream] >= ilimit);
|
||||
assert(ip[stream] >= ilowest);
|
||||
}
|
||||
#endif
|
||||
/* Compute olimit */
|
||||
@@ -721,7 +753,7 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
/* Each iteration consumes up to 11 bits * 5 = 55 bits < 7 bytes
|
||||
* per stream.
|
||||
*/
|
||||
size_t const iiters = (size_t)(ip[0] - ilimit) / 7;
|
||||
size_t const iiters = (size_t)(ip[0] - ilowest) / 7;
|
||||
/* We can safely run iters iterations before running bounds checks */
|
||||
size_t const iters = MIN(oiters, iiters);
|
||||
size_t const symbols = iters * 5;
|
||||
@@ -732,8 +764,8 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
*/
|
||||
olimit = op[3] + symbols;
|
||||
|
||||
/* Exit fast decoding loop once we get close to the end. */
|
||||
if (op[3] + 20 > olimit)
|
||||
/* Exit fast decoding loop once we reach the end. */
|
||||
if (op[3] == olimit)
|
||||
break;
|
||||
|
||||
/* Exit the decoding loop if any input pointer has crossed the
|
||||
@@ -752,27 +784,42 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HUF_4X1_DECODE_SYMBOL(_stream, _symbol) \
|
||||
do { \
|
||||
int const index = (int)(bits[(_stream)] >> 53); \
|
||||
int const entry = (int)dtable[index]; \
|
||||
bits[(_stream)] <<= (entry & 0x3F); \
|
||||
op[(_stream)][(_symbol)] = (BYTE)((entry >> 8) & 0xFF); \
|
||||
} while (0)
|
||||
|
||||
#define HUF_4X1_RELOAD_STREAM(_stream) \
|
||||
do { \
|
||||
int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
|
||||
int const nbBits = ctz & 7; \
|
||||
int const nbBytes = ctz >> 3; \
|
||||
op[(_stream)] += 5; \
|
||||
ip[(_stream)] -= nbBytes; \
|
||||
bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1; \
|
||||
bits[(_stream)] <<= nbBits; \
|
||||
} while (0)
|
||||
|
||||
/* Manually unroll the loop because compilers don't consistently
|
||||
* unroll the inner loops, which destroys performance.
|
||||
*/
|
||||
do {
|
||||
/* Decode 5 symbols in each of the 4 streams */
|
||||
for (symbol = 0; symbol < 5; ++symbol) {
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
int const index = (int)(bits[stream] >> 53);
|
||||
int const entry = (int)dtable[index];
|
||||
bits[stream] <<= (entry & 63);
|
||||
op[stream][symbol] = (BYTE)((entry >> 8) & 0xFF);
|
||||
}
|
||||
}
|
||||
/* Reload the bitstreams */
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
int const ctz = ZSTD_countTrailingZeros64(bits[stream]);
|
||||
int const nbBits = ctz & 7;
|
||||
int const nbBytes = ctz >> 3;
|
||||
op[stream] += 5;
|
||||
ip[stream] -= nbBytes;
|
||||
bits[stream] = MEM_read64(ip[stream]) | 1;
|
||||
bits[stream] <<= nbBits;
|
||||
}
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 0);
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 1);
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 2);
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 3);
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 4);
|
||||
|
||||
/* Reload each of the 4 the bitstreams */
|
||||
HUF_4X_FOR_EACH_STREAM(HUF_4X1_RELOAD_STREAM);
|
||||
} while (op[3] < olimit);
|
||||
|
||||
#undef HUF_4X1_DECODE_SYMBOL
|
||||
#undef HUF_4X1_RELOAD_STREAM
|
||||
}
|
||||
|
||||
_out:
|
||||
@@ -797,8 +844,8 @@ HUF_decompress4X1_usingDTable_internal_fast(
|
||||
HUF_DecompressFastLoopFn loopFn)
|
||||
{
|
||||
void const* dt = DTable + 1;
|
||||
const BYTE* const iend = (const BYTE*)cSrc + 6;
|
||||
BYTE* const oend = (BYTE*)dst + dstSize;
|
||||
BYTE const* const ilowest = (BYTE const*)cSrc;
|
||||
BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize);
|
||||
HUF_DecompressFastArgs args;
|
||||
{ size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
FORWARD_IF_ERROR(ret, "Failed to init fast loop args");
|
||||
@@ -806,18 +853,22 @@ HUF_decompress4X1_usingDTable_internal_fast(
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(args.ip[0] >= args.ilimit);
|
||||
assert(args.ip[0] >= args.ilowest);
|
||||
loopFn(&args);
|
||||
|
||||
/* Our loop guarantees that ip[] >= ilimit and that we haven't
|
||||
/* Our loop guarantees that ip[] >= ilowest and that we haven't
|
||||
* overwritten any op[].
|
||||
*/
|
||||
assert(args.ip[0] >= iend);
|
||||
assert(args.ip[1] >= iend);
|
||||
assert(args.ip[2] >= iend);
|
||||
assert(args.ip[3] >= iend);
|
||||
assert(args.ip[0] >= ilowest);
|
||||
assert(args.ip[0] >= ilowest);
|
||||
assert(args.ip[1] >= ilowest);
|
||||
assert(args.ip[2] >= ilowest);
|
||||
assert(args.ip[3] >= ilowest);
|
||||
assert(args.op[3] <= oend);
|
||||
(void)iend;
|
||||
|
||||
assert(ilowest == args.ilowest);
|
||||
assert(ilowest + 6 == args.iend[0]);
|
||||
(void)ilowest;
|
||||
|
||||
/* finish bit streams one by one. */
|
||||
{ size_t const segmentSize = (dstSize+3) / 4;
|
||||
@@ -868,7 +919,7 @@ static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(flags & HUF_flags_disableFast)) {
|
||||
if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {
|
||||
size_t const ret = HUF_decompress4X1_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
@@ -1239,15 +1290,19 @@ HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, c
|
||||
}
|
||||
|
||||
#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
|
||||
ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
|
||||
do { ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); } while (0)
|
||||
|
||||
#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
|
||||
if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
|
||||
ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
|
||||
#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
|
||||
do { \
|
||||
if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
|
||||
ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \
|
||||
} while (0)
|
||||
|
||||
#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
|
||||
if (MEM_64bits()) \
|
||||
ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
|
||||
#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
|
||||
do { \
|
||||
if (MEM_64bits()) \
|
||||
ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \
|
||||
} while (0)
|
||||
|
||||
HINT_INLINE size_t
|
||||
HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,
|
||||
@@ -1307,7 +1362,7 @@ HUF_decompress1X2_usingDTable_internal_body(
|
||||
|
||||
/* decode */
|
||||
{ BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
BYTE* const oend = ZSTD_maybeNullPtrAdd(ostart, dstSize);
|
||||
const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */
|
||||
const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
|
||||
DTableDesc const dtd = HUF_getDTableDesc(DTable);
|
||||
@@ -1332,6 +1387,7 @@ HUF_decompress4X2_usingDTable_internal_body(
|
||||
const HUF_DTable* DTable)
|
||||
{
|
||||
if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
|
||||
if (dstSize < 6) return ERROR(corruption_detected); /* stream 4-split doesn't work */
|
||||
|
||||
{ const BYTE* const istart = (const BYTE*) cSrc;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
@@ -1367,7 +1423,7 @@ HUF_decompress4X2_usingDTable_internal_body(
|
||||
|
||||
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
||||
if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */
|
||||
if (dstSize < 6) return ERROR(corruption_detected); /* stream 4-split doesn't work */
|
||||
assert(dstSize >= 6 /* validated above */);
|
||||
CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
|
||||
CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
|
||||
CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
|
||||
@@ -1472,7 +1528,7 @@ void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
BYTE* op[4];
|
||||
BYTE* oend[4];
|
||||
HUF_DEltX2 const* const dtable = (HUF_DEltX2 const*)args->dt;
|
||||
BYTE const* const ilimit = args->ilimit;
|
||||
BYTE const* const ilowest = args->ilowest;
|
||||
|
||||
/* Copy the arguments to local registers. */
|
||||
ZSTD_memcpy(&bits, &args->bits, sizeof(bits));
|
||||
@@ -1490,13 +1546,12 @@ void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
for (;;) {
|
||||
BYTE* olimit;
|
||||
int stream;
|
||||
int symbol;
|
||||
|
||||
/* Assert loop preconditions */
|
||||
#ifndef NDEBUG
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
assert(op[stream] <= oend[stream]);
|
||||
assert(ip[stream] >= ilimit);
|
||||
assert(ip[stream] >= ilowest);
|
||||
}
|
||||
#endif
|
||||
/* Compute olimit */
|
||||
@@ -1509,7 +1564,7 @@ void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
* We also know that each input pointer is >= ip[0]. So we can run
|
||||
* iters loops before running out of input.
|
||||
*/
|
||||
size_t iters = (size_t)(ip[0] - ilimit) / 7;
|
||||
size_t iters = (size_t)(ip[0] - ilowest) / 7;
|
||||
/* Each iteration can produce up to 10 bytes of output per stream.
|
||||
* Each output stream my advance at different rates. So take the
|
||||
* minimum number of safe iterations among all the output streams.
|
||||
@@ -1527,8 +1582,8 @@ void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
*/
|
||||
olimit = op[3] + (iters * 5);
|
||||
|
||||
/* Exit the fast decoding loop if we are too close to the end. */
|
||||
if (op[3] + 10 > olimit)
|
||||
/* Exit the fast decoding loop once we reach the end. */
|
||||
if (op[3] == olimit)
|
||||
break;
|
||||
|
||||
/* Exit the decoding loop if any input pointer has crossed the
|
||||
@@ -1547,54 +1602,58 @@ void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HUF_4X2_DECODE_SYMBOL(_stream, _decode3) \
|
||||
do { \
|
||||
if ((_decode3) || (_stream) != 3) { \
|
||||
int const index = (int)(bits[(_stream)] >> 53); \
|
||||
HUF_DEltX2 const entry = dtable[index]; \
|
||||
MEM_write16(op[(_stream)], entry.sequence); \
|
||||
bits[(_stream)] <<= (entry.nbBits) & 0x3F; \
|
||||
op[(_stream)] += (entry.length); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define HUF_4X2_RELOAD_STREAM(_stream) \
|
||||
do { \
|
||||
HUF_4X2_DECODE_SYMBOL(3, 1); \
|
||||
{ \
|
||||
int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
|
||||
int const nbBits = ctz & 7; \
|
||||
int const nbBytes = ctz >> 3; \
|
||||
ip[(_stream)] -= nbBytes; \
|
||||
bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1; \
|
||||
bits[(_stream)] <<= nbBits; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Manually unroll the loop because compilers don't consistently
|
||||
* unroll the inner loops, which destroys performance.
|
||||
*/
|
||||
do {
|
||||
/* Do 5 table lookups for each of the first 3 streams */
|
||||
for (symbol = 0; symbol < 5; ++symbol) {
|
||||
for (stream = 0; stream < 3; ++stream) {
|
||||
int const index = (int)(bits[stream] >> 53);
|
||||
HUF_DEltX2 const entry = dtable[index];
|
||||
MEM_write16(op[stream], entry.sequence);
|
||||
bits[stream] <<= (entry.nbBits);
|
||||
op[stream] += (entry.length);
|
||||
}
|
||||
}
|
||||
/* Do 1 table lookup from the final stream */
|
||||
{
|
||||
int const index = (int)(bits[3] >> 53);
|
||||
HUF_DEltX2 const entry = dtable[index];
|
||||
MEM_write16(op[3], entry.sequence);
|
||||
bits[3] <<= (entry.nbBits);
|
||||
op[3] += (entry.length);
|
||||
}
|
||||
/* Do 4 table lookups from the final stream & reload bitstreams */
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
/* Do a table lookup from the final stream.
|
||||
* This is interleaved with the reloading to reduce register
|
||||
* pressure. This shouldn't be necessary, but compilers can
|
||||
* struggle with codegen with high register pressure.
|
||||
*/
|
||||
{
|
||||
int const index = (int)(bits[3] >> 53);
|
||||
HUF_DEltX2 const entry = dtable[index];
|
||||
MEM_write16(op[3], entry.sequence);
|
||||
bits[3] <<= (entry.nbBits);
|
||||
op[3] += (entry.length);
|
||||
}
|
||||
/* Reload the bistreams. The final bitstream must be reloaded
|
||||
* after the 5th symbol was decoded.
|
||||
*/
|
||||
{
|
||||
int const ctz = ZSTD_countTrailingZeros64(bits[stream]);
|
||||
int const nbBits = ctz & 7;
|
||||
int const nbBytes = ctz >> 3;
|
||||
ip[stream] -= nbBytes;
|
||||
bits[stream] = MEM_read64(ip[stream]) | 1;
|
||||
bits[stream] <<= nbBits;
|
||||
}
|
||||
}
|
||||
/* Decode 5 symbols from each of the first 3 streams.
|
||||
* The final stream will be decoded during the reload phase
|
||||
* to reduce register pressure.
|
||||
*/
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
|
||||
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
|
||||
|
||||
/* Decode one symbol from the final stream */
|
||||
HUF_4X2_DECODE_SYMBOL(3, 1);
|
||||
|
||||
/* Decode 4 symbols from the final stream & reload bitstreams.
|
||||
* The final stream is reloaded last, meaning that all 5 symbols
|
||||
* are decoded from the final stream before it is reloaded.
|
||||
*/
|
||||
HUF_4X_FOR_EACH_STREAM(HUF_4X2_RELOAD_STREAM);
|
||||
} while (op[3] < olimit);
|
||||
}
|
||||
|
||||
#undef HUF_4X2_DECODE_SYMBOL
|
||||
#undef HUF_4X2_RELOAD_STREAM
|
||||
|
||||
_out:
|
||||
|
||||
/* Save the final values of each of the state variables back to args. */
|
||||
@@ -1611,8 +1670,8 @@ HUF_decompress4X2_usingDTable_internal_fast(
|
||||
const HUF_DTable* DTable,
|
||||
HUF_DecompressFastLoopFn loopFn) {
|
||||
void const* dt = DTable + 1;
|
||||
const BYTE* const iend = (const BYTE*)cSrc + 6;
|
||||
BYTE* const oend = (BYTE*)dst + dstSize;
|
||||
const BYTE* const ilowest = (const BYTE*)cSrc;
|
||||
BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize);
|
||||
HUF_DecompressFastArgs args;
|
||||
{
|
||||
size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
@@ -1621,16 +1680,19 @@ HUF_decompress4X2_usingDTable_internal_fast(
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(args.ip[0] >= args.ilimit);
|
||||
assert(args.ip[0] >= args.ilowest);
|
||||
loopFn(&args);
|
||||
|
||||
/* note : op4 already verified within main loop */
|
||||
assert(args.ip[0] >= iend);
|
||||
assert(args.ip[1] >= iend);
|
||||
assert(args.ip[2] >= iend);
|
||||
assert(args.ip[3] >= iend);
|
||||
assert(args.ip[0] >= ilowest);
|
||||
assert(args.ip[1] >= ilowest);
|
||||
assert(args.ip[2] >= ilowest);
|
||||
assert(args.ip[3] >= ilowest);
|
||||
assert(args.op[3] <= oend);
|
||||
(void)iend;
|
||||
|
||||
assert(ilowest == args.ilowest);
|
||||
assert(ilowest + 6 == args.iend[0]);
|
||||
(void)ilowest;
|
||||
|
||||
/* finish bitStreams one by one */
|
||||
{
|
||||
@@ -1679,7 +1741,7 @@ static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(flags & HUF_flags_disableFast)) {
|
||||
if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {
|
||||
size_t const ret = HUF_decompress4X2_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
@@ -10,11 +10,32 @@
|
||||
|
||||
#include "../common/portability_macros.h"
|
||||
|
||||
#if defined(__ELF__) && defined(__GNUC__)
|
||||
/* Stack marking
|
||||
* ref: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart
|
||||
*/
|
||||
#if defined(__ELF__) && defined(__GNUC__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
|
||||
#if defined(__aarch64__)
|
||||
/* Mark that this assembly supports BTI & PAC, because it is empty for aarch64.
|
||||
* See: https://github.com/facebook/zstd/issues/3841
|
||||
* See: https://gcc.godbolt.org/z/sqr5T4ffK
|
||||
* See: https://lore.kernel.org/linux-arm-kernel/20200429211641.9279-8-broonie@kernel.org/
|
||||
* See: https://reviews.llvm.org/D62609
|
||||
*/
|
||||
.pushsection .note.gnu.property, "a"
|
||||
.p2align 3
|
||||
.long 4 /* size of the name - "GNU\0" */
|
||||
.long 0x10 /* size of descriptor */
|
||||
.long 0x5 /* NT_GNU_PROPERTY_TYPE_0 */
|
||||
.asciz "GNU"
|
||||
.long 0xc0000000 /* pr_type - GNU_PROPERTY_AARCH64_FEATURE_1_AND */
|
||||
.long 4 /* pr_datasz - 4 bytes */
|
||||
.long 3 /* pr_data - GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC */
|
||||
.p2align 3 /* pr_padding - bring everything to 8 byte alignment */
|
||||
.popsection
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
@@ -131,7 +152,7 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
|
||||
movq 88(%rax), %bits3
|
||||
movq 96(%rax), %dtable
|
||||
push %rax /* argument */
|
||||
push 104(%rax) /* ilimit */
|
||||
push 104(%rax) /* ilowest */
|
||||
push 112(%rax) /* oend */
|
||||
push %olimit /* olimit space */
|
||||
|
||||
@@ -156,11 +177,11 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
|
||||
shrq $2, %r15
|
||||
|
||||
movq %ip0, %rax /* rax = ip0 */
|
||||
movq 40(%rsp), %rdx /* rdx = ilimit */
|
||||
subq %rdx, %rax /* rax = ip0 - ilimit */
|
||||
movq %rax, %rbx /* rbx = ip0 - ilimit */
|
||||
movq 40(%rsp), %rdx /* rdx = ilowest */
|
||||
subq %rdx, %rax /* rax = ip0 - ilowest */
|
||||
movq %rax, %rbx /* rbx = ip0 - ilowest */
|
||||
|
||||
/* rdx = (ip0 - ilimit) / 7 */
|
||||
/* rdx = (ip0 - ilowest) / 7 */
|
||||
movabsq $2635249153387078803, %rdx
|
||||
mulq %rdx
|
||||
subq %rdx, %rbx
|
||||
@@ -183,9 +204,8 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
|
||||
|
||||
/* If (op3 + 20 > olimit) */
|
||||
movq %op3, %rax /* rax = op3 */
|
||||
addq $20, %rax /* rax = op3 + 20 */
|
||||
cmpq %rax, %olimit /* op3 + 20 > olimit */
|
||||
jb .L_4X1_exit
|
||||
cmpq %rax, %olimit /* op3 == olimit */
|
||||
je .L_4X1_exit
|
||||
|
||||
/* If (ip1 < ip0) go to exit */
|
||||
cmpq %ip0, %ip1
|
||||
@@ -316,7 +336,7 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
|
||||
/* Restore stack (oend & olimit) */
|
||||
pop %rax /* olimit */
|
||||
pop %rax /* oend */
|
||||
pop %rax /* ilimit */
|
||||
pop %rax /* ilowest */
|
||||
pop %rax /* arg */
|
||||
|
||||
/* Save ip / op / bits */
|
||||
@@ -387,7 +407,7 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
|
||||
movq 96(%rax), %dtable
|
||||
push %rax /* argument */
|
||||
push %rax /* olimit */
|
||||
push 104(%rax) /* ilimit */
|
||||
push 104(%rax) /* ilowest */
|
||||
|
||||
movq 112(%rax), %rax
|
||||
push %rax /* oend3 */
|
||||
@@ -414,9 +434,9 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
|
||||
|
||||
/* We can consume up to 7 input bytes each iteration. */
|
||||
movq %ip0, %rax /* rax = ip0 */
|
||||
movq 40(%rsp), %rdx /* rdx = ilimit */
|
||||
subq %rdx, %rax /* rax = ip0 - ilimit */
|
||||
movq %rax, %r15 /* r15 = ip0 - ilimit */
|
||||
movq 40(%rsp), %rdx /* rdx = ilowest */
|
||||
subq %rdx, %rax /* rax = ip0 - ilowest */
|
||||
movq %rax, %r15 /* r15 = ip0 - ilowest */
|
||||
|
||||
/* rdx = rax / 7 */
|
||||
movabsq $2635249153387078803, %rdx
|
||||
@@ -426,7 +446,7 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
|
||||
addq %r15, %rdx
|
||||
shrq $2, %rdx
|
||||
|
||||
/* r15 = (ip0 - ilimit) / 7 */
|
||||
/* r15 = (ip0 - ilowest) / 7 */
|
||||
movq %rdx, %r15
|
||||
|
||||
/* r15 = min(r15, min(oend0 - op0, oend1 - op1, oend2 - op2, oend3 - op3) / 10) */
|
||||
@@ -467,9 +487,8 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
|
||||
|
||||
/* If (op3 + 10 > olimit) */
|
||||
movq %op3, %rax /* rax = op3 */
|
||||
addq $10, %rax /* rax = op3 + 10 */
|
||||
cmpq %rax, %olimit /* op3 + 10 > olimit */
|
||||
jb .L_4X2_exit
|
||||
cmpq %rax, %olimit /* op3 == olimit */
|
||||
je .L_4X2_exit
|
||||
|
||||
/* If (ip1 < ip0) go to exit */
|
||||
cmpq %ip0, %ip1
|
||||
@@ -537,7 +556,7 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
|
||||
pop %rax /* oend1 */
|
||||
pop %rax /* oend2 */
|
||||
pop %rax /* oend3 */
|
||||
pop %rax /* ilimit */
|
||||
pop %rax /* ilowest */
|
||||
pop %rax /* olimit */
|
||||
pop %rax /* arg */
|
||||
|
||||
|
||||
@@ -55,18 +55,19 @@
|
||||
/*-*******************************************************
|
||||
* Dependencies
|
||||
*********************************************************/
|
||||
#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
|
||||
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
|
||||
#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
|
||||
#include "../common/error_private.h"
|
||||
#include "../common/zstd_internal.h" /* blockProperties_t */
|
||||
#include "../common/mem.h" /* low level memory routines */
|
||||
#include "../common/bits.h" /* ZSTD_highbit32 */
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "../common/fse.h"
|
||||
#include "../common/huf.h"
|
||||
#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
|
||||
#include "../common/zstd_internal.h" /* blockProperties_t */
|
||||
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
||||
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
||||
#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
|
||||
#include "../common/bits.h" /* ZSTD_highbit32 */
|
||||
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
||||
# include "../legacy/zstd_legacy.h"
|
||||
@@ -728,17 +729,17 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
||||
return frameSizeInfo;
|
||||
}
|
||||
|
||||
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
||||
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize, ZSTD_format_e format)
|
||||
{
|
||||
ZSTD_frameSizeInfo frameSizeInfo;
|
||||
ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
||||
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||
if (ZSTD_isLegacy(src, srcSize))
|
||||
if (format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize))
|
||||
return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
|
||||
#endif
|
||||
|
||||
if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
||||
if (format == ZSTD_f_zstd1 && (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
||||
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||
frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
|
||||
assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
|
||||
@@ -752,7 +753,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
||||
ZSTD_frameHeader zfh;
|
||||
|
||||
/* Extract Frame Header */
|
||||
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
||||
{ size_t const ret = ZSTD_getFrameHeader_advanced(&zfh, src, srcSize, format);
|
||||
if (ZSTD_isError(ret))
|
||||
return ZSTD_errorFrameSizeInfo(ret);
|
||||
if (ret > 0)
|
||||
@@ -795,15 +796,17 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
||||
}
|
||||
}
|
||||
|
||||
static size_t ZSTD_findFrameCompressedSize_advanced(const void *src, size_t srcSize, ZSTD_format_e format) {
|
||||
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, format);
|
||||
return frameSizeInfo.compressedSize;
|
||||
}
|
||||
|
||||
/** ZSTD_findFrameCompressedSize() :
|
||||
* compatible with legacy mode
|
||||
* `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
|
||||
* `srcSize` must be at least as large as the frame contained
|
||||
* @return : the compressed size of the frame starting at `src` */
|
||||
* See docs in zstd.h
|
||||
* Note: compatible with legacy mode */
|
||||
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
||||
{
|
||||
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
||||
return frameSizeInfo.compressedSize;
|
||||
return ZSTD_findFrameCompressedSize_advanced(src, srcSize, ZSTD_f_zstd1);
|
||||
}
|
||||
|
||||
/** ZSTD_decompressBound() :
|
||||
@@ -817,7 +820,7 @@ 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);
|
||||
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);
|
||||
size_t const compressedSize = frameSizeInfo.compressedSize;
|
||||
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
||||
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
||||
@@ -837,7 +840,7 @@ size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
|
||||
|
||||
/* Iterate over each frame */
|
||||
while (srcSize > 0) {
|
||||
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
||||
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);
|
||||
size_t const compressedSize = frameSizeInfo.compressedSize;
|
||||
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
||||
ZSTD_frameHeader zfh;
|
||||
@@ -1023,12 +1026,14 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
default:
|
||||
RETURN_ERROR(corruption_detected, "invalid block type");
|
||||
}
|
||||
|
||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||
if (dctx->validateChecksum)
|
||||
FORWARD_IF_ERROR(decodedSize, "Block decompression failure");
|
||||
DEBUGLOG(5, "Decompressed block of dSize = %u", (unsigned)decodedSize);
|
||||
if (dctx->validateChecksum) {
|
||||
XXH64_update(&dctx->xxhState, op, decodedSize);
|
||||
if (decodedSize != 0)
|
||||
}
|
||||
if (decodedSize) /* support dst = NULL,0 */ {
|
||||
op += decodedSize;
|
||||
}
|
||||
assert(ip != NULL);
|
||||
ip += cBlockSize;
|
||||
remainingSrcSize -= cBlockSize;
|
||||
@@ -1058,7 +1063,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
return (size_t)(op-ostart);
|
||||
}
|
||||
|
||||
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
static
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict, size_t dictSize,
|
||||
@@ -1078,7 +1085,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
|
||||
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||
if (ZSTD_isLegacy(src, srcSize)) {
|
||||
if (dctx->format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize)) {
|
||||
size_t decodedSize;
|
||||
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
||||
if (ZSTD_isError(frameSize)) return frameSize;
|
||||
@@ -1088,6 +1095,15 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||
|
||||
{
|
||||
unsigned long long const expectedSize = ZSTD_getFrameContentSize(src, srcSize);
|
||||
RETURN_ERROR_IF(expectedSize == ZSTD_CONTENTSIZE_ERROR, corruption_detected, "Corrupted frame header!");
|
||||
if (expectedSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
||||
RETURN_ERROR_IF(expectedSize != decodedSize, corruption_detected,
|
||||
"Frame header size does not match decoded size!");
|
||||
}
|
||||
}
|
||||
|
||||
assert(decodedSize <= dstCapacity);
|
||||
dst = (BYTE*)dst + decodedSize;
|
||||
dstCapacity -= decodedSize;
|
||||
@@ -1099,7 +1115,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (srcSize >= 4) {
|
||||
if (dctx->format == ZSTD_f_zstd1 && srcSize >= 4) {
|
||||
U32 const magicNumber = MEM_readLE32(src);
|
||||
DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
|
||||
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||
@@ -1396,6 +1412,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||
case ZSTDds_decodeSkippableHeader:
|
||||
assert(src != NULL);
|
||||
assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
|
||||
assert(dctx->format != ZSTD_f_zstd1_magicless);
|
||||
ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
|
||||
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
|
||||
dctx->stage = ZSTDds_skipFrame;
|
||||
@@ -1548,12 +1565,6 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
||||
dctx->stage = ZSTDds_getFrameHeaderSize;
|
||||
dctx->processedCSize = 0;
|
||||
dctx->decodedSize = 0;
|
||||
/* Set to non-null because ZSTD_prefetchMatch() may end up doing addition
|
||||
* with this value for corrupted frames. However, it then just passes the
|
||||
* pointer to PREFETCH_L1(), which doesn't require valid pointers. But,
|
||||
* if it is NULL we get nullptr-with-nonzero-offset UBSAN warnings.
|
||||
*/
|
||||
dctx->previousDstEnd = "";
|
||||
dctx->previousDstEnd = NULL;
|
||||
dctx->prefixStart = NULL;
|
||||
dctx->virtualStart = NULL;
|
||||
@@ -2172,12 +2183,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
||||
&& zds->fParams.frameType != ZSTD_skippableFrame
|
||||
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
||||
size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
|
||||
size_t const cSize = ZSTD_findFrameCompressedSize_advanced(istart, (size_t)(iend-istart), zds->format);
|
||||
if (cSize <= (size_t)(iend-istart)) {
|
||||
/* shortcut : using single-pass mode */
|
||||
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
|
||||
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
||||
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
||||
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()");
|
||||
assert(istart != NULL);
|
||||
ip = istart + cSize;
|
||||
op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
|
||||
@@ -2199,7 +2210,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
DEBUGLOG(4, "Consume header");
|
||||
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 */
|
||||
if (zds->format == ZSTD_f_zstd1
|
||||
&& (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 {
|
||||
|
||||
@@ -727,6 +727,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
||||
|
||||
/* FSE table descriptors */
|
||||
RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong, ""); /* minimum possible size: 1 byte for symbol encoding types */
|
||||
RETURN_ERROR_IF(*ip & 3, corruption_detected, ""); /* The last field, Reserved, must be all-zeroes. */
|
||||
{ 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);
|
||||
@@ -902,6 +903,7 @@ static void ZSTD_safecopyDstBeforeSrc(BYTE* op, const BYTE* ip, ptrdiff_t length
|
||||
* to be optimized for many small sequences, since those fall into ZSTD_execSequence().
|
||||
*/
|
||||
FORCE_NOINLINE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_execSequenceEnd(BYTE* op,
|
||||
BYTE* const oend, seq_t sequence,
|
||||
const BYTE** litPtr, const BYTE* const litLimit,
|
||||
@@ -949,6 +951,7 @@ size_t ZSTD_execSequenceEnd(BYTE* op,
|
||||
* This version is intended to be used during instances where the litBuffer is still split. It is kept separate to avoid performance impact for the good case.
|
||||
*/
|
||||
FORCE_NOINLINE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_execSequenceEndSplitLitBuffer(BYTE* op,
|
||||
BYTE* const oend, const BYTE* const oend_w, seq_t sequence,
|
||||
const BYTE** litPtr, const BYTE* const litLimit,
|
||||
@@ -994,6 +997,7 @@ size_t ZSTD_execSequenceEndSplitLitBuffer(BYTE* op,
|
||||
}
|
||||
|
||||
HINT_INLINE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_execSequence(BYTE* op,
|
||||
BYTE* const oend, seq_t sequence,
|
||||
const BYTE** litPtr, const BYTE* const litLimit,
|
||||
@@ -1092,6 +1096,7 @@ size_t ZSTD_execSequence(BYTE* op,
|
||||
}
|
||||
|
||||
HINT_INLINE
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
size_t ZSTD_execSequenceSplitLitBuffer(BYTE* op,
|
||||
BYTE* const oend, const BYTE* const oend_w, seq_t sequence,
|
||||
const BYTE** litPtr, const BYTE* const litLimit,
|
||||
@@ -1300,7 +1305,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
|
||||
} else {
|
||||
offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1);
|
||||
{ size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
|
||||
temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
|
||||
temp -= !temp; /* 0 is not valid: input corrupted => force offset to -1 => corruption detected at execSequence */
|
||||
if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
|
||||
seqState->prevOffset[1] = seqState->prevOffset[0];
|
||||
seqState->prevOffset[0] = offset = temp;
|
||||
@@ -1340,8 +1345,9 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
|
||||
return seq;
|
||||
}
|
||||
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
MEM_STATIC int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd)
|
||||
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
|
||||
#if DEBUGLEVEL >= 1
|
||||
static int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd)
|
||||
{
|
||||
size_t const windowSize = dctx->fParams.windowSize;
|
||||
/* No dictionary used. */
|
||||
@@ -1355,8 +1361,9 @@ MEM_STATIC int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefix
|
||||
/* Dictionary is active. */
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
MEM_STATIC void ZSTD_assertValidSequence(
|
||||
static void ZSTD_assertValidSequence(
|
||||
ZSTD_DCtx const* dctx,
|
||||
BYTE const* op, BYTE const* oend,
|
||||
seq_t const seq,
|
||||
@@ -1401,7 +1408,7 @@ ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,
|
||||
const BYTE* ip = (const BYTE*)seqStart;
|
||||
const BYTE* const iend = ip + seqSize;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* const oend = ostart + maxDstSize;
|
||||
BYTE* const oend = ZSTD_maybeNullPtrAdd(ostart, maxDstSize);
|
||||
BYTE* op = ostart;
|
||||
const BYTE* litPtr = dctx->litPtr;
|
||||
const BYTE* litBufferEnd = dctx->litBufferEnd;
|
||||
@@ -1429,7 +1436,7 @@ ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,
|
||||
BIT_DStream_completed < BIT_DStream_overflow);
|
||||
|
||||
/* decompress without overrunning litPtr begins */
|
||||
{ seq_t sequence = {0,0,0}; /* some static analyzer believe that @sequence is not initialized (it necessarily is, since for(;;) loop as at least one interation) */
|
||||
{ seq_t sequence = {0,0,0}; /* some static analyzer believe that @sequence is not initialized (it necessarily is, since for(;;) loop as at least one iteration) */
|
||||
/* Align the decompression loop to 32 + 16 bytes.
|
||||
*
|
||||
* zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression
|
||||
@@ -1579,7 +1586,8 @@ ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,
|
||||
/* last literal segment */
|
||||
if (dctx->litBufferLocation == ZSTD_split) {
|
||||
/* split hasn't been reached yet, first get dst then copy litExtraBuffer */
|
||||
size_t const lastLLSize = litBufferEnd - litPtr;
|
||||
size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);
|
||||
DEBUGLOG(6, "copy last literals from segment : %u", (U32)lastLLSize);
|
||||
RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, "");
|
||||
if (op != NULL) {
|
||||
ZSTD_memmove(op, litPtr, lastLLSize);
|
||||
@@ -1589,15 +1597,17 @@ ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,
|
||||
litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
|
||||
dctx->litBufferLocation = ZSTD_not_in_dst;
|
||||
}
|
||||
/* copy last literals from interal buffer */
|
||||
{ size_t const lastLLSize = litBufferEnd - litPtr;
|
||||
/* copy last literals from internal buffer */
|
||||
{ size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);
|
||||
DEBUGLOG(6, "copy last literals from internal buffer : %u", (U32)lastLLSize);
|
||||
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
|
||||
if (op != NULL) {
|
||||
ZSTD_memcpy(op, litPtr, lastLLSize);
|
||||
op += lastLLSize;
|
||||
} }
|
||||
|
||||
return op-ostart;
|
||||
DEBUGLOG(6, "decoded block of size %u bytes", (U32)(op - ostart));
|
||||
return (size_t)(op - ostart);
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
@@ -1610,7 +1620,7 @@ ZSTD_decompressSequences_body(ZSTD_DCtx* dctx,
|
||||
const BYTE* ip = (const BYTE*)seqStart;
|
||||
const BYTE* const iend = ip + seqSize;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* const oend = dctx->litBufferLocation == ZSTD_not_in_dst ? ostart + maxDstSize : dctx->litBuffer;
|
||||
BYTE* const oend = dctx->litBufferLocation == ZSTD_not_in_dst ? ZSTD_maybeNullPtrAdd(ostart, maxDstSize) : dctx->litBuffer;
|
||||
BYTE* op = ostart;
|
||||
const BYTE* litPtr = dctx->litPtr;
|
||||
const BYTE* const litEnd = litPtr + dctx->litSize;
|
||||
@@ -1667,14 +1677,16 @@ ZSTD_decompressSequences_body(ZSTD_DCtx* dctx,
|
||||
}
|
||||
|
||||
/* last literal segment */
|
||||
{ size_t const lastLLSize = litEnd - litPtr;
|
||||
{ size_t const lastLLSize = (size_t)(litEnd - litPtr);
|
||||
DEBUGLOG(6, "copy last literals : %u", (U32)lastLLSize);
|
||||
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
|
||||
if (op != NULL) {
|
||||
ZSTD_memcpy(op, litPtr, lastLLSize);
|
||||
op += lastLLSize;
|
||||
} }
|
||||
|
||||
return op-ostart;
|
||||
DEBUGLOG(6, "decoded block of size %u bytes", (U32)(op - ostart));
|
||||
return (size_t)(op - ostart);
|
||||
}
|
||||
|
||||
static size_t
|
||||
@@ -1698,14 +1710,16 @@ ZSTD_decompressSequencesSplitLitBuffer_default(ZSTD_DCtx* dctx,
|
||||
|
||||
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence,
|
||||
FORCE_INLINE_TEMPLATE
|
||||
|
||||
size_t ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence,
|
||||
const BYTE* const prefixStart, const BYTE* const dictEnd)
|
||||
{
|
||||
prefetchPos += sequence.litLength;
|
||||
{ const BYTE* const matchBase = (sequence.offset > prefetchPos) ? dictEnd : prefixStart;
|
||||
const BYTE* const match = matchBase + prefetchPos - sequence.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
|
||||
* No consequence though : memory address is only used for prefetching, not for dereferencing */
|
||||
/* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
|
||||
* No consequence though : memory address is only used for prefetching, not for dereferencing */
|
||||
const BYTE* const match = ZSTD_wrappedPtrSub(ZSTD_wrappedPtrAdd(matchBase, prefetchPos), sequence.offset);
|
||||
PREFETCH_L1(match); PREFETCH_L1(match+CACHELINE_SIZE); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
||||
}
|
||||
return prefetchPos + sequence.matchLength;
|
||||
@@ -1725,7 +1739,7 @@ ZSTD_decompressSequencesLong_body(
|
||||
const BYTE* ip = (const BYTE*)seqStart;
|
||||
const BYTE* const iend = ip + seqSize;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* const oend = dctx->litBufferLocation == ZSTD_in_dst ? dctx->litBuffer : ostart + maxDstSize;
|
||||
BYTE* const oend = dctx->litBufferLocation == ZSTD_in_dst ? dctx->litBuffer : ZSTD_maybeNullPtrAdd(ostart, maxDstSize);
|
||||
BYTE* op = ostart;
|
||||
const BYTE* litPtr = dctx->litPtr;
|
||||
const BYTE* litBufferEnd = dctx->litBufferEnd;
|
||||
@@ -1870,7 +1884,7 @@ ZSTD_decompressSequencesLong_body(
|
||||
}
|
||||
}
|
||||
|
||||
return op-ostart;
|
||||
return (size_t)(op - ostart);
|
||||
}
|
||||
|
||||
static size_t
|
||||
@@ -2060,7 +2074,7 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
const void* src, size_t srcSize, const streaming_operation streaming)
|
||||
{ /* blockType == blockCompressed */
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
|
||||
DEBUGLOG(5, "ZSTD_decompressBlock_internal (cSize : %u)", (unsigned)srcSize);
|
||||
|
||||
/* Note : the wording of the specification
|
||||
* allows compressed block to be sized exactly ZSTD_blockSizeMax(dctx).
|
||||
@@ -2086,7 +2100,7 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
* Additionally, take the min with dstCapacity to ensure that the totalHistorySize fits in a size_t.
|
||||
*/
|
||||
size_t const blockSizeMax = MIN(dstCapacity, ZSTD_blockSizeMax(dctx));
|
||||
size_t const totalHistorySize = ZSTD_totalHistorySize((BYTE*)dst + blockSizeMax, (BYTE const*)dctx->virtualStart);
|
||||
size_t const totalHistorySize = ZSTD_totalHistorySize(ZSTD_maybeNullPtrAdd((BYTE*)dst, blockSizeMax), (BYTE const*)dctx->virtualStart);
|
||||
/* isLongOffset must be true if there are long offsets.
|
||||
* Offsets are long if they are larger than ZSTD_maxShortOffset().
|
||||
* We don't expect that to be the case in 64-bit mode.
|
||||
@@ -2166,6 +2180,7 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
}
|
||||
|
||||
|
||||
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
||||
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize)
|
||||
{
|
||||
if (dst != dctx->previousDstEnd && dstSize > 0) { /* not contiguous */
|
||||
@@ -2185,6 +2200,7 @@ size_t ZSTD_decompressBlock_deprecated(ZSTD_DCtx* dctx,
|
||||
dctx->isFrameDecompression = 0;
|
||||
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
||||
dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, not_streaming);
|
||||
FORWARD_IF_ERROR(dSize, "");
|
||||
dctx->previousDstEnd = (char*)dst + dSize;
|
||||
return dSize;
|
||||
}
|
||||
|
||||
+14
-10
@@ -31,8 +31,8 @@
|
||||
#endif
|
||||
|
||||
#include "../common/mem.h" /* read */
|
||||
#include "../common/pool.h"
|
||||
#include "../common/threading.h"
|
||||
#include "../common/pool.h" /* POOL_ctx */
|
||||
#include "../common/threading.h" /* ZSTD_pthread_mutex_t */
|
||||
#include "../common/zstd_internal.h" /* includes zstd.h */
|
||||
#include "../common/bits.h" /* ZSTD_highbit32 */
|
||||
#include "../zdict.h"
|
||||
@@ -78,7 +78,7 @@ static clock_t g_time = 0;
|
||||
#undef LOCALDISPLAYUPDATE
|
||||
#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \
|
||||
if (displayLevel >= l) { \
|
||||
if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \
|
||||
if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \
|
||||
g_time = clock(); \
|
||||
DISPLAY(__VA_ARGS__); \
|
||||
} \
|
||||
@@ -301,9 +301,10 @@ static int WIN_CDECL COVER_strict_cmp8(const void *lp, const void *rp) {
|
||||
* Returns the first pointer in [first, last) whose element does not compare
|
||||
* less than value. If no such element exists it returns last.
|
||||
*/
|
||||
static const size_t *COVER_lower_bound(const size_t *first, const size_t *last,
|
||||
static const size_t *COVER_lower_bound(const size_t* first, const size_t* last,
|
||||
size_t value) {
|
||||
size_t count = last - first;
|
||||
size_t count = (size_t)(last - first);
|
||||
assert(last >= first);
|
||||
while (count != 0) {
|
||||
size_t step = count / 2;
|
||||
const size_t *ptr = first;
|
||||
@@ -549,7 +550,8 @@ static void COVER_ctx_destroy(COVER_ctx_t *ctx) {
|
||||
*/
|
||||
static size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
const size_t *samplesSizes, unsigned nbSamples,
|
||||
unsigned d, double splitPoint) {
|
||||
unsigned d, double splitPoint)
|
||||
{
|
||||
const BYTE *const samples = (const BYTE *)samplesBuffer;
|
||||
const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples);
|
||||
/* Split samples into testing and training sets */
|
||||
@@ -907,8 +909,10 @@ 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, ZDICT_cover_params_t parameters,
|
||||
COVER_dictSelection_t selection) {
|
||||
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;
|
||||
@@ -980,8 +984,8 @@ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBuffe
|
||||
size_t largestCompressed = 0;
|
||||
BYTE* customDictContentEnd = customDictContent + dictContentSize;
|
||||
|
||||
BYTE * largestDictbuffer = (BYTE *)malloc(dictBufferCapacity);
|
||||
BYTE * candidateDictBuffer = (BYTE *)malloc(dictBufferCapacity);
|
||||
BYTE* largestDictbuffer = (BYTE*)malloc(dictBufferCapacity);
|
||||
BYTE* candidateDictBuffer = (BYTE*)malloc(dictBufferCapacity);
|
||||
double regressionTolerance = ((double)params.shrinkDictMaxRegression / 100.0) + 1.00;
|
||||
|
||||
if (!largestDictbuffer || !candidateDictBuffer) {
|
||||
|
||||
@@ -12,14 +12,8 @@
|
||||
# define ZDICT_STATIC_LINKING_ONLY
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* fprintf */
|
||||
#include <stdlib.h> /* malloc, free, qsort */
|
||||
#include <string.h> /* memset */
|
||||
#include <time.h> /* clock */
|
||||
#include "../common/mem.h" /* read */
|
||||
#include "../common/pool.h"
|
||||
#include "../common/threading.h"
|
||||
#include "../common/zstd_internal.h" /* includes zstd.h */
|
||||
#include "../common/threading.h" /* ZSTD_pthread_mutex_t */
|
||||
#include "../common/mem.h" /* U32, BYTE */
|
||||
#include "../zdict.h"
|
||||
|
||||
/**
|
||||
|
||||
+12
-6
@@ -74,9 +74,9 @@ static const U32 g_selectivity_default = 9;
|
||||
* Console display
|
||||
***************************************/
|
||||
#undef DISPLAY
|
||||
#define DISPLAY(...) { fprintf(stderr, __VA_ARGS__); fflush( stderr ); }
|
||||
#define DISPLAY(...) do { fprintf(stderr, __VA_ARGS__); fflush( stderr ); } while (0)
|
||||
#undef DISPLAYLEVEL
|
||||
#define DISPLAYLEVEL(l, ...) if (notificationLevel>=l) { DISPLAY(__VA_ARGS__); } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */
|
||||
#define DISPLAYLEVEL(l, ...) do { if (notificationLevel>=l) { DISPLAY(__VA_ARGS__); } } while (0) /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */
|
||||
|
||||
static clock_t ZDICT_clockSpan(clock_t nPrevious) { return clock() - nPrevious; }
|
||||
|
||||
@@ -477,10 +477,16 @@ static size_t ZDICT_trainBuffer_legacy(dictItem* dictList, U32 dictListSize,
|
||||
clock_t const refreshRate = CLOCKS_PER_SEC * 3 / 10;
|
||||
|
||||
# undef DISPLAYUPDATE
|
||||
# define DISPLAYUPDATE(l, ...) if (notificationLevel>=l) { \
|
||||
if (ZDICT_clockSpan(displayClock) > refreshRate) \
|
||||
{ displayClock = clock(); DISPLAY(__VA_ARGS__); \
|
||||
if (notificationLevel>=4) fflush(stderr); } }
|
||||
# define DISPLAYUPDATE(l, ...) \
|
||||
do { \
|
||||
if (notificationLevel>=l) { \
|
||||
if (ZDICT_clockSpan(displayClock) > refreshRate) { \
|
||||
displayClock = clock(); \
|
||||
DISPLAY(__VA_ARGS__); \
|
||||
} \
|
||||
if (notificationLevel>=4) fflush(stderr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* init */
|
||||
DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */
|
||||
|
||||
@@ -124,6 +124,20 @@ MEM_STATIC size_t ZSTD_decompressLegacy(
|
||||
const void* dict,size_t dictSize)
|
||||
{
|
||||
U32 const version = ZSTD_isLegacy(src, compressedSize);
|
||||
char x;
|
||||
/* Avoid passing NULL to legacy decoding. */
|
||||
if (dst == NULL) {
|
||||
assert(dstCapacity == 0);
|
||||
dst = &x;
|
||||
}
|
||||
if (src == NULL) {
|
||||
assert(compressedSize == 0);
|
||||
src = &x;
|
||||
}
|
||||
if (dict == NULL) {
|
||||
assert(dictSize == 0);
|
||||
dict = &x;
|
||||
}
|
||||
(void)dst; (void)dstCapacity; (void)dict; (void)dictSize; /* unused when ZSTD_LEGACY_SUPPORT >= 8 */
|
||||
switch(version)
|
||||
{
|
||||
@@ -287,6 +301,12 @@ MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)
|
||||
MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U32 newVersion,
|
||||
const void* dict, size_t dictSize)
|
||||
{
|
||||
char x;
|
||||
/* Avoid passing NULL to legacy decoding. */
|
||||
if (dict == NULL) {
|
||||
assert(dictSize == 0);
|
||||
dict = &x;
|
||||
}
|
||||
DEBUGLOG(5, "ZSTD_initLegacyStream for v0.%u", newVersion);
|
||||
if (prevVersion != newVersion) ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion);
|
||||
switch(newVersion)
|
||||
@@ -346,6 +366,16 @@ MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U
|
||||
MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,
|
||||
ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
||||
{
|
||||
static char x;
|
||||
/* Avoid passing NULL to legacy decoding. */
|
||||
if (output->dst == NULL) {
|
||||
assert(output->size == 0);
|
||||
output->dst = &x;
|
||||
}
|
||||
if (input->src == NULL) {
|
||||
assert(input->size == 0);
|
||||
input->src = &x;
|
||||
}
|
||||
DEBUGLOG(5, "ZSTD_decompressLegacyStream for v0.%u", version);
|
||||
switch(version)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
******************************************/
|
||||
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||
#include "zstd_v01.h"
|
||||
#include "../common/compiler.h"
|
||||
#include "../common/error_private.h"
|
||||
|
||||
|
||||
@@ -2118,6 +2119,7 @@ size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSi
|
||||
}
|
||||
ctx->phase = 1;
|
||||
ctx->expected = ZSTD_blockHeaderSize;
|
||||
if (ZSTDv01_isError(rSize)) return rSize;
|
||||
ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);
|
||||
return rSize;
|
||||
}
|
||||
|
||||
+4
-16
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||
#include "zstd_v02.h"
|
||||
#include "../common/compiler.h"
|
||||
#include "../common/error_private.h"
|
||||
|
||||
|
||||
@@ -71,20 +72,6 @@ extern "C" {
|
||||
#include <string.h> /* memcpy */
|
||||
|
||||
|
||||
/******************************************
|
||||
* Compiler-specific
|
||||
******************************************/
|
||||
#if defined(__GNUC__)
|
||||
# define MEM_STATIC static __attribute__((unused))
|
||||
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
# define MEM_STATIC static inline
|
||||
#elif defined(_MSC_VER)
|
||||
# define MEM_STATIC static __inline
|
||||
#else
|
||||
# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
||||
#endif
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Basic Types
|
||||
*****************************************************************/
|
||||
@@ -875,7 +862,7 @@ extern "C" {
|
||||
* Streaming functions
|
||||
***************************************/
|
||||
|
||||
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
|
||||
typedef struct ZSTDv02_Dctx_s ZSTD_DCtx;
|
||||
|
||||
/*
|
||||
Use above functions alternatively.
|
||||
@@ -2750,7 +2737,7 @@ static unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }
|
||||
/* *************************************************************
|
||||
* Decompression section
|
||||
***************************************************************/
|
||||
struct ZSTD_DCtx_s
|
||||
struct ZSTDv02_Dctx_s
|
||||
{
|
||||
U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
|
||||
U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
|
||||
@@ -3431,6 +3418,7 @@ static size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSi
|
||||
}
|
||||
ctx->phase = 1;
|
||||
ctx->expected = ZSTD_blockHeaderSize;
|
||||
if (ZSTD_isError(rSize)) return rSize;
|
||||
ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);
|
||||
return rSize;
|
||||
}
|
||||
|
||||
+4
-16
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||
#include "zstd_v03.h"
|
||||
#include "../common/compiler.h"
|
||||
#include "../common/error_private.h"
|
||||
|
||||
|
||||
@@ -72,20 +73,6 @@ extern "C" {
|
||||
#include <string.h> /* memcpy */
|
||||
|
||||
|
||||
/******************************************
|
||||
* Compiler-specific
|
||||
******************************************/
|
||||
#if defined(__GNUC__)
|
||||
# define MEM_STATIC static __attribute__((unused))
|
||||
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
# define MEM_STATIC static inline
|
||||
#elif defined(_MSC_VER)
|
||||
# define MEM_STATIC static __inline
|
||||
#else
|
||||
# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
||||
#endif
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Basic Types
|
||||
*****************************************************************/
|
||||
@@ -875,7 +862,7 @@ extern "C" {
|
||||
* Streaming functions
|
||||
***************************************/
|
||||
|
||||
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
|
||||
typedef struct ZSTDv03_Dctx_s ZSTD_DCtx;
|
||||
|
||||
/*
|
||||
Use above functions alternatively.
|
||||
@@ -2390,7 +2377,7 @@ static unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }
|
||||
/* *************************************************************
|
||||
* Decompression section
|
||||
***************************************************************/
|
||||
struct ZSTD_DCtx_s
|
||||
struct ZSTDv03_Dctx_s
|
||||
{
|
||||
U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
|
||||
U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
|
||||
@@ -3071,6 +3058,7 @@ static size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSi
|
||||
}
|
||||
ctx->phase = 1;
|
||||
ctx->expected = ZSTD_blockHeaderSize;
|
||||
if (ZSTD_isError(rSize)) return rSize;
|
||||
ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);
|
||||
return rSize;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <string.h> /* memcpy */
|
||||
|
||||
#include "zstd_v04.h"
|
||||
#include "../common/compiler.h"
|
||||
#include "../common/error_private.h"
|
||||
|
||||
|
||||
@@ -3209,6 +3210,7 @@ static size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSi
|
||||
}
|
||||
ctx->stage = ZSTDds_decodeBlockHeader;
|
||||
ctx->expected = ZSTD_blockHeaderSize;
|
||||
if (ZSTD_isError(rSize)) return rSize;
|
||||
ctx->previousDstEnd = (char*)dst + rSize;
|
||||
return rSize;
|
||||
}
|
||||
@@ -3536,8 +3538,8 @@ static size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbc, void* dst, size_t* maxDs
|
||||
unsigned ZBUFFv04_isError(size_t errorCode) { return ERR_isError(errorCode); }
|
||||
const char* ZBUFFv04_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
|
||||
|
||||
size_t ZBUFFv04_recommendedDInSize() { return BLOCKSIZE + 3; }
|
||||
size_t ZBUFFv04_recommendedDOutSize() { return BLOCKSIZE; }
|
||||
size_t ZBUFFv04_recommendedDInSize(void) { return BLOCKSIZE + 3; }
|
||||
size_t ZBUFFv04_recommendedDOutSize(void) { return BLOCKSIZE; }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3600,6 +3600,7 @@ size_t ZSTDv05_decompressContinue(ZSTDv05_DCtx* dctx, void* dst, size_t maxDstSi
|
||||
}
|
||||
dctx->stage = ZSTDv05ds_decodeBlockHeader;
|
||||
dctx->expected = ZSTDv05_blockHeaderSize;
|
||||
if (ZSTDv05_isError(rSize)) return rSize;
|
||||
dctx->previousDstEnd = (char*)dst + rSize;
|
||||
return rSize;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||
#include <string.h> /* memcpy */
|
||||
#include <stdlib.h> /* malloc, free, qsort */
|
||||
#include "../common/compiler.h"
|
||||
#include "../common/error_private.h"
|
||||
|
||||
|
||||
@@ -3736,6 +3737,7 @@ size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapac
|
||||
}
|
||||
dctx->stage = ZSTDds_decodeBlockHeader;
|
||||
dctx->expected = ZSTDv06_blockHeaderSize;
|
||||
if (ZSTDv06_isError(rSize)) return rSize;
|
||||
dctx->previousDstEnd = (char*)dst + rSize;
|
||||
return rSize;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define HUFv07_STATIC_LINKING_ONLY /* HUFv07_TABLELOG_ABSOLUTEMAX */
|
||||
#define ZSTDv07_STATIC_LINKING_ONLY
|
||||
|
||||
#include "../common/compiler.h"
|
||||
#include "../common/error_private.h"
|
||||
|
||||
|
||||
@@ -4006,8 +4007,8 @@ size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapac
|
||||
}
|
||||
dctx->stage = ZSTDds_decodeBlockHeader;
|
||||
dctx->expected = ZSTDv07_blockHeaderSize;
|
||||
dctx->previousDstEnd = (char*)dst + rSize;
|
||||
if (ZSTDv07_isError(rSize)) return rSize;
|
||||
dctx->previousDstEnd = (char*)dst + rSize;
|
||||
if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
|
||||
return rSize;
|
||||
}
|
||||
|
||||
+23
-11
@@ -8,12 +8,21 @@
|
||||
# You may select, at your option, one of the above-listed licenses.
|
||||
# ################################################################
|
||||
|
||||
# This included Makefile provides the following variables :
|
||||
# LIB_SRCDIR, LIB_BINDIR
|
||||
|
||||
# Ensure the file is not included twice
|
||||
# Note : must be included after setting the default target
|
||||
ifndef LIBZSTD_MK_INCLUDED
|
||||
LIBZSTD_MK_INCLUDED := 1
|
||||
|
||||
##################################################################
|
||||
# Input Variables
|
||||
##################################################################
|
||||
|
||||
# Zstd lib directory
|
||||
LIBZSTD ?= ./
|
||||
# By default, library's directory is same as this included makefile
|
||||
LIB_SRCDIR ?= $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
LIB_BINDIR ?= $(LIBSRC_DIR)
|
||||
|
||||
# ZSTD_LIB_MINIFY is a helper variable that
|
||||
# configures a bunch of other variables to space-optimized defaults.
|
||||
@@ -60,6 +69,7 @@ VOID ?= /dev/null
|
||||
NUM_SYMBOL := \#
|
||||
|
||||
# define silent mode as default (verbose mode with V=1 or VERBOSE=1)
|
||||
# Note : must be defined _after_ the default target
|
||||
$(V)$(VERBOSE).SILENT:
|
||||
|
||||
# When cross-compiling from linux to windows,
|
||||
@@ -69,7 +79,7 @@ $(V)$(VERBOSE).SILENT:
|
||||
TARGET_SYSTEM ?= $(OS)
|
||||
|
||||
# Version numbers
|
||||
LIBVER_SRC := $(LIBZSTD)/zstd.h
|
||||
LIBVER_SRC := $(LIB_SRCDIR)/zstd.h
|
||||
LIBVER_MAJOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)`
|
||||
LIBVER_MINOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)`
|
||||
LIBVER_PATCH_SCRIPT:=`sed -n '/define ZSTD_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)`
|
||||
@@ -136,14 +146,14 @@ ifeq ($(HAVE_COLORNEVER), 1)
|
||||
endif
|
||||
GREP = grep $(GREP_OPTIONS)
|
||||
|
||||
ZSTD_COMMON_FILES := $(sort $(wildcard $(LIBZSTD)/common/*.c))
|
||||
ZSTD_COMPRESS_FILES := $(sort $(wildcard $(LIBZSTD)/compress/*.c))
|
||||
ZSTD_DECOMPRESS_FILES := $(sort $(wildcard $(LIBZSTD)/decompress/*.c))
|
||||
ZSTD_DICTBUILDER_FILES := $(sort $(wildcard $(LIBZSTD)/dictBuilder/*.c))
|
||||
ZSTD_DEPRECATED_FILES := $(sort $(wildcard $(LIBZSTD)/deprecated/*.c))
|
||||
ZSTD_COMMON_FILES := $(sort $(wildcard $(LIB_SRCDIR)/common/*.c))
|
||||
ZSTD_COMPRESS_FILES := $(sort $(wildcard $(LIB_SRCDIR)/compress/*.c))
|
||||
ZSTD_DECOMPRESS_FILES := $(sort $(wildcard $(LIB_SRCDIR)/decompress/*.c))
|
||||
ZSTD_DICTBUILDER_FILES := $(sort $(wildcard $(LIB_SRCDIR)/dictBuilder/*.c))
|
||||
ZSTD_DEPRECATED_FILES := $(sort $(wildcard $(LIB_SRCDIR)/deprecated/*.c))
|
||||
ZSTD_LEGACY_FILES :=
|
||||
|
||||
ZSTD_DECOMPRESS_AMD64_ASM_FILES := $(sort $(wildcard $(LIBZSTD)/decompress/*_amd64.S))
|
||||
ZSTD_DECOMPRESS_AMD64_ASM_FILES := $(sort $(wildcard $(LIB_SRCDIR)/decompress/*_amd64.S))
|
||||
|
||||
ifneq ($(ZSTD_NO_ASM), 0)
|
||||
CPPFLAGS += -DZSTD_DISABLE_ASM
|
||||
@@ -191,7 +201,7 @@ endif
|
||||
|
||||
ifneq ($(ZSTD_LEGACY_SUPPORT), 0)
|
||||
ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0)
|
||||
ZSTD_LEGACY_FILES += $(shell ls $(LIBZSTD)/legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]')
|
||||
ZSTD_LEGACY_FILES += $(shell ls $(LIB_SRCDIR)/legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]')
|
||||
endif
|
||||
endif
|
||||
CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
||||
@@ -220,6 +230,8 @@ ifeq ($(HAVE_HASH),0)
|
||||
endif
|
||||
endif # BUILD_DIR
|
||||
|
||||
ZSTD_SUBDIR := $(LIBZSTD)/common $(LIBZSTD)/compress $(LIBZSTD)/decompress $(LIBZSTD)/dictBuilder $(LIBZSTD)/legacy $(LIBZSTD)/deprecated
|
||||
ZSTD_SUBDIR := $(LIB_SRCDIR)/common $(LIB_SRCDIR)/compress $(LIB_SRCDIR)/decompress $(LIB_SRCDIR)/dictBuilder $(LIB_SRCDIR)/legacy $(LIB_SRCDIR)/deprecated
|
||||
vpath %.c $(ZSTD_SUBDIR)
|
||||
vpath %.S $(ZSTD_SUBDIR)
|
||||
|
||||
endif # LIBZSTD_MK_INCLUDED
|
||||
|
||||
+86
-41
@@ -106,7 +106,7 @@ extern "C" {
|
||||
/*------ Version ------*/
|
||||
#define ZSTD_VERSION_MAJOR 1
|
||||
#define ZSTD_VERSION_MINOR 5
|
||||
#define ZSTD_VERSION_RELEASE 5
|
||||
#define ZSTD_VERSION_RELEASE 6
|
||||
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
|
||||
|
||||
/*! ZSTD_versionNumber() :
|
||||
@@ -249,7 +249,7 @@ ZSTDLIB_API int ZSTD_defaultCLevel(void); /*!< default 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.
|
||||
* and reuse it for each successive compression operation.
|
||||
* This will make workload friendlier for system's memory.
|
||||
* Note : re-using context is just a speed / resource optimization.
|
||||
* It doesn't change the compression ratio, which remains identical.
|
||||
@@ -262,9 +262,9 @@ ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /* accept NULL pointer *
|
||||
|
||||
/*! ZSTD_compressCCtx() :
|
||||
* Same as ZSTD_compress(), using an explicit ZSTD_CCtx.
|
||||
* Important : in order to behave similarly to `ZSTD_compress()`,
|
||||
* this function compresses at requested compression level,
|
||||
* __ignoring any other parameter__ .
|
||||
* Important : in order to mirror `ZSTD_compress()` behavior,
|
||||
* this function compresses at the requested compression level,
|
||||
* __ignoring any other advanced parameter__ .
|
||||
* If any advanced parameter was set using the advanced API,
|
||||
* they will all be reset. Only `compressionLevel` remains.
|
||||
*/
|
||||
@@ -276,7 +276,7 @@ ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
|
||||
/*= Decompression context
|
||||
* When decompressing many times,
|
||||
* it is recommended to allocate a context only once,
|
||||
* and re-use it for each successive compression operation.
|
||||
* and reuse it for each successive compression operation.
|
||||
* This will make workload friendlier for system's memory.
|
||||
* Use one context per thread for parallel execution. */
|
||||
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
|
||||
@@ -286,7 +286,7 @@ ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer *
|
||||
/*! ZSTD_decompressDCtx() :
|
||||
* Same as ZSTD_decompress(),
|
||||
* requires an allocated ZSTD_DCtx.
|
||||
* Compatible with sticky parameters.
|
||||
* Compatible with sticky parameters (see below).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
@@ -302,12 +302,12 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
|
||||
* using ZSTD_CCtx_set*() functions.
|
||||
* Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame.
|
||||
* "sticky" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` !
|
||||
* __They do not apply to "simple" one-shot variants such as ZSTD_compressCCtx()__ .
|
||||
* __They do not apply to one-shot variants such as ZSTD_compressCCtx()__ .
|
||||
*
|
||||
* It's possible to reset all parameters to "default" using ZSTD_CCtx_reset().
|
||||
*
|
||||
* This API supersedes all other "advanced" API entry points in the experimental section.
|
||||
* In the future, we expect to remove from experimental API entry points which are redundant with this API.
|
||||
* In the future, we expect to remove API entry points from experimental which are redundant with this API.
|
||||
*/
|
||||
|
||||
|
||||
@@ -390,6 +390,19 @@ typedef enum {
|
||||
* The higher the value of selected strategy, the more complex it is,
|
||||
* resulting in stronger and slower compression.
|
||||
* Special: value 0 means "use default strategy". */
|
||||
|
||||
ZSTD_c_targetCBlockSize=130, /* v1.5.6+
|
||||
* Attempts to fit compressed block size into approximatively targetCBlockSize.
|
||||
* Bound by ZSTD_TARGETCBLOCKSIZE_MIN and ZSTD_TARGETCBLOCKSIZE_MAX.
|
||||
* Note that it's not a guarantee, just a convergence target (default:0).
|
||||
* No target when targetCBlockSize == 0.
|
||||
* This is helpful in low bandwidth streaming environments to improve end-to-end latency,
|
||||
* when a client can make use of partial documents (a prominent example being Chrome).
|
||||
* Note: this parameter is stable since v1.5.6.
|
||||
* It was present as an experimental parameter in earlier versions,
|
||||
* but it's not recommended using it with earlier library versions
|
||||
* due to massive performance regressions.
|
||||
*/
|
||||
/* LDM mode parameters */
|
||||
ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching.
|
||||
* This parameter is designed to improve compression ratio
|
||||
@@ -469,7 +482,6 @@ typedef enum {
|
||||
* ZSTD_c_forceMaxWindow
|
||||
* ZSTD_c_forceAttachDict
|
||||
* ZSTD_c_literalCompressionMode
|
||||
* ZSTD_c_targetCBlockSize
|
||||
* ZSTD_c_srcSizeHint
|
||||
* ZSTD_c_enableDedicatedDictSearch
|
||||
* ZSTD_c_stableInBuffer
|
||||
@@ -490,7 +502,7 @@ typedef enum {
|
||||
ZSTD_c_experimentalParam3=1000,
|
||||
ZSTD_c_experimentalParam4=1001,
|
||||
ZSTD_c_experimentalParam5=1002,
|
||||
ZSTD_c_experimentalParam6=1003,
|
||||
/* was ZSTD_c_experimentalParam6=1003; is now ZSTD_c_targetCBlockSize */
|
||||
ZSTD_c_experimentalParam7=1004,
|
||||
ZSTD_c_experimentalParam8=1005,
|
||||
ZSTD_c_experimentalParam9=1006,
|
||||
@@ -575,6 +587,7 @@ 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.
|
||||
* (note that this entry point doesn't even expose a compression level parameter).
|
||||
* 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*()
|
||||
@@ -682,14 +695,14 @@ typedef struct ZSTD_outBuffer_s {
|
||||
* 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.
|
||||
* It is recommended to reuse 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.
|
||||
* it will reuse 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
|
||||
@@ -778,6 +791,11 @@ typedef enum {
|
||||
* 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.
|
||||
* - note: if an operation ends with an error, it may leave @cctx in an undefined state.
|
||||
* Therefore, it's UB to invoke ZSTD_compressStream2() of ZSTD_compressStream() on such a state.
|
||||
* In order to be re-employed after an error, a state must be reset,
|
||||
* which can be done explicitly (ZSTD_CCtx_reset()),
|
||||
* or is sometimes implied by methods starting a new compression job (ZSTD_initCStream(), ZSTD_compressCCtx())
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||
ZSTD_outBuffer* output,
|
||||
@@ -837,7 +855,7 @@ ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
|
||||
*
|
||||
* 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.
|
||||
* ZSTD_DStream objects can be reused multiple times.
|
||||
*
|
||||
* Use ZSTD_initDStream() to start a new decompression operation.
|
||||
* @return : recommended first input size
|
||||
@@ -891,6 +909,12 @@ ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
|
||||
* @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 some decoding or flushing to do to complete current frame.
|
||||
*
|
||||
* Note: when an operation returns with an error code, the @zds state may be left in undefined state.
|
||||
* It's UB to invoke `ZSTD_decompressStream()` on such a state.
|
||||
* In order to re-use such a state, it must be first reset,
|
||||
* which can be done explicitly (`ZSTD_DCtx_reset()`),
|
||||
* or is implied for operations starting some new decompression job (`ZSTD_initDStream`, `ZSTD_decompressDCtx()`, `ZSTD_decompress_usingDict()`)
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||
|
||||
@@ -1023,7 +1047,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
*
|
||||
* This API allows dictionaries to be used with ZSTD_compress2(),
|
||||
* ZSTD_compressStream2(), and ZSTD_decompressDCtx().
|
||||
* Dictionaries are sticky, they remain valid when same context is re-used,
|
||||
* Dictionaries are sticky, they remain valid when same context is reused,
|
||||
* they only reset when the context is reset
|
||||
* with ZSTD_reset_parameters or ZSTD_reset_session_and_parameters.
|
||||
* In contrast, Prefixes are single-use.
|
||||
@@ -1241,7 +1265,7 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
#define ZSTD_LDM_HASHRATELOG_MAX (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
|
||||
|
||||
/* Advanced parameter bounds */
|
||||
#define ZSTD_TARGETCBLOCKSIZE_MIN 64
|
||||
#define ZSTD_TARGETCBLOCKSIZE_MIN 1340 /* suitable to fit into an ethernet / wifi / 4G transport frame */
|
||||
#define ZSTD_TARGETCBLOCKSIZE_MAX ZSTD_BLOCKSIZE_MAX
|
||||
#define ZSTD_SRCSIZEHINT_MIN 0
|
||||
#define ZSTD_SRCSIZEHINT_MAX INT_MAX
|
||||
@@ -1529,25 +1553,38 @@ typedef enum {
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize);
|
||||
|
||||
/*! ZSTD_generateSequences() :
|
||||
* WARNING: This function is meant for debugging and informational purposes ONLY!
|
||||
* Its implementation is flawed, and it will be deleted in a future version.
|
||||
* It is not guaranteed to succeed, as there are several cases where it will give
|
||||
* up and fail. You should NOT use this function in production code.
|
||||
*
|
||||
* This function is deprecated, and will be removed in a future version.
|
||||
*
|
||||
* Generate sequences using ZSTD_compress2(), given a source buffer.
|
||||
*
|
||||
* @param zc The compression context to be used for ZSTD_compress2(). Set any
|
||||
* compression parameters you need on this context.
|
||||
* @param outSeqs The output sequences buffer of size @p outSeqsSize
|
||||
* @param outSeqsSize The size of the output sequences buffer.
|
||||
* ZSTD_sequenceBound(srcSize) is an upper bound on the number
|
||||
* of sequences that can be generated.
|
||||
* @param src The source buffer to generate sequences from of size @p srcSize.
|
||||
* @param srcSize The size of the source buffer.
|
||||
*
|
||||
* Each block will end with a dummy sequence
|
||||
* with offset == 0, matchLength == 0, and litLength == length of last literals.
|
||||
* litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0)
|
||||
* simply acts as a block delimiter.
|
||||
*
|
||||
* @zc can be used to insert custom compression params.
|
||||
* This function invokes ZSTD_compress2().
|
||||
*
|
||||
* The output of this function can be fed into ZSTD_compressSequences() with CCtx
|
||||
* setting of ZSTD_c_blockDelimiters as ZSTD_sf_explicitBlockDelimiters
|
||||
* @return : number of sequences generated
|
||||
* @returns The number of sequences generated, necessarily less than
|
||||
* ZSTD_sequenceBound(srcSize), or an error code that can be checked
|
||||
* with ZSTD_isError().
|
||||
*/
|
||||
|
||||
ZSTD_DEPRECATED("For debugging only, will be replaced by ZSTD_extractSequences()")
|
||||
ZSTDLIB_STATIC_API size_t
|
||||
ZSTD_generateSequences( ZSTD_CCtx* zc,
|
||||
ZSTD_Sequence* outSeqs, size_t outSeqsSize,
|
||||
const void* src, size_t srcSize);
|
||||
ZSTD_generateSequences(ZSTD_CCtx* zc,
|
||||
ZSTD_Sequence* outSeqs, size_t outSeqsSize,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_mergeBlockDelimiters() :
|
||||
* Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals
|
||||
@@ -1665,9 +1702,6 @@ ZSTDLIB_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);
|
||||
*
|
||||
* Note : only single-threaded compression is supported.
|
||||
* ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
*
|
||||
* Note 2 : ZSTD_estimateCCtxSize* functions are not compatible with the Block-Level Sequence Producer API at this time.
|
||||
* Size estimates assume that no external sequence producer is registered.
|
||||
*/
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int maxCompressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
@@ -1954,11 +1988,6 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo
|
||||
*/
|
||||
#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
|
||||
|
||||
/* User's best guess of source size.
|
||||
* Hint is not valid when srcSizeHint == 0.
|
||||
* There is no guarantee that hint is close to actual source size,
|
||||
@@ -2581,7 +2610,7 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
||||
* explicitly specified.
|
||||
*
|
||||
* 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.
|
||||
* This is typically useful to skip dictionary loading stage, since it will reuse 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.
|
||||
* If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.
|
||||
@@ -2657,7 +2686,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const Z
|
||||
*
|
||||
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
*
|
||||
* re-use decompression parameters from previous init; saves dictionary loading
|
||||
* reuse decompression parameters from previous init; saves dictionary loading
|
||||
*/
|
||||
ZSTD_DEPRECATED("use ZSTD_DCtx_reset, see zstd.h for detailed instructions")
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
@@ -2789,7 +2818,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
|
||||
#define ZSTD_SEQUENCE_PRODUCER_ERROR ((size_t)(-1))
|
||||
|
||||
typedef size_t ZSTD_sequenceProducer_F (
|
||||
typedef size_t (*ZSTD_sequenceProducer_F) (
|
||||
void* sequenceProducerState,
|
||||
ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
@@ -2821,7 +2850,23 @@ ZSTDLIB_STATIC_API void
|
||||
ZSTD_registerSequenceProducer(
|
||||
ZSTD_CCtx* cctx,
|
||||
void* sequenceProducerState,
|
||||
ZSTD_sequenceProducer_F* sequenceProducer
|
||||
ZSTD_sequenceProducer_F sequenceProducer
|
||||
);
|
||||
|
||||
/*! ZSTD_CCtxParams_registerSequenceProducer() :
|
||||
* Same as ZSTD_registerSequenceProducer(), but operates on ZSTD_CCtx_params.
|
||||
* This is used for accurate size estimation with ZSTD_estimateCCtxSize_usingCCtxParams(),
|
||||
* which is needed when creating a ZSTD_CCtx with ZSTD_initStaticCCtx().
|
||||
*
|
||||
* If you are using the external sequence producer API in a scenario where ZSTD_initStaticCCtx()
|
||||
* is required, then this function is for you. Otherwise, you probably don't need it.
|
||||
*
|
||||
* See tests/zstreamtest.c for example usage. */
|
||||
ZSTDLIB_STATIC_API void
|
||||
ZSTD_CCtxParams_registerSequenceProducer(
|
||||
ZSTD_CCtx_params* params,
|
||||
void* sequenceProducerState,
|
||||
ZSTD_sequenceProducer_F sequenceProducer
|
||||
);
|
||||
|
||||
|
||||
@@ -2844,7 +2889,7 @@ ZSTD_registerSequenceProducer(
|
||||
|
||||
A ZSTD_CCtx object is required to track streaming operations.
|
||||
Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.
|
||||
ZSTD_CCtx object can be re-used multiple times within successive compression operations.
|
||||
ZSTD_CCtx object can be reused multiple times within successive compression operations.
|
||||
|
||||
Start by initializing a context.
|
||||
Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression.
|
||||
@@ -2865,7 +2910,7 @@ ZSTD_registerSequenceProducer(
|
||||
It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.
|
||||
Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders.
|
||||
|
||||
`ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again.
|
||||
`ZSTD_CCtx` object can be reused (ZSTD_compressBegin()) to compress again.
|
||||
*/
|
||||
|
||||
/*===== Buffer-less streaming compression functions =====*/
|
||||
@@ -2897,7 +2942,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_
|
||||
|
||||
A ZSTD_DCtx object is required to track streaming operations.
|
||||
Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
|
||||
A ZSTD_DCtx object can be re-used multiple times.
|
||||
A ZSTD_DCtx object can be reused multiple times.
|
||||
|
||||
First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader().
|
||||
Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough.
|
||||
|
||||
+5
-6
@@ -15,12 +15,11 @@
|
||||
# zstd-decompress : decompressor-only version of zstd
|
||||
# ##########################################################################
|
||||
|
||||
.PHONY: default
|
||||
default: zstd-release
|
||||
# default target (when running `make` with no argument)
|
||||
zstd-release:
|
||||
|
||||
LIBZSTD := ../lib
|
||||
|
||||
include $(LIBZSTD)/libzstd.mk
|
||||
LIBZSTD_MK_DIR = ../lib
|
||||
include $(LIBZSTD_MK_DIR)/libzstd.mk
|
||||
|
||||
ifeq ($(shell $(CC) -v 2>&1 | $(GREP) -c "gcc version "), 1)
|
||||
ALIGN_LOOP = -falign-loops=32
|
||||
@@ -223,7 +222,7 @@ zstd-noxz : zstd
|
||||
|
||||
## zstd-dll: zstd executable linked to dynamic library libzstd (must have same version)
|
||||
.PHONY: zstd-dll
|
||||
zstd-dll : LDFLAGS+= -L$(LIBZSTD)
|
||||
zstd-dll : LDFLAGS+= -L$(LIB_BINDIR)
|
||||
zstd-dll : LDLIBS += -lzstd
|
||||
zstd-dll : ZSTDLIB_LOCAL_SRC = xxhash.c pool.c threading.c
|
||||
zstd-dll : zstd
|
||||
|
||||
+2
-2
@@ -108,7 +108,6 @@ static BMK_runOutcome_t BMK_setValid_runTime(BMK_runTime_t runTime)
|
||||
BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
|
||||
unsigned nbLoops)
|
||||
{
|
||||
size_t dstSize = 0;
|
||||
nbLoops += !nbLoops; /* minimum nbLoops is 1 */
|
||||
|
||||
/* init */
|
||||
@@ -118,7 +117,8 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
|
||||
} }
|
||||
|
||||
/* benchmark */
|
||||
{ UTIL_time_t const clockStart = UTIL_getTime();
|
||||
{ size_t dstSize = 0;
|
||||
UTIL_time_t const clockStart = UTIL_getTime();
|
||||
unsigned loopNb, blockNb;
|
||||
if (p.initFn != NULL) p.initFn(p.initPayload);
|
||||
for (loopNb = 0; loopNb < nbLoops; loopNb++) {
|
||||
|
||||
+768
-418
File diff suppressed because it is too large
Load Diff
@@ -100,6 +100,7 @@ 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*/
|
||||
size_t targetCBlockSize;/* Approximative size of compressed blocks */
|
||||
int nbWorkers; /* multithreading */
|
||||
unsigned realTime; /* real time priority */
|
||||
int additionalParam; /* used by python speed benchmark */
|
||||
@@ -126,11 +127,12 @@ int BMK_benchFilesAdvanced(
|
||||
|
||||
/*! BMK_syntheticTest() -- called from zstdcli */
|
||||
/* Generates a sample with datagen, using compressibility argument */
|
||||
/* cLevel - compression level to benchmark, errors if invalid
|
||||
* compressibility - determines compressibility of sample
|
||||
* compressionParams - basic compression Parameters
|
||||
* displayLevel - see benchFiles
|
||||
* adv - see advanced_Params_t
|
||||
/* @cLevel - compression level to benchmark, errors if invalid
|
||||
* @compressibility - determines compressibility of sample, range [0.0 - 1.0]
|
||||
* if @compressibility < 0.0, uses the lorem ipsum generator
|
||||
* @compressionParams - basic compression Parameters
|
||||
* @displayLevel - see benchFiles
|
||||
* @adv - see advanced_Params_t
|
||||
* @return: 0 on success, !0 on error
|
||||
*/
|
||||
int BMK_syntheticTest(int cLevel, double compressibility,
|
||||
|
||||
+119
-14
@@ -527,7 +527,7 @@ static int FIO_removeFile(const char* path)
|
||||
DISPLAYLEVEL(2, "zstd: Refusing to remove non-regular file %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
#if defined(_WIN32)
|
||||
/* windows doesn't allow remove read-only files,
|
||||
* so try to make it writable first */
|
||||
if (!(statbuf.st_mode & _S_IWRITE)) {
|
||||
@@ -1096,15 +1096,15 @@ static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs,
|
||||
comprParams->windowLog = MAX(ZSTD_WINDOWLOG_MIN, MIN(ZSTD_WINDOWLOG_MAX, fileWindowLog));
|
||||
if (fileWindowLog > ZSTD_cycleLog(cParams.chainLog, cParams.strategy)) {
|
||||
if (!prefs->ldmFlag)
|
||||
DISPLAYLEVEL(1, "long mode automatically triggered\n");
|
||||
DISPLAYLEVEL(2, "long mode automatically triggered\n");
|
||||
FIO_setLdmFlag(prefs, 1);
|
||||
}
|
||||
if (cParams.strategy >= ZSTD_btopt) {
|
||||
DISPLAYLEVEL(1, "[Optimal parser notes] Consider the following to improve patch size at the cost of speed:\n");
|
||||
DISPLAYLEVEL(1, "- Use --single-thread mode in the zstd cli\n");
|
||||
DISPLAYLEVEL(1, "- Set a larger targetLength (e.g. --zstd=targetLength=4096)\n");
|
||||
DISPLAYLEVEL(1, "- Set a larger chainLog (e.g. --zstd=chainLog=%u)\n", ZSTD_CHAINLOG_MAX);
|
||||
DISPLAYLEVEL(1, "Also consider playing around with searchLog and hashLog\n");
|
||||
DISPLAYLEVEL(3, "[Optimal parser notes] Consider the following to improve patch size at the cost of speed:\n");
|
||||
DISPLAYLEVEL(3, "- Use --single-thread mode in the zstd cli\n");
|
||||
DISPLAYLEVEL(3, "- Set a larger targetLength (e.g. --zstd=targetLength=4096)\n");
|
||||
DISPLAYLEVEL(3, "- Set a larger chainLog (e.g. --zstd=chainLog=%u)\n", ZSTD_CHAINLOG_MAX);
|
||||
DISPLAYLEVEL(3, "Also consider playing around with searchLog and hashLog\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1839,7 +1839,6 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
|
||||
int closeDstFile = 0;
|
||||
int result;
|
||||
int transferStat = 0;
|
||||
FILE *dstFile;
|
||||
int dstFd = -1;
|
||||
|
||||
assert(AIO_ReadPool_getFile(ress.readCtx) != NULL);
|
||||
@@ -1854,10 +1853,11 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
|
||||
|
||||
closeDstFile = 1;
|
||||
DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s \n", dstFileName);
|
||||
dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFileInitialPermissions);
|
||||
if (dstFile==NULL) return 1; /* could not open dstFileName */
|
||||
dstFd = fileno(dstFile);
|
||||
AIO_WritePool_setFile(ress.writeCtx, dstFile);
|
||||
{ FILE *dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFileInitialPermissions);
|
||||
if (dstFile==NULL) return 1; /* could not open dstFileName */
|
||||
dstFd = fileno(dstFile);
|
||||
AIO_WritePool_setFile(ress.writeCtx, dstFile);
|
||||
}
|
||||
/* Must only be added after FIO_openDstFile() succeeds.
|
||||
* Otherwise we may delete the destination file if it already exists,
|
||||
* and the user presses Ctrl-C when asked if they wish to overwrite.
|
||||
@@ -1907,6 +1907,110 @@ static const char *compressedFileExtensions[] = {
|
||||
TXZ_EXTENSION,
|
||||
LZ4_EXTENSION,
|
||||
TLZ4_EXTENSION,
|
||||
".7z",
|
||||
".aa3",
|
||||
".aac",
|
||||
".aar",
|
||||
".ace",
|
||||
".alac",
|
||||
".ape",
|
||||
".apk",
|
||||
".apng",
|
||||
".arc",
|
||||
".archive",
|
||||
".arj",
|
||||
".ark",
|
||||
".asf",
|
||||
".avi",
|
||||
".avif",
|
||||
".ba",
|
||||
".br",
|
||||
".bz2",
|
||||
".cab",
|
||||
".cdx",
|
||||
".chm",
|
||||
".cr2",
|
||||
".divx",
|
||||
".dmg",
|
||||
".dng",
|
||||
".docm",
|
||||
".docx",
|
||||
".dotm",
|
||||
".dotx",
|
||||
".dsft",
|
||||
".ear",
|
||||
".eftx",
|
||||
".emz",
|
||||
".eot",
|
||||
".epub",
|
||||
".f4v",
|
||||
".flac",
|
||||
".flv",
|
||||
".gho",
|
||||
".gif",
|
||||
".gifv",
|
||||
".gnp",
|
||||
".iso",
|
||||
".jar",
|
||||
".jpeg",
|
||||
".jpg",
|
||||
".jxl",
|
||||
".lz",
|
||||
".lzh",
|
||||
".m4a",
|
||||
".m4v",
|
||||
".mkv",
|
||||
".mov",
|
||||
".mp2",
|
||||
".mp3",
|
||||
".mp4",
|
||||
".mpa",
|
||||
".mpc",
|
||||
".mpe",
|
||||
".mpeg",
|
||||
".mpg",
|
||||
".mpl",
|
||||
".mpv",
|
||||
".msi",
|
||||
".odp",
|
||||
".ods",
|
||||
".odt",
|
||||
".ogg",
|
||||
".ogv",
|
||||
".otp",
|
||||
".ots",
|
||||
".ott",
|
||||
".pea",
|
||||
".png",
|
||||
".pptx",
|
||||
".qt",
|
||||
".rar",
|
||||
".s7z",
|
||||
".sfx",
|
||||
".sit",
|
||||
".sitx",
|
||||
".sqx",
|
||||
".svgz",
|
||||
".swf",
|
||||
".tbz2",
|
||||
".tib",
|
||||
".tlz",
|
||||
".vob",
|
||||
".war",
|
||||
".webm",
|
||||
".webp",
|
||||
".wma",
|
||||
".wmv",
|
||||
".woff",
|
||||
".woff2",
|
||||
".wvl",
|
||||
".xlsx",
|
||||
".xpi",
|
||||
".xps",
|
||||
".zip",
|
||||
".zipx",
|
||||
".zoo",
|
||||
".zpaq",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -2337,9 +2441,10 @@ FIO_decompressZstdFrame(FIO_ctx_t* const fCtx, dRess_t* ress,
|
||||
U64 frameSize = 0;
|
||||
IOJob_t *writeJob = AIO_WritePool_acquireJob(ress->writeCtx);
|
||||
|
||||
/* display last 20 characters only */
|
||||
/* display last 20 characters only when not --verbose */
|
||||
{ size_t const srcFileLength = strlen(srcFileName);
|
||||
if (srcFileLength>20) srcFileName += srcFileLength-20;
|
||||
if ((srcFileLength>20) && (g_display_prefs.displayLevel<3))
|
||||
srcFileName += srcFileLength-20;
|
||||
}
|
||||
|
||||
ZSTD_DCtx_reset(ress->dctx, ZSTD_reset_session_only);
|
||||
|
||||
@@ -453,8 +453,8 @@ static IOJob_t* AIO_ReadPool_findNextWaitingOffsetCompletedJob_locked(ReadPoolCt
|
||||
/* AIO_ReadPool_numReadsInFlight:
|
||||
* Returns the number of IO read jobs currently in flight. */
|
||||
static size_t AIO_ReadPool_numReadsInFlight(ReadPoolCtx_t* ctx) {
|
||||
const size_t jobsHeld = (ctx->currentJobHeld==NULL ? 0 : 1);
|
||||
return ctx->base.totalIoJobs - (ctx->base.availableJobsCount + ctx->completedJobsCount + jobsHeld);
|
||||
const int jobsHeld = (ctx->currentJobHeld==NULL ? 0 : 1);
|
||||
return (size_t)(ctx->base.totalIoJobs - (ctx->base.availableJobsCount + ctx->completedJobsCount + jobsHeld));
|
||||
}
|
||||
|
||||
/* AIO_ReadPool_getNextCompletedJob:
|
||||
@@ -514,8 +514,7 @@ static void AIO_ReadPool_enqueueRead(ReadPoolCtx_t* ctx) {
|
||||
}
|
||||
|
||||
static void AIO_ReadPool_startReading(ReadPoolCtx_t* ctx) {
|
||||
int i;
|
||||
for (i = 0; i < ctx->base.availableJobsCount; i++) {
|
||||
while(ctx->base.availableJobsCount) {
|
||||
AIO_ReadPool_enqueueRead(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Implementation notes:
|
||||
*
|
||||
* This is a very simple lorem ipsum generator
|
||||
* which features a static list of words
|
||||
* and print them one after another randomly
|
||||
* with a fake sentence / paragraph structure.
|
||||
*
|
||||
* The goal is to generate a printable text
|
||||
* that can be used to fake a text compression scenario.
|
||||
* The resulting compression / ratio curve of the lorem ipsum generator
|
||||
* is more satisfying than the previous statistical generator,
|
||||
* which was initially designed for entropy compression,
|
||||
* and lacks a regularity more representative of text.
|
||||
*
|
||||
* The compression ratio achievable on the generated lorem ipsum
|
||||
* is still a bit too good, presumably because the dictionary is a bit too
|
||||
* small. It would be possible to create some more complex scheme, notably by
|
||||
* enlarging the dictionary with a word generator, and adding grammatical rules
|
||||
* (composition) and syntax rules. But that's probably overkill for the intended
|
||||
* goal.
|
||||
*/
|
||||
|
||||
#include "lorem.h"
|
||||
#include <assert.h>
|
||||
#include <limits.h> /* INT_MAX */
|
||||
#include <string.h> /* memcpy */
|
||||
|
||||
#define WORD_MAX_SIZE 20
|
||||
|
||||
/* Define the word pool */
|
||||
static const char* kWords[] = {
|
||||
"lorem", "ipsum", "dolor", "sit", "amet",
|
||||
"consectetur", "adipiscing", "elit", "sed", "do",
|
||||
"eiusmod", "tempor", "incididunt", "ut", "labore",
|
||||
"et", "dolore", "magna", "aliqua", "dis",
|
||||
"lectus", "vestibulum", "mattis", "ullamcorper", "velit",
|
||||
"commodo", "a", "lacus", "arcu", "magnis",
|
||||
"parturient", "montes", "nascetur", "ridiculus", "mus",
|
||||
"mauris", "nulla", "malesuada", "pellentesque", "eget",
|
||||
"gravida", "in", "dictum", "non", "erat",
|
||||
"nam", "voluptat", "maecenas", "blandit", "aliquam",
|
||||
"etiam", "enim", "lobortis", "scelerisque", "fermentum",
|
||||
"dui", "faucibus", "ornare", "at", "elementum",
|
||||
"eu", "facilisis", "odio", "morbi", "quis",
|
||||
"eros", "donec", "ac", "orci", "purus",
|
||||
"turpis", "cursus", "leo", "vel", "porta",
|
||||
"consequat", "interdum", "varius", "vulputate", "aliquet",
|
||||
"pharetra", "nunc", "auctor", "urna", "id",
|
||||
"metus", "viverra", "nibh", "cras", "mi",
|
||||
"unde", "omnis", "iste", "natus", "error",
|
||||
"perspiciatis", "voluptatem", "accusantium", "doloremque", "laudantium",
|
||||
"totam", "rem", "aperiam", "eaque", "ipsa",
|
||||
"quae", "ab", "illo", "inventore", "veritatis",
|
||||
"quasi", "architecto", "beatae", "vitae", "dicta",
|
||||
"sunt", "explicabo", "nemo", "ipsam", "quia",
|
||||
"voluptas", "aspernatur", "aut", "odit", "fugit",
|
||||
"consequuntur", "magni", "dolores", "eos", "qui",
|
||||
"ratione", "sequi", "nesciunt", "neque", "porro",
|
||||
"quisquam", "est", "dolorem", "adipisci", "numquam",
|
||||
"eius", "modi", "tempora", "incidunt", "magnam",
|
||||
"quaerat", "ad", "minima", "veniam", "nostrum",
|
||||
"ullam", "corporis", "suscipit", "laboriosam", "nisi",
|
||||
"aliquid", "ex", "ea", "commodi", "consequatur",
|
||||
"autem", "eum", "iure", "voluptate", "esse",
|
||||
"quam", "nihil", "molestiae", "illum", "fugiat",
|
||||
"quo", "pariatur", "vero", "accusamus", "iusto",
|
||||
"dignissimos", "ducimus", "blanditiis", "praesentium", "voluptatum",
|
||||
"deleniti", "atque", "corrupti", "quos", "quas",
|
||||
"molestias", "excepturi", "sint", "occaecati", "cupiditate",
|
||||
"provident", "similique", "culpa", "officia", "deserunt",
|
||||
"mollitia", "animi", "laborum", "dolorum", "fuga",
|
||||
"harum", "quidem", "rerum", "facilis", "expedita",
|
||||
"distinctio", "libero", "tempore", "cum", "soluta",
|
||||
"nobis", "eligendi", "optio", "cumque", "impedit",
|
||||
"minus", "quod", "maxime", "placeat", "facere",
|
||||
"possimus", "assumenda", "repellendus", "temporibus", "quibusdam",
|
||||
"officiis", "debitis", "saepe", "eveniet", "voluptates",
|
||||
"repudiandae", "recusandae", "itaque", "earum", "hic",
|
||||
"tenetur", "sapiente", "delectus", "reiciendis", "cillum",
|
||||
"maiores", "alias", "perferendis", "doloribus", "asperiores",
|
||||
"repellat", "minim", "nostrud", "exercitation", "ullamco",
|
||||
"laboris", "aliquip", "duis", "aute", "irure",
|
||||
};
|
||||
static const unsigned kNbWords = sizeof(kWords) / sizeof(kWords[0]);
|
||||
|
||||
/* simple 1-dimension distribution, based on word's length, favors small words
|
||||
*/
|
||||
static const int kWeights[] = { 0, 8, 6, 4, 3, 2 };
|
||||
static const size_t kNbWeights = sizeof(kWeights) / sizeof(kWeights[0]);
|
||||
|
||||
#define DISTRIB_SIZE_MAX 650
|
||||
static int g_distrib[DISTRIB_SIZE_MAX] = { 0 };
|
||||
static unsigned g_distribCount = 0;
|
||||
|
||||
static void countFreqs(
|
||||
const char* words[],
|
||||
size_t nbWords,
|
||||
const int* weights,
|
||||
size_t nbWeights)
|
||||
{
|
||||
unsigned total = 0;
|
||||
size_t w;
|
||||
for (w = 0; w < nbWords; w++) {
|
||||
size_t len = strlen(words[w]);
|
||||
int lmax;
|
||||
if (len >= nbWeights)
|
||||
len = nbWeights - 1;
|
||||
lmax = weights[len];
|
||||
total += (unsigned)lmax;
|
||||
}
|
||||
g_distribCount = total;
|
||||
assert(g_distribCount <= DISTRIB_SIZE_MAX);
|
||||
}
|
||||
|
||||
static void init_word_distrib(
|
||||
const char* words[],
|
||||
size_t nbWords,
|
||||
const int* weights,
|
||||
size_t nbWeights)
|
||||
{
|
||||
size_t w, d = 0;
|
||||
countFreqs(words, nbWords, weights, nbWeights);
|
||||
for (w = 0; w < nbWords; w++) {
|
||||
size_t len = strlen(words[w]);
|
||||
int l, lmax;
|
||||
if (len >= nbWeights)
|
||||
len = nbWeights - 1;
|
||||
lmax = weights[len];
|
||||
for (l = 0; l < lmax; l++) {
|
||||
g_distrib[d++] = (int)w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: this unit only works when invoked sequentially.
|
||||
* No concurrent access is allowed */
|
||||
static char* g_ptr = NULL;
|
||||
static size_t g_nbChars = 0;
|
||||
static size_t g_maxChars = 10000000;
|
||||
static unsigned g_randRoot = 0;
|
||||
|
||||
#define RDG_rotl32(x, r) ((x << r) | (x >> (32 - r)))
|
||||
static unsigned LOREM_rand(unsigned range)
|
||||
{
|
||||
static const unsigned prime1 = 2654435761U;
|
||||
static const unsigned prime2 = 2246822519U;
|
||||
unsigned rand32 = g_randRoot;
|
||||
rand32 *= prime1;
|
||||
rand32 ^= prime2;
|
||||
rand32 = RDG_rotl32(rand32, 13);
|
||||
g_randRoot = rand32;
|
||||
return (unsigned)(((unsigned long long)rand32 * range) >> 32);
|
||||
}
|
||||
|
||||
static void writeLastCharacters(void)
|
||||
{
|
||||
size_t lastChars = g_maxChars - g_nbChars;
|
||||
assert(g_maxChars >= g_nbChars);
|
||||
if (lastChars == 0)
|
||||
return;
|
||||
g_ptr[g_nbChars++] = '.';
|
||||
if (lastChars > 2) {
|
||||
memset(g_ptr + g_nbChars, ' ', lastChars - 2);
|
||||
}
|
||||
if (lastChars > 1) {
|
||||
g_ptr[g_maxChars - 1] = '\n';
|
||||
}
|
||||
g_nbChars = g_maxChars;
|
||||
}
|
||||
|
||||
static void generateWord(const char* word, const char* separator, int upCase)
|
||||
{
|
||||
size_t const len = strlen(word) + strlen(separator);
|
||||
if (g_nbChars + len > g_maxChars) {
|
||||
writeLastCharacters();
|
||||
return;
|
||||
}
|
||||
memcpy(g_ptr + g_nbChars, word, strlen(word));
|
||||
if (upCase) {
|
||||
static const char toUp = 'A' - 'a';
|
||||
g_ptr[g_nbChars] = (char)(g_ptr[g_nbChars] + toUp);
|
||||
}
|
||||
g_nbChars += strlen(word);
|
||||
memcpy(g_ptr + g_nbChars, separator, strlen(separator));
|
||||
g_nbChars += strlen(separator);
|
||||
}
|
||||
|
||||
static int about(unsigned target)
|
||||
{
|
||||
return (int)(LOREM_rand(target) + LOREM_rand(target) + 1);
|
||||
}
|
||||
|
||||
/* Function to generate a random sentence */
|
||||
static void generateSentence(int nbWords)
|
||||
{
|
||||
int commaPos = about(9);
|
||||
int comma2 = commaPos + about(7);
|
||||
int qmark = (LOREM_rand(11) == 7);
|
||||
const char* endSep = qmark ? "? " : ". ";
|
||||
int i;
|
||||
for (i = 0; i < nbWords; i++) {
|
||||
int const wordID = g_distrib[LOREM_rand(g_distribCount)];
|
||||
const char* const word = kWords[wordID];
|
||||
const char* sep = " ";
|
||||
if (i == commaPos)
|
||||
sep = ", ";
|
||||
if (i == comma2)
|
||||
sep = ", ";
|
||||
if (i == nbWords - 1)
|
||||
sep = endSep;
|
||||
generateWord(word, sep, i == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void generateParagraph(int nbSentences)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nbSentences; i++) {
|
||||
int wordsPerSentence = about(11);
|
||||
generateSentence(wordsPerSentence);
|
||||
}
|
||||
if (g_nbChars < g_maxChars) {
|
||||
g_ptr[g_nbChars++] = '\n';
|
||||
}
|
||||
if (g_nbChars < g_maxChars) {
|
||||
g_ptr[g_nbChars++] = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
/* It's "common" for lorem ipsum generators to start with the same first
|
||||
* pre-defined sentence */
|
||||
static void generateFirstSentence(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 18; i++) {
|
||||
const char* word = kWords[i];
|
||||
const char* separator = " ";
|
||||
if (i == 4)
|
||||
separator = ", ";
|
||||
if (i == 7)
|
||||
separator = ", ";
|
||||
generateWord(word, separator, i == 0);
|
||||
}
|
||||
generateWord(kWords[18], ". ", 0);
|
||||
}
|
||||
|
||||
size_t
|
||||
LOREM_genBlock(void* buffer, size_t size, unsigned seed, int first, int fill)
|
||||
{
|
||||
g_ptr = (char*)buffer;
|
||||
assert(size < INT_MAX);
|
||||
g_maxChars = size;
|
||||
g_nbChars = 0;
|
||||
g_randRoot = seed;
|
||||
if (g_distribCount == 0) {
|
||||
init_word_distrib(kWords, kNbWords, kWeights, kNbWeights);
|
||||
}
|
||||
|
||||
if (first) {
|
||||
generateFirstSentence();
|
||||
}
|
||||
while (g_nbChars < g_maxChars) {
|
||||
int sentencePerParagraph = about(7);
|
||||
generateParagraph(sentencePerParagraph);
|
||||
if (!fill)
|
||||
break; /* only generate one paragraph in not-fill mode */
|
||||
}
|
||||
g_ptr = NULL;
|
||||
return g_nbChars;
|
||||
}
|
||||
|
||||
void LOREM_genBuffer(void* buffer, size_t size, unsigned seed)
|
||||
{
|
||||
LOREM_genBlock(buffer, size, seed, 1, 1);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* lorem ipsum generator */
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
/*
|
||||
* LOREM_genBuffer():
|
||||
* Generate @size bytes of compressible data using lorem ipsum generator
|
||||
* into provided @buffer.
|
||||
*/
|
||||
void LOREM_genBuffer(void* buffer, size_t size, unsigned seed);
|
||||
|
||||
/*
|
||||
* LOREM_genBlock():
|
||||
* Similar to LOREM_genBuffer, with additional controls :
|
||||
* - @first : generate the first sentence
|
||||
* - @fill : fill the entire @buffer,
|
||||
* if ==0: generate one paragraph at most.
|
||||
* @return : nb of bytes generated into @buffer.
|
||||
*/
|
||||
size_t LOREM_genBlock(void* buffer, size_t size,
|
||||
unsigned seed,
|
||||
int first, int fill);
|
||||
+3
-4
@@ -74,8 +74,7 @@ extern "C" {
|
||||
***************************************************************/
|
||||
#ifndef PLATFORM_POSIX_VERSION
|
||||
|
||||
# if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1-2001 (SUSv3) conformant */ \
|
||||
|| defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) /* BSD distros */
|
||||
# if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1-2001 (SUSv3) conformant */
|
||||
/* exception rule : force posix version to 200112L,
|
||||
* note: it's better to use unistd.h's _POSIX_VERSION whenever possible */
|
||||
# define PLATFORM_POSIX_VERSION 200112L
|
||||
@@ -141,7 +140,7 @@ extern "C" {
|
||||
#elif defined(MSDOS) || defined(OS2)
|
||||
# include <io.h> /* _isatty */
|
||||
# define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
|
||||
#elif defined(WIN32) || defined(_WIN32)
|
||||
#elif defined(_WIN32)
|
||||
# include <io.h> /* _isatty */
|
||||
# include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
|
||||
# include <stdio.h> /* FILE */
|
||||
@@ -157,7 +156,7 @@ static __inline int IS_CONSOLE(FILE* stdStream) {
|
||||
/******************************
|
||||
* OS-specific IO behaviors
|
||||
******************************/
|
||||
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32)
|
||||
#if defined(MSDOS) || defined(OS2) || defined(_WIN32)
|
||||
# include <fcntl.h> /* _O_BINARY */
|
||||
# include <io.h> /* _setmode, _fileno, _get_osfhandle */
|
||||
# if !defined(__DJGPP__)
|
||||
|
||||
+25
-13
@@ -23,16 +23,27 @@ extern "C" {
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/param.h> /* __FreeBSD_version */
|
||||
#endif /* #ifdef __FreeBSD__ */
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <sys/utime.h> /* utime */
|
||||
# include <io.h> /* _chmod */
|
||||
# define ZSTD_USE_UTIMENSAT 0
|
||||
#else
|
||||
# include <unistd.h> /* chown, stat */
|
||||
# if PLATFORM_POSIX_VERSION < 200809L || !defined(st_mtime)
|
||||
# include <utime.h> /* utime */
|
||||
# include <sys/stat.h> /* utimensat, st_mtime */
|
||||
# if (PLATFORM_POSIX_VERSION >= 200809L && defined(st_mtime)) \
|
||||
|| (defined(__FreeBSD__) && __FreeBSD_version >= 1100056)
|
||||
# define ZSTD_USE_UTIMENSAT 1
|
||||
# else
|
||||
# define ZSTD_USE_UTIMENSAT 0
|
||||
# endif
|
||||
# if ZSTD_USE_UTIMENSAT
|
||||
# include <fcntl.h> /* AT_FDCWD */
|
||||
# include <sys/stat.h> /* utimensat */
|
||||
# else
|
||||
# include <utime.h> /* utime */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -259,7 +270,12 @@ int UTIL_utime(const char* filename, const stat_t *statbuf)
|
||||
* that struct stat has a struct timespec st_mtim member. We need this
|
||||
* check because there are some platforms that claim to be POSIX 2008
|
||||
* compliant but which do not have st_mtim... */
|
||||
#if (PLATFORM_POSIX_VERSION >= 200809L) && defined(st_mtime)
|
||||
/* FreeBSD has implemented POSIX 2008 for a long time but still only
|
||||
* advertises support for POSIX 2001. They have a version macro that
|
||||
* lets us safely gate them in.
|
||||
* See https://docs.freebsd.org/en/books/porters-handbook/versions/.
|
||||
*/
|
||||
#if ZSTD_USE_UTIMENSAT
|
||||
{
|
||||
/* (atime, mtime) */
|
||||
struct timespec timebuf[2] = { {0, UTIME_NOW} };
|
||||
@@ -660,7 +676,6 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName)
|
||||
size_t nbFiles = 0;
|
||||
char* buf;
|
||||
size_t bufSize;
|
||||
size_t pos = 0;
|
||||
stat_t statbuf;
|
||||
|
||||
if (!UTIL_stat(inputFileName, &statbuf) || !UTIL_isRegularFileStat(&statbuf))
|
||||
@@ -687,12 +702,13 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName)
|
||||
{ const char** filenamesTable = (const char**) malloc(nbFiles * sizeof(*filenamesTable));
|
||||
CONTROL(filenamesTable != NULL);
|
||||
|
||||
{ size_t fnb;
|
||||
for (fnb = 0, pos = 0; fnb < nbFiles; fnb++) {
|
||||
{ size_t fnb, pos = 0;
|
||||
for (fnb = 0; fnb < nbFiles; fnb++) {
|
||||
filenamesTable[fnb] = buf+pos;
|
||||
pos += strlen(buf+pos)+1; /* +1 for the finishing `\0` */
|
||||
} }
|
||||
}
|
||||
assert(pos <= bufSize);
|
||||
}
|
||||
|
||||
return UTIL_assembleFileNamesTable(filenamesTable, nbFiles, buf);
|
||||
}
|
||||
@@ -753,7 +769,7 @@ void UTIL_refFilename(FileNamesTable* fnt, const char* filename)
|
||||
|
||||
static size_t getTotalTableSize(FileNamesTable* table)
|
||||
{
|
||||
size_t fnb = 0, totalSize = 0;
|
||||
size_t fnb, totalSize = 0;
|
||||
for(fnb = 0 ; fnb < table->tableSize && table->fileNames[fnb] ; ++fnb) {
|
||||
totalSize += strlen(table->fileNames[fnb]) + 1; /* +1 to add '\0' at the end of each fileName */
|
||||
}
|
||||
@@ -1119,9 +1135,6 @@ static char* mallocAndJoin2Dir(const char *dir1, const char *dir2)
|
||||
memcpy(outDirBuffer, dir1, dir1Size);
|
||||
outDirBuffer[dir1Size] = '\0';
|
||||
|
||||
if (dir2[0] == '.')
|
||||
return outDirBuffer;
|
||||
|
||||
buffer = outDirBuffer + dir1Size;
|
||||
if (dir1Size > 0 && *(buffer - 1) != PATH_SEP) {
|
||||
*buffer = PATH_SEP;
|
||||
@@ -1546,7 +1559,6 @@ failed:
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
/* Use physical core sysctl when available
|
||||
|
||||
+1
-1
@@ -338,7 +338,7 @@ void UTIL_refFilename(FileNamesTable* fnt, const char* filename);
|
||||
FileNamesTable*
|
||||
UTIL_createExpandedFNT(const char* const* filenames, size_t nbFilenames, int followLinks);
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
#if defined(_WIN32)
|
||||
DWORD CountSetBits(ULONG_PTR bitMask);
|
||||
#endif
|
||||
|
||||
|
||||
+337
-152
@@ -1,381 +1,566 @@
|
||||
.TH "ZSTD" "1" "March 2023" "zstd 1.5.5" "User Commands"
|
||||
.
|
||||
.TH "ZSTD" "1" "March 2024" "zstd 1.5.6" "User Commands"
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files
|
||||
.
|
||||
.SH "SYNOPSIS"
|
||||
.TS
|
||||
allbox;
|
||||
\fBzstd\fR [\fIOPTIONS\fR] [\- \fIINPUT\-FILE\fR] [\-o \fIOUTPUT\-FILE\fR]
|
||||
.TE
|
||||
\fBzstd\fR [\fIOPTIONS\fR] [\-|\fIINPUT\-FILE\fR] [\-o \fIOUTPUT\-FILE\fR]
|
||||
.
|
||||
.P
|
||||
\fBzstdmt\fR is equivalent to \fBzstd \-T0\fR
|
||||
.
|
||||
.P
|
||||
\fBunzstd\fR is equivalent to \fBzstd \-d\fR
|
||||
.
|
||||
.P
|
||||
\fBzstdcat\fR is equivalent to \fBzstd \-dcf\fR
|
||||
.
|
||||
.SH "DESCRIPTION"
|
||||
\fBzstd\fR is a fast lossless compression algorithm and data compression tool, with command line syntax similar to \fBgzip\fR(1) and \fBxz\fR(1)\. It is based on the \fBLZ77\fR family, with further FSE & huff0 entropy stages\. \fBzstd\fR offers highly configurable compression speed, from fast modes at > 200 MB/s per core, to strong modes with excellent compression ratios\. It also features a very fast decoder, with speeds > 500 MB/s per core\.
|
||||
\fBzstd\fR is a fast lossless compression algorithm and data compression tool, with command line syntax similar to \fBgzip\fR(1) and \fBxz\fR(1)\. It is based on the \fBLZ77\fR family, with further FSE & huff0 entropy stages\. \fBzstd\fR offers highly configurable compression speed, from fast modes at > 200 MB/s per core, to strong modes with excellent compression ratios\. It also features a very fast decoder, with speeds > 500 MB/s per core, which remains roughly stable at all compression settings\.
|
||||
.
|
||||
.P
|
||||
\fBzstd\fR command line syntax is generally similar to gzip, but features the following differences:
|
||||
.IP "\[ci]" 4
|
||||
\fBzstd\fR command line syntax is generally similar to gzip, but features the following few differences:
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Source files are preserved by default\. It\'s possible to remove them automatically by using the \fB\-\-rm\fR command\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
When compressing a single file, \fBzstd\fR displays progress notifications and result summary by default\. Use \fB\-q\fR to turn them off\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fBzstd\fR displays a short help page when command line is an error\. Use \fB\-q\fR to turn it off\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fBzstd\fR does not accept input from console, though it does accept \fBstdin\fR when it\'s not the console\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fBzstd\fR does not store the input\'s filename or attributes, only its contents\.
|
||||
.
|
||||
.IP "" 0
|
||||
.
|
||||
.P
|
||||
\fBzstd\fR processes each \fIfile\fR according to the selected operation mode\. If no \fIfiles\fR are given or \fIfile\fR is \fB\-\fR, \fBzstd\fR reads from standard input and writes the processed data to standard output\. \fBzstd\fR will refuse to write compressed data to standard output if it is a terminal: it will display an error message and skip the file\. Similarly, \fBzstd\fR will refuse to read compressed data from standard input if it is a terminal\.
|
||||
.
|
||||
.P
|
||||
Unless \fB\-\-stdout\fR or \fB\-o\fR is specified, \fIfiles\fR are written to a new file whose name is derived from the source \fIfile\fR name:
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
When compressing, the suffix \fB\.zst\fR is appended to the source filename to get the target filename\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
When decompressing, the \fB\.zst\fR suffix is removed from the source filename to get the target filename
|
||||
.
|
||||
.IP "" 0
|
||||
.
|
||||
.SS "Concatenation with \.zst Files"
|
||||
It is possible to concatenate multiple \fB\.zst\fR files\. \fBzstd\fR will decompress such agglomerated file as if it was a single \fB\.zst\fR file\.
|
||||
.
|
||||
.SH "OPTIONS"
|
||||
.
|
||||
.SS "Integer Suffixes and Special Values"
|
||||
In most places where an integer argument is expected, an optional suffix is supported to easily indicate large integers\. There must be no space between the integer and the suffix\.
|
||||
.
|
||||
.TP
|
||||
\fBKiB\fR
|
||||
Multiply the integer by 1,024 (2\e^10)\. \fBKi\fR, \fBK\fR, and \fBKB\fR are accepted as synonyms for \fBKiB\fR\.
|
||||
Multiply the integer by 1,024 (2^10)\. \fBKi\fR, \fBK\fR, and \fBKB\fR are accepted as synonyms for \fBKiB\fR\.
|
||||
.
|
||||
.TP
|
||||
\fBMiB\fR
|
||||
Multiply the integer by 1,048,576 (2\e^20)\. \fBMi\fR, \fBM\fR, and \fBMB\fR are accepted as synonyms for \fBMiB\fR\.
|
||||
Multiply the integer by 1,048,576 (2^20)\. \fBMi\fR, \fBM\fR, and \fBMB\fR are accepted as synonyms for \fBMiB\fR\.
|
||||
.
|
||||
.SS "Operation Mode"
|
||||
If multiple operation mode options are given, the last one takes effect\.
|
||||
.
|
||||
.TP
|
||||
\fB\-z\fR, \fB\-\-compress\fR
|
||||
Compress\. This is the default operation mode when no operation mode option is specified and no other operation mode is implied from the command name (for example, \fBunzstd\fR implies \fB\-\-decompress\fR)\.
|
||||
.
|
||||
.TP
|
||||
\fB\-d\fR, \fB\-\-decompress\fR, \fB\-\-uncompress\fR
|
||||
Decompress\.
|
||||
.
|
||||
.TP
|
||||
\fB\-t\fR, \fB\-\-test\fR
|
||||
Test the integrity of compressed \fIfiles\fR\. This option is equivalent to \fB\-\-decompress \-\-stdout > /dev/null\fR, decompressed data is discarded and checksummed for errors\. No files are created or removed\.
|
||||
.
|
||||
.TP
|
||||
\fB\-b#\fR
|
||||
Benchmark file(s) using compression level \fI#\fR\. See \fIBENCHMARK\fR below for a description of this operation\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-train FILES\fR
|
||||
Use \fIFILES\fR as a training set to create a dictionary\. The training set should contain a lot of small files (> 100)\. See \fIDICTIONARY BUILDER\fR below for a description of this operation\.
|
||||
.
|
||||
.TP
|
||||
\fB\-l\fR, \fB\-\-list\fR
|
||||
Display information related to a zstd compressed file, such as size, ratio, and checksum\. Some of these fields may not be available\. This command\'s output can be augmented with the \fB\-v\fR modifier\.
|
||||
.
|
||||
.SS "Operation Modifiers"
|
||||
.IP "\[ci]" 4
|
||||
\fB\-#\fR: selects \fB#\fR compression level [1\-19] (default: 3)
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-#\fR: selects \fB#\fR compression level [1\-19] (default: 3)\. Higher compression levels \fIgenerally\fR produce higher compression ratio at the expense of speed and memory\. A rough rule of thumb is that compression speed is expected to be divided by 2 every 2 levels\. Technically, each level is mapped to a set of advanced parameters (that can also be modified individually, see below)\. Because the compressor\'s behavior highly depends on the content to compress, there\'s no guarantee of a smooth progression from one level to another\.
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-ultra\fR: unlocks high compression levels 20+ (maximum 22), using a lot more memory\. Note that decompression will also require more memory when using these levels\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-fast[=#]\fR: switch to ultra\-fast compression levels\. If \fB=#\fR is not present, it defaults to \fB1\fR\. The higher the value, the faster the compression speed, at the cost of some compression ratio\. This setting overwrites compression level if one was set previously\. Similarly, if a compression level is set after \fB\-\-fast\fR, it overrides it\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-T#\fR, \fB\-\-threads=#\fR: Compress using \fB#\fR working threads (default: 1)\. If \fB#\fR is 0, attempt to detect and use the number of physical CPU cores\. In all cases, the nb of threads is capped to \fBZSTDMT_NBWORKERS_MAX\fR, which is either 64 in 32\-bit mode, or 256 for 64\-bit environments\. This modifier does nothing if \fBzstd\fR is compiled without multithread support\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-single\-thread\fR: Use a single thread for both I/O and compression\. As compression is serialized with I/O, this can be slightly slower\. Single\-thread mode features significantly lower memory usage, which can be useful for systems with limited amount of memory, such as 32\-bit systems\.
|
||||
.
|
||||
.IP
|
||||
Note 1: this mode is the only available one when multithread support is disabled\.
|
||||
.
|
||||
.IP
|
||||
Note 2: this mode is different from \fB\-T1\fR, which spawns 1 compression thread in parallel with I/O\. Final compressed result is also slightly different from \fB\-T1\fR\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-auto\-threads={physical,logical} (default: physical)\fR: When using a default amount of threads via \fB\-T0\fR, choose the default based on the number of detected physical or logical cores\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-adapt[=min=#,max=#]\fR: \fBzstd\fR will dynamically adapt compression level to perceived I/O conditions\. Compression level adaptation can be observed live by using command \fB\-v\fR\. Adaptation can be constrained between supplied \fBmin\fR and \fBmax\fR levels\. The feature works when combined with multi\-threading and \fB\-\-long\fR mode\. It does not work with \fB\-\-single\-thread\fR\. It sets window size to 8 MiB by default (can be changed manually, see \fBwlog\fR)\. Due to the chaotic nature of dynamic adaptation, compressed result is not reproducible\.
|
||||
.
|
||||
.IP
|
||||
\fINote\fR: at the time of this writing, \fB\-\-adapt\fR can remain stuck at low speed when combined with multiple worker threads (>=2)\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-long[=#]\fR: enables long distance matching with \fB#\fR \fBwindowLog\fR, if \fB#\fR is not present it defaults to \fB27\fR\. This increases the window size (\fBwindowLog\fR) and memory usage for both the compressor and decompressor\. This setting is designed to improve the compression ratio for files with long matches at a large distance\.
|
||||
.
|
||||
.IP
|
||||
Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \fB\-\-memory=windowSize\fR needs to be passed to the decompressor\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-D DICT\fR: use \fBDICT\fR as Dictionary to compress or decompress FILE(s)
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-patch\-from FILE\fR: Specify the file to be used as a reference point for zstd\'s diff engine\. This is effectively dictionary compression with some convenient parameter selection, namely that \fIwindowSize\fR > \fIsrcSize\fR\.
|
||||
.
|
||||
.IP
|
||||
Note: cannot use both this and \fB\-D\fR together\.
|
||||
.
|
||||
.IP
|
||||
Note: \fB\-\-long\fR mode will be automatically activated if \fIchainLog\fR < \fIfileLog\fR (\fIfileLog\fR being the \fIwindowLog\fR required to cover the whole file)\. You can also manually force it\.
|
||||
.
|
||||
.IP
|
||||
Note: for all levels, you can use \fB\-\-patch\-from\fR in \fB\-\-single\-thread\fR mode to improve compression ratio at the cost of speed\.
|
||||
.
|
||||
.IP
|
||||
Note: for level 19, you can get increased compression ratio at the cost of speed by specifying \fB\-\-zstd=targetLength=\fR to be something large (i\.e\. 4096), and by setting a large \fB\-\-zstd=chainLog=\fR\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-rsyncable\fR: \fBzstd\fR will periodically synchronize the compression state to make the compressed file more rsync\-friendly\. There is a negligible impact to compression ratio, and a potential impact to compression speed, perceptible at higher speeds, for example when combining \fB\-\-rsyncable\fR with many parallel worker threads\. This feature does not work with \fB\-\-single\-thread\fR\. You probably don\'t want to use it with long range mode, since it will decrease the effectiveness of the synchronization points, but your mileage may vary\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-C\fR, \fB\-\-[no\-]check\fR: add integrity check computed from uncompressed data (default: enabled)
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-[no\-]content\-size\fR: enable / disable whether or not the original size of the file is placed in the header of the compressed file\. The default option is \fB\-\-content\-size\fR (meaning that the original size will be placed in the header)\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-no\-dictID\fR: do not store dictionary ID within frame header (dictionary compression)\. The decoder will have to rely on implicit knowledge about which dictionary to use, it won\'t be able to check if it\'s correct\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-M#\fR, \fB\-\-memory=#\fR: Set a memory usage limit\. By default, \fBzstd\fR uses 128 MiB for decompression as the maximum amount of memory the decompressor is allowed to use, but you can override this manually if need be in either direction (i\.e\. you can increase or decrease it)\.
|
||||
.
|
||||
.IP
|
||||
This is also used during compression when using with \fB\-\-patch\-from=\fR\. In this case, this parameter overrides that maximum size allowed for a dictionary\. (128 MiB)\.
|
||||
.
|
||||
.IP
|
||||
Additionally, this can be used to limit memory for dictionary training\. This parameter overrides the default limit of 2 GiB\. zstd will load training samples up to the memory limit and ignore the rest\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-stream\-size=#\fR: Sets the pledged source size of input coming from a stream\. This value must be exact, as it will be included in the produced frame header\. Incorrect stream sizes will cause an error\. This information will be used to better optimize compression parameters, resulting in better and potentially faster compression, especially for smaller source sizes\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-size\-hint=#\fR: When handling input from a stream, \fBzstd\fR must guess how large the source size will be when optimizing compression parameters\. If the stream size is relatively small, this guess may be a poor one, resulting in a higher compression ratio than expected\. This feature allows for controlling the guess when needed\. Exact guesses result in better compression ratios\. Overestimates result in slightly degraded compression ratios, while underestimates may result in significant degradation\.
|
||||
.IP "\[ci]" 4
|
||||
\fB\-o FILE\fR: save result into \fBFILE\fR\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-target\-compressed\-block\-size=#\fR: Attempt to produce compressed blocks of approximately this size\. This will split larger blocks in order to approach this target\. This feature is notably useful for improved latency, when the receiver can leverage receiving early incomplete data\. This parameter defines a loose target: compressed blocks will target this size "on average", but individual blocks can still be larger or smaller\. Enabling this feature can decrease compression speed by up to ~10% at level 1\. Higher levels will see smaller relative speed regression, becoming invisible at higher settings\.
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-f\fR, \fB\-\-force\fR: disable input and output checks\. Allows overwriting existing files, input from console, output to stdout, operating on links, block devices, etc\. During decompression and when the output destination is stdout, pass\-through unrecognized formats as\-is\.
|
||||
.IP "\[ci]" 4
|
||||
\fB\-c\fR, \fB\-\-stdout\fR: write to standard output (even if it is the console); keep original files unchanged\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-c\fR, \fB\-\-stdout\fR: write to standard output (even if it is the console); keep original files (disable \fB\-\-rm\fR)\.
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-o FILE\fR: save result into \fBFILE\fR\. Note that this operation is in conflict with \fB\-c\fR\. If both operations are present on the command line, the last expressed one wins\.
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-[no\-]sparse\fR: enable / disable sparse FS support, to make files with many zeroes smaller on disk\. Creating sparse files may save disk space and speed up decompression by reducing the amount of disk I/O\. default: enabled when output is into a file, and disabled when output is stdout\. This setting overrides default and can force sparse mode over stdout\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-[no\-]pass\-through\fR enable / disable passing through uncompressed files as\-is\. During decompression when pass\-through is enabled, unrecognized formats will be copied as\-is from the input to the output\. By default, pass\-through will occur when the output destination is stdout and the force (\fB\-f\fR) option is set\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-rm\fR: remove source file(s) after successful compression or decompression\. This command is silently ignored if output is \fBstdout\fR\. If used in combination with \fB\-o\fR, triggers a confirmation prompt (which can be silenced with \fB\-f\fR), as this is a destructive operation\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-k\fR, \fB\-\-keep\fR: keep source file(s) after successful compression or decompression\. This is the default behavior\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-r\fR: operate recursively on directories\. It selects all files in the named directory and all its subdirectories\. This can be useful both to reduce command line typing, and to circumvent shell expansion limitations, when there are a lot of files and naming breaks the maximum size of a command line\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-filelist FILE\fR read a list of files to process as content from \fBFILE\fR\. Format is compatible with \fBls\fR output, with one file per line\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-output\-dir\-flat DIR\fR: resulting files are stored into target \fBDIR\fR directory, instead of same directory as origin file\. Be aware that this command can introduce name collision issues, if multiple files, from different directories, end up having the same name\. Collision resolution ensures first file with a given name will be present in \fBDIR\fR, while in combination with \fB\-f\fR, the last file will be present instead\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-output\-dir\-mirror DIR\fR: similar to \fB\-\-output\-dir\-flat\fR, the output files are stored underneath target \fBDIR\fR directory, but this option will replicate input directory hierarchy into output \fBDIR\fR\.
|
||||
.
|
||||
.IP
|
||||
If input directory contains "\.\.", the files in this directory will be ignored\. If input directory is an absolute directory (i\.e\. "/var/tmp/abc"), it will be stored into the "output\-dir/var/tmp/abc"\. If there are multiple input files or directories, name collision resolution will follow the same rules as \fB\-\-output\-dir\-flat\fR\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-format=FORMAT\fR: compress and decompress in other formats\. If compiled with support, zstd can compress to or decompress from other compression algorithm formats\. Possibly available options are \fBzstd\fR, \fBgzip\fR, \fBxz\fR, \fBlzma\fR, and \fBlz4\fR\. If no such format is provided, \fBzstd\fR is the default\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-h\fR/\fB\-H\fR, \fB\-\-help\fR: display help/long help and exit
|
||||
.IP "\[ci]" 4
|
||||
\fB\-V\fR, \fB\-\-version\fR: display version number and exit\. Advanced: \fB\-vV\fR also displays supported formats\. \fB\-vvV\fR also displays POSIX support\. \fB\-q\fR will only display the version number, suitable for machine reading\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-V\fR, \fB\-\-version\fR: display version number and immediately exit\. note that, since it exits, flags specified after \fB\-V\fR are effectively ignored\. Advanced: \fB\-vV\fR also displays supported formats\. \fB\-vvV\fR also displays POSIX support\. \fB\-qV\fR will only display the version number, suitable for machine reading\.
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-v\fR, \fB\-\-verbose\fR: verbose mode, display more information
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-q\fR, \fB\-\-quiet\fR: suppress warnings, interactivity, and notifications\. specify twice to suppress errors too\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-no\-progress\fR: do not display the progress bar, but keep all other messages\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-show\-default\-cparams\fR: shows the default compression parameters that will be used for a particular input file, based on the provided compression level and the input size\. If the provided file is not a regular file (e\.g\. a pipe), this flag will output the parameters used for inputs of unknown size\.
|
||||
.IP "\[ci]" 4
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-exclude\-compressed\fR: only compress files that are not already compressed\.
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
\fB\-\-\fR: All arguments after \fB\-\-\fR are treated as files
|
||||
.
|
||||
.IP "" 0
|
||||
.
|
||||
.SS "gzip Operation Modifiers"
|
||||
When invoked via a \fBgzip\fR symlink, \fBzstd\fR will support further options that intend to mimic the \fBgzip\fR behavior:
|
||||
.
|
||||
.TP
|
||||
\fB\-n\fR, \fB\-\-no\-name\fR
|
||||
do not store the original filename and timestamps when compressing a file\. This is the default behavior and hence a no\-op\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-best\fR
|
||||
alias to the option \fB\-9\fR\.
|
||||
.
|
||||
.SS "Environment Variables"
|
||||
Employing environment variables to set parameters has security implications\. Therefore, this avenue is intentionally limited\. Only \fBZSTD_CLEVEL\fR and \fBZSTD_NBTHREADS\fR are currently supported\. They set the compression level and number of threads to use during compression, respectively\.
|
||||
Employing environment variables to set parameters has security implications\. Therefore, this avenue is intentionally limited\. Only \fBZSTD_CLEVEL\fR and \fBZSTD_NBTHREADS\fR are currently supported\. They set the default compression level and number of threads to use during compression, respectively\.
|
||||
.
|
||||
.P
|
||||
\fBZSTD_CLEVEL\fR can be used to set the level between 1 and 19 (the "normal" range)\. If the value of \fBZSTD_CLEVEL\fR is not a valid integer, it will be ignored with a warning message\. \fBZSTD_CLEVEL\fR just replaces the default compression level (\fB3\fR)\.
|
||||
.
|
||||
.P
|
||||
\fBZSTD_NBTHREADS\fR can be used to set the number of threads \fBzstd\fR will attempt to use during compression\. If the value of \fBZSTD_NBTHREADS\fR is not a valid unsigned integer, it will be ignored with a warning message\. \fBZSTD_NBTHREADS\fR has a default value of (\fB1\fR), and is capped at ZSTDMT_NBWORKERS_MAX==200\. \fBzstd\fR must be compiled with multithread support for this to have any effect\.
|
||||
\fBZSTD_NBTHREADS\fR can be used to set the number of threads \fBzstd\fR will attempt to use during compression\. If the value of \fBZSTD_NBTHREADS\fR is not a valid unsigned integer, it will be ignored with a warning message\. \fBZSTD_NBTHREADS\fR has a default value of (\fB1\fR), and is capped at ZSTDMT_NBWORKERS_MAX==200\. \fBzstd\fR must be compiled with multithread support for this variable to have any effect\.
|
||||
.
|
||||
.P
|
||||
They can both be overridden by corresponding command line arguments: \fB\-#\fR for compression level and \fB\-T#\fR for number of compression threads\.
|
||||
.SH "DICTIONARY BUILDER"
|
||||
\fBzstd\fR offers \fIdictionary\fR compression, which greatly improves efficiency on small files and messages\. It\'s possible to train \fBzstd\fR with a set of samples, the result of which is saved into a file called a \fBdictionary\fR\. Then, during compression and decompression, reference the same dictionary, using command \fB\-D dictionaryFileName\fR\. Compression of small files similar to the sample set will be greatly improved\.
|
||||
.TP
|
||||
\fB\-\-train FILEs\fR
|
||||
Use FILEs as training set to create a dictionary\. The training set should ideally contain a lot of samples (> 100), and weight typically 100x the target dictionary size (for example, ~10 MB for a 100 KB dictionary)\. \fB\-\-train\fR can be combined with \fB\-r\fR to indicate a directory rather than listing all the files, which can be useful to circumvent shell expansion limits\.
|
||||
.IP
|
||||
Since dictionary compression is mostly effective for small files, the expectation is that the training set will only contain small files\. In the case where some samples happen to be large, only the first 128 KiB of these samples will be used for training\.
|
||||
.IP
|
||||
\fB\-\-train\fR supports multithreading if \fBzstd\fR is compiled with threading support (default)\. Additional advanced parameters can be specified with \fB\-\-train\-fastcover\fR\. The legacy dictionary builder can be accessed with \fB\-\-train\-legacy\fR\. The slower cover dictionary builder can be accessed with \fB\-\-train\-cover\fR\. Default \fB\-\-train\fR is equivalent to \fB\-\-train\-fastcover=d=8,steps=4\fR\.
|
||||
.TP
|
||||
\fB\-o FILE\fR
|
||||
Dictionary saved into \fBFILE\fR (default name: dictionary)\.
|
||||
.TP
|
||||
\fB\-\-maxdict=#\fR
|
||||
Limit dictionary to specified size (default: 112640 bytes)\. As usual, quantities are expressed in bytes by default, and it\'s possible to employ suffixes (like \fBKB\fR or \fBMB\fR) to specify larger values\.
|
||||
.TP
|
||||
\fB\-#\fR
|
||||
Use \fB#\fR compression level during training (optional)\. Will generate statistics more tuned for selected compression level, resulting in a \fIsmall\fR compression ratio improvement for this level\.
|
||||
.TP
|
||||
\fB\-B#\fR
|
||||
Split input files into blocks of size # (default: no split)
|
||||
.TP
|
||||
\fB\-M#\fR, \fB\-\-memory=#\fR
|
||||
Limit the amount of sample data loaded for training (default: 2 GB)\. Note that the default (2 GB) is also the maximum\. This parameter can be useful in situations where the training set size is not well controlled and could be potentially very large\. Since speed of the training process is directly correlated to the size of the training sample set, a smaller sample set leads to faster training\.
|
||||
.IP
|
||||
In situations where the training set is larger than maximum memory, the CLI will randomly select samples among the available ones, up to the maximum allowed memory budget\. This is meant to improve dictionary relevance by mitigating the potential impact of clustering, such as selecting only files from the beginning of a list sorted by modification date, or sorted by alphabetical order\. The randomization process is deterministic, so training of the same list of files with the same parameters will lead to the creation of the same dictionary\.
|
||||
.TP
|
||||
\fB\-\-dictID=#\fR
|
||||
A dictionary ID is a locally unique ID\. The decoder will use this value to verify it is using the right dictionary\. By default, zstd will create a 4\-bytes random number ID\. It\'s possible to provide an explicit number ID instead\. It\'s up to the dictionary manager to not assign twice the same ID to 2 different dictionaries\. Note that short numbers have an advantage: an ID < 256 will only need 1 byte in the compressed frame header, and an ID < 65536 will only need 2 bytes\. This compares favorably to 4 bytes default\.
|
||||
.IP
|
||||
Note that RFC8878 reserves IDs less than 32768 and greater than or equal to 2\e^31, so they should not be used in public\.
|
||||
.TP
|
||||
\fB\-\-train\-cover[=k#,d=#,steps=#,split=#,shrink[=#]]\fR
|
||||
Select parameters for the default dictionary builder algorithm named cover\. If \fId\fR is not specified, then it tries \fId\fR = 6 and \fId\fR = 8\. If \fIk\fR is not specified, then it tries \fIsteps\fR values in the range [50, 2000]\. If \fIsteps\fR is not specified, then the default value of 40 is used\. If \fIsplit\fR is not specified or split <= 0, then the default value of 100 is used\. Requires that \fId\fR <= \fIk\fR\. If \fIshrink\fR flag is not used, then the default value for \fIshrinkDict\fR of 0 is used\. If \fIshrink\fR is not specified, then the default value for \fIshrinkDictMaxRegression\fR of 1 is used\.
|
||||
.IP
|
||||
Selects segments of size \fIk\fR with highest score to put in the dictionary\. The score of a segment is computed by the sum of the frequencies of all the subsegments of size \fId\fR\. Generally \fId\fR should be in the range [6, 8], occasionally up to 16, but the algorithm will run faster with d <= \fI8\fR\. Good values for \fIk\fR vary widely based on the input data, but a safe range is [2 * \fId\fR, 2000]\. If \fIsplit\fR is 100, all input samples are used for both training and testing to find optimal \fId\fR and \fIk\fR to build dictionary\. Supports multithreading if \fBzstd\fR is compiled with threading support\. Having \fIshrink\fR enabled takes a truncated dictionary of minimum size and doubles in size until compression ratio of the truncated dictionary is at most \fIshrinkDictMaxRegression%\fR worse than the compression ratio of the largest dictionary\.
|
||||
.IP
|
||||
Examples:
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover FILEs\fR
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=k=50,d=8 FILEs\fR
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=d=8,steps=500 FILEs\fR
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=k=50 FILEs\fR
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=k=50,split=60 FILEs\fR
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=shrink FILEs\fR
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=shrink=2 FILEs\fR
|
||||
.TP
|
||||
\fB\-\-train\-fastcover[=k#,d=#,f=#,steps=#,split=#,accel=#]\fR
|
||||
Same as cover but with extra parameters \fIf\fR and \fIaccel\fR and different default value of split If \fIsplit\fR is not specified, then it tries \fIsplit\fR = 75\. If \fIf\fR is not specified, then it tries \fIf\fR = 20\. Requires that 0 < \fIf\fR < 32\. If \fIaccel\fR is not specified, then it tries \fIaccel\fR = 1\. Requires that 0 < \fIaccel\fR <= 10\. Requires that \fId\fR = 6 or \fId\fR = 8\.
|
||||
.IP
|
||||
\fIf\fR is log of size of array that keeps track of frequency of subsegments of size \fId\fR\. The subsegment is hashed to an index in the range [0,2^\fIf\fR \- 1]\. It is possible that 2 different subsegments are hashed to the same index, and they are considered as the same subsegment when computing frequency\. Using a higher \fIf\fR reduces collision but takes longer\.
|
||||
.IP
|
||||
Examples:
|
||||
.IP
|
||||
\fBzstd \-\-train\-fastcover FILEs\fR
|
||||
.IP
|
||||
\fBzstd \-\-train\-fastcover=d=8,f=15,accel=2 FILEs\fR
|
||||
.TP
|
||||
\fB\-\-train\-legacy[=selectivity=#]\fR
|
||||
Use legacy dictionary builder algorithm with the given dictionary \fIselectivity\fR (default: 9)\. The smaller the \fIselectivity\fR value, the denser the dictionary, improving its efficiency but reducing its achievable maximum size\. \fB\-\-train\-legacy=s=#\fR is also accepted\.
|
||||
.IP
|
||||
Examples:
|
||||
.IP
|
||||
\fBzstd \-\-train\-legacy FILEs\fR
|
||||
.IP
|
||||
\fBzstd \-\-train\-legacy=selectivity=8 FILEs\fR
|
||||
.SH "BENCHMARK"
|
||||
.TP
|
||||
\fB\-b#\fR
|
||||
benchmark file(s) using compression level #
|
||||
.TP
|
||||
\fB\-e#\fR
|
||||
benchmark file(s) using multiple compression levels, from \fB\-b#\fR to \fB\-e#\fR (inclusive)
|
||||
.TP
|
||||
\fB\-i#\fR
|
||||
minimum evaluation time, in seconds (default: 3s), benchmark mode only
|
||||
.TP
|
||||
\fB\-B#\fR, \fB\-\-block\-size=#\fR
|
||||
cut file(s) into independent chunks of size # (default: no chunking)
|
||||
.TP
|
||||
\fB\-\-priority=rt\fR
|
||||
set process priority to real\-time
|
||||
.P
|
||||
\fBOutput Format:\fR CompressionLevel#Filename: InputSize \-> OutputSize (CompressionRatio), CompressionSpeed, DecompressionSpeed
|
||||
.P
|
||||
\fBMethodology:\fR For both compression and decompression speed, the entire input is compressed/decompressed in\-memory to measure speed\. A run lasts at least 1 sec, so when files are small, they are compressed/decompressed several times per run, in order to improve measurement accuracy\.
|
||||
.
|
||||
.SH "ADVANCED COMPRESSION OPTIONS"
|
||||
### \-B#: Specify the size of each compression job\. This parameter is only available when multi\-threading is enabled\. Each compression job is run in parallel, so this value indirectly impacts the nb of active threads\. Default job size varies depending on compression level (generally \fB4 * windowSize\fR)\. \fB\-B#\fR makes it possible to manually select a custom size\. Note that job size must respect a minimum value which is enforced transparently\. This minimum is either 512 KB, or \fBoverlapSize\fR, whichever is largest\. Different job sizes will lead to non\-identical compressed frames\.
|
||||
\fBzstd\fR provides 22 predefined regular compression levels plus the fast levels\. A compression level is translated internally into multiple advanced parameters that control the behavior of the compressor (one can observe the result of this translation with \fB\-\-show\-default\-cparams\fR)\. These advanced parameters can be overridden using advanced compression options\.
|
||||
.
|
||||
.SS "\-\-zstd[=options]:"
|
||||
\fBzstd\fR provides 22 predefined regular compression levels plus the fast levels\. This compression level is translated internally into a number of specific parameters that actually control the behavior of the compressor\. (You can see the result of this translation with \fB\-\-show\-default\-cparams\fR\.) These specific parameters can be overridden with advanced compression options\. The \fIoptions\fR are provided as a comma\-separated list\. You may specify only the options you want to change and the rest will be taken from the selected or default compression level\. The list of available \fIoptions\fR:
|
||||
The \fIoptions\fR are provided as a comma\-separated list\. You may specify only the options you want to change and the rest will be taken from the selected or default compression level\. The list of available \fIoptions\fR:
|
||||
.
|
||||
.TP
|
||||
\fBstrategy\fR=\fIstrat\fR, \fBstrat\fR=\fIstrat\fR
|
||||
Specify a strategy used by a match finder\.
|
||||
.
|
||||
.IP
|
||||
There are 9 strategies numbered from 1 to 9, from fastest to strongest: 1=\fBZSTD_fast\fR, 2=\fBZSTD_dfast\fR, 3=\fBZSTD_greedy\fR, 4=\fBZSTD_lazy\fR, 5=\fBZSTD_lazy2\fR, 6=\fBZSTD_btlazy2\fR, 7=\fBZSTD_btopt\fR, 8=\fBZSTD_btultra\fR, 9=\fBZSTD_btultra2\fR\.
|
||||
.
|
||||
.TP
|
||||
\fBwindowLog\fR=\fIwlog\fR, \fBwlog\fR=\fIwlog\fR
|
||||
Specify the maximum number of bits for a match distance\.
|
||||
.
|
||||
.IP
|
||||
The higher number of increases the chance to find a match which usually improves compression ratio\. It also increases memory requirements for the compressor and decompressor\. The minimum \fIwlog\fR is 10 (1 KiB) and the maximum is 30 (1 GiB) on 32\-bit platforms and 31 (2 GiB) on 64\-bit platforms\.
|
||||
.
|
||||
.IP
|
||||
Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \fB\-\-memory=windowSize\fR needs to be passed to the decompressor\.
|
||||
.
|
||||
.TP
|
||||
\fBhashLog\fR=\fIhlog\fR, \fBhlog\fR=\fIhlog\fR
|
||||
Specify the maximum number of bits for a hash table\.
|
||||
.
|
||||
.IP
|
||||
Bigger hash tables cause fewer collisions which usually makes compression faster, but requires more memory during compression\.
|
||||
.
|
||||
.IP
|
||||
The minimum \fIhlog\fR is 6 (64 entries / 256 B) and the maximum is 30 (1B entries / 4 GiB)\.
|
||||
.
|
||||
.TP
|
||||
\fBchainLog\fR=\fIclog\fR, \fBclog\fR=\fIclog\fR
|
||||
Specify the maximum number of bits for the secondary search structure, whose form depends on the selected \fBstrategy\fR\.
|
||||
.
|
||||
.IP
|
||||
Higher numbers of bits increases the chance to find a match which usually improves compression ratio\. It also slows down compression speed and increases memory requirements for compression\. This option is ignored for the \fBZSTD_fast\fR \fBstrategy\fR, which only has the primary hash table\.
|
||||
.
|
||||
.IP
|
||||
The minimum \fIclog\fR is 6 (64 entries / 256 B) and the maximum is 29 (512M entries / 2 GiB) on 32\-bit platforms and 30 (1B entries / 4 GiB) on 64\-bit platforms\.
|
||||
.
|
||||
.TP
|
||||
\fBsearchLog\fR=\fIslog\fR, \fBslog\fR=\fIslog\fR
|
||||
Specify the maximum number of searches in a hash chain or a binary tree using logarithmic scale\.
|
||||
.
|
||||
.IP
|
||||
More searches increases the chance to find a match which usually increases compression ratio but decreases compression speed\.
|
||||
.
|
||||
.IP
|
||||
The minimum \fIslog\fR is 1 and the maximum is \'windowLog\' \- 1\.
|
||||
.
|
||||
.TP
|
||||
\fBminMatch\fR=\fImml\fR, \fBmml\fR=\fImml\fR
|
||||
Specify the minimum searched length of a match in a hash table\.
|
||||
.
|
||||
.IP
|
||||
Larger search lengths usually decrease compression ratio but improve decompression speed\.
|
||||
.
|
||||
.IP
|
||||
The minimum \fImml\fR is 3 and the maximum is 7\.
|
||||
.
|
||||
.TP
|
||||
\fBtargetLength\fR=\fItlen\fR, \fBtlen\fR=\fItlen\fR
|
||||
The impact of this field vary depending on selected strategy\.
|
||||
.
|
||||
.IP
|
||||
For \fBZSTD_btopt\fR, \fBZSTD_btultra\fR and \fBZSTD_btultra2\fR, it specifies the minimum match length that causes match finder to stop searching\. A larger \fBtargetLength\fR usually improves compression ratio but decreases compression speed\.
|
||||
.
|
||||
.IP
|
||||
For \fBZSTD_fast\fR, it triggers ultra\-fast mode when > 0\. The value represents the amount of data skipped between match sampling\. Impact is reversed: a larger \fBtargetLength\fR increases compression speed but decreases compression ratio\.
|
||||
.
|
||||
.IP
|
||||
For all other strategies, this field has no impact\.
|
||||
.
|
||||
.IP
|
||||
The minimum \fItlen\fR is 0 and the maximum is 128 KiB\.
|
||||
.
|
||||
.TP
|
||||
\fBoverlapLog\fR=\fIovlog\fR, \fBovlog\fR=\fIovlog\fR
|
||||
Determine \fBoverlapSize\fR, amount of data reloaded from previous job\. This parameter is only available when multithreading is enabled\. Reloading more data improves compression ratio, but decreases speed\.
|
||||
.
|
||||
.IP
|
||||
The minimum \fIovlog\fR is 0, and the maximum is 9\. 1 means "no overlap", hence completely independent jobs\. 9 means "full overlap", meaning up to \fBwindowSize\fR is reloaded from previous job\. Reducing \fIovlog\fR by 1 reduces the reloaded amount by a factor 2\. For example, 8 means "windowSize/2", and 6 means "windowSize/8"\. Value 0 is special and means "default": \fIovlog\fR is automatically determined by \fBzstd\fR\. In which case, \fIovlog\fR will range from 6 to 9, depending on selected \fIstrat\fR\.
|
||||
.
|
||||
.TP
|
||||
\fBldmHashLog\fR=\fIlhlog\fR, \fBlhlog\fR=\fIlhlog\fR
|
||||
Specify the maximum size for a hash table used for long distance matching\.
|
||||
.
|
||||
.IP
|
||||
This option is ignored unless long distance matching is enabled\.
|
||||
.
|
||||
.IP
|
||||
Bigger hash tables usually improve compression ratio at the expense of more memory during compression and a decrease in compression speed\.
|
||||
.
|
||||
.IP
|
||||
The minimum \fIlhlog\fR is 6 and the maximum is 30 (default: 20)\.
|
||||
.
|
||||
.TP
|
||||
\fBldmMinMatch\fR=\fIlmml\fR, \fBlmml\fR=\fIlmml\fR
|
||||
Specify the minimum searched length of a match for long distance matching\.
|
||||
.
|
||||
.IP
|
||||
This option is ignored unless long distance matching is enabled\.
|
||||
.
|
||||
.IP
|
||||
Larger/very small values usually decrease compression ratio\.
|
||||
.
|
||||
.IP
|
||||
The minimum \fIlmml\fR is 4 and the maximum is 4096 (default: 64)\.
|
||||
.
|
||||
.TP
|
||||
\fBldmBucketSizeLog\fR=\fIlblog\fR, \fBlblog\fR=\fIlblog\fR
|
||||
Specify the size of each bucket for the hash table used for long distance matching\.
|
||||
.
|
||||
.IP
|
||||
This option is ignored unless long distance matching is enabled\.
|
||||
.
|
||||
.IP
|
||||
Larger bucket sizes improve collision resolution but decrease compression speed\.
|
||||
.
|
||||
.IP
|
||||
The minimum \fIlblog\fR is 1 and the maximum is 8 (default: 3)\.
|
||||
.
|
||||
.TP
|
||||
\fBldmHashRateLog\fR=\fIlhrlog\fR, \fBlhrlog\fR=\fIlhrlog\fR
|
||||
Specify the frequency of inserting entries into the long distance matching hash table\.
|
||||
.
|
||||
.IP
|
||||
This option is ignored unless long distance matching is enabled\.
|
||||
.
|
||||
.IP
|
||||
Larger values will improve compression speed\. Deviating far from the default value will likely result in a decrease in compression ratio\.
|
||||
.
|
||||
.IP
|
||||
The default value is \fBwlog \- lhlog\fR\.
|
||||
.
|
||||
.SS "Example"
|
||||
The following parameters sets advanced compression options to something similar to predefined level 19 for files bigger than 256 KB:
|
||||
.
|
||||
.P
|
||||
\fB\-\-zstd\fR=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6
|
||||
.
|
||||
.SS "\-B#:"
|
||||
Specify the size of each compression job\. This parameter is only available when multi\-threading is enabled\. Each compression job is run in parallel, so this value indirectly impacts the nb of active threads\. Default job size varies depending on compression level (generally \fB4 * windowSize\fR)\. \fB\-B#\fR makes it possible to manually select a custom size\. Note that job size must respect a minimum value which is enforced transparently\. This minimum is either 512 KB, or \fBoverlapSize\fR, whichever is largest\. Different job sizes will lead to non\-identical compressed frames\.
|
||||
.
|
||||
.SH "DICTIONARY BUILDER"
|
||||
\fBzstd\fR offers \fIdictionary\fR compression, which greatly improves efficiency on small files and messages\. It\'s possible to train \fBzstd\fR with a set of samples, the result of which is saved into a file called a \fBdictionary\fR\. Then, during compression and decompression, reference the same dictionary, using command \fB\-D dictionaryFileName\fR\. Compression of small files similar to the sample set will be greatly improved\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-train FILEs\fR
|
||||
Use FILEs as training set to create a dictionary\. The training set should ideally contain a lot of samples (> 100), and weight typically 100x the target dictionary size (for example, ~10 MB for a 100 KB dictionary)\. \fB\-\-train\fR can be combined with \fB\-r\fR to indicate a directory rather than listing all the files, which can be useful to circumvent shell expansion limits\.
|
||||
.
|
||||
.IP
|
||||
Since dictionary compression is mostly effective for small files, the expectation is that the training set will only contain small files\. In the case where some samples happen to be large, only the first 128 KiB of these samples will be used for training\.
|
||||
.
|
||||
.IP
|
||||
\fB\-\-train\fR supports multithreading if \fBzstd\fR is compiled with threading support (default)\. Additional advanced parameters can be specified with \fB\-\-train\-fastcover\fR\. The legacy dictionary builder can be accessed with \fB\-\-train\-legacy\fR\. The slower cover dictionary builder can be accessed with \fB\-\-train\-cover\fR\. Default \fB\-\-train\fR is equivalent to \fB\-\-train\-fastcover=d=8,steps=4\fR\.
|
||||
.
|
||||
.TP
|
||||
\fB\-o FILE\fR
|
||||
Dictionary saved into \fBFILE\fR (default name: dictionary)\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-maxdict=#\fR
|
||||
Limit dictionary to specified size (default: 112640 bytes)\. As usual, quantities are expressed in bytes by default, and it\'s possible to employ suffixes (like \fBKB\fR or \fBMB\fR) to specify larger values\.
|
||||
.
|
||||
.TP
|
||||
\fB\-#\fR
|
||||
Use \fB#\fR compression level during training (optional)\. Will generate statistics more tuned for selected compression level, resulting in a \fIsmall\fR compression ratio improvement for this level\.
|
||||
.
|
||||
.TP
|
||||
\fB\-B#\fR
|
||||
Split input files into blocks of size # (default: no split)
|
||||
.
|
||||
.TP
|
||||
\fB\-M#\fR, \fB\-\-memory=#\fR
|
||||
Limit the amount of sample data loaded for training (default: 2 GB)\. Note that the default (2 GB) is also the maximum\. This parameter can be useful in situations where the training set size is not well controlled and could be potentially very large\. Since speed of the training process is directly correlated to the size of the training sample set, a smaller sample set leads to faster training\.
|
||||
.
|
||||
.IP
|
||||
In situations where the training set is larger than maximum memory, the CLI will randomly select samples among the available ones, up to the maximum allowed memory budget\. This is meant to improve dictionary relevance by mitigating the potential impact of clustering, such as selecting only files from the beginning of a list sorted by modification date, or sorted by alphabetical order\. The randomization process is deterministic, so training of the same list of files with the same parameters will lead to the creation of the same dictionary\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-dictID=#\fR
|
||||
A dictionary ID is a locally unique ID\. The decoder will use this value to verify it is using the right dictionary\. By default, zstd will create a 4\-bytes random number ID\. It\'s possible to provide an explicit number ID instead\. It\'s up to the dictionary manager to not assign twice the same ID to 2 different dictionaries\. Note that short numbers have an advantage: an ID < 256 will only need 1 byte in the compressed frame header, and an ID < 65536 will only need 2 bytes\. This compares favorably to 4 bytes default\.
|
||||
.
|
||||
.IP
|
||||
Note that RFC8878 reserves IDs less than 32768 and greater than or equal to 2^31, so they should not be used in public\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-train\-cover[=k#,d=#,steps=#,split=#,shrink[=#]]\fR
|
||||
Select parameters for the default dictionary builder algorithm named cover\. If \fId\fR is not specified, then it tries \fId\fR = 6 and \fId\fR = 8\. If \fIk\fR is not specified, then it tries \fIsteps\fR values in the range [50, 2000]\. If \fIsteps\fR is not specified, then the default value of 40 is used\. If \fIsplit\fR is not specified or split <= 0, then the default value of 100 is used\. Requires that \fId\fR <= \fIk\fR\. If \fIshrink\fR flag is not used, then the default value for \fIshrinkDict\fR of 0 is used\. If \fIshrink\fR is not specified, then the default value for \fIshrinkDictMaxRegression\fR of 1 is used\.
|
||||
.
|
||||
.IP
|
||||
Selects segments of size \fIk\fR with highest score to put in the dictionary\. The score of a segment is computed by the sum of the frequencies of all the subsegments of size \fId\fR\. Generally \fId\fR should be in the range [6, 8], occasionally up to 16, but the algorithm will run faster with d <= \fI8\fR\. Good values for \fIk\fR vary widely based on the input data, but a safe range is [2 * \fId\fR, 2000]\. If \fIsplit\fR is 100, all input samples are used for both training and testing to find optimal \fId\fR and \fIk\fR to build dictionary\. Supports multithreading if \fBzstd\fR is compiled with threading support\. Having \fIshrink\fR enabled takes a truncated dictionary of minimum size and doubles in size until compression ratio of the truncated dictionary is at most \fIshrinkDictMaxRegression%\fR worse than the compression ratio of the largest dictionary\.
|
||||
.
|
||||
.IP
|
||||
Examples:
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover FILEs\fR
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=k=50,d=8 FILEs\fR
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=d=8,steps=500 FILEs\fR
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=k=50 FILEs\fR
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=k=50,split=60 FILEs\fR
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=shrink FILEs\fR
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-cover=shrink=2 FILEs\fR
|
||||
.
|
||||
.TP
|
||||
\fB\-\-train\-fastcover[=k#,d=#,f=#,steps=#,split=#,accel=#]\fR
|
||||
Same as cover but with extra parameters \fIf\fR and \fIaccel\fR and different default value of split If \fIsplit\fR is not specified, then it tries \fIsplit\fR = 75\. If \fIf\fR is not specified, then it tries \fIf\fR = 20\. Requires that 0 < \fIf\fR < 32\. If \fIaccel\fR is not specified, then it tries \fIaccel\fR = 1\. Requires that 0 < \fIaccel\fR <= 10\. Requires that \fId\fR = 6 or \fId\fR = 8\.
|
||||
.
|
||||
.IP
|
||||
\fIf\fR is log of size of array that keeps track of frequency of subsegments of size \fId\fR\. The subsegment is hashed to an index in the range [0,2^\fIf\fR \- 1]\. It is possible that 2 different subsegments are hashed to the same index, and they are considered as the same subsegment when computing frequency\. Using a higher \fIf\fR reduces collision but takes longer\.
|
||||
.
|
||||
.IP
|
||||
Examples:
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-fastcover FILEs\fR
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-fastcover=d=8,f=15,accel=2 FILEs\fR
|
||||
.
|
||||
.TP
|
||||
\fB\-\-train\-legacy[=selectivity=#]\fR
|
||||
Use legacy dictionary builder algorithm with the given dictionary \fIselectivity\fR (default: 9)\. The smaller the \fIselectivity\fR value, the denser the dictionary, improving its efficiency but reducing its achievable maximum size\. \fB\-\-train\-legacy=s=#\fR is also accepted\.
|
||||
.
|
||||
.IP
|
||||
Examples:
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-legacy FILEs\fR
|
||||
.
|
||||
.IP
|
||||
\fBzstd \-\-train\-legacy=selectivity=8 FILEs\fR
|
||||
.
|
||||
.SH "BENCHMARK"
|
||||
The \fBzstd\fR CLI provides a benchmarking mode that can be used to easily find suitable compression parameters, or alternatively to benchmark a computer\'s performance\. Note that the results are highly dependent on the content being compressed\.
|
||||
.
|
||||
.TP
|
||||
\fB\-b#\fR
|
||||
benchmark file(s) using compression level #
|
||||
.
|
||||
.TP
|
||||
\fB\-e#\fR
|
||||
benchmark file(s) using multiple compression levels, from \fB\-b#\fR to \fB\-e#\fR (inclusive)
|
||||
.
|
||||
.TP
|
||||
\fB\-d\fR
|
||||
benchmark decompression speed only (requires providing an already zstd\-compressed content)
|
||||
.
|
||||
.TP
|
||||
\fB\-i#\fR
|
||||
minimum evaluation time, in seconds (default: 3s), benchmark mode only
|
||||
.
|
||||
.TP
|
||||
\fB\-B#\fR, \fB\-\-block\-size=#\fR
|
||||
cut file(s) into independent chunks of size # (default: no chunking)
|
||||
.
|
||||
.TP
|
||||
\fB\-\-priority=rt\fR
|
||||
set process priority to real\-time (Windows)
|
||||
.
|
||||
.P
|
||||
\fBOutput Format:\fR CompressionLevel#Filename: InputSize \-> OutputSize (CompressionRatio), CompressionSpeed, DecompressionSpeed
|
||||
.
|
||||
.P
|
||||
\fBMethodology:\fR For both compression and decompression speed, the entire input is compressed/decompressed in\-memory to measure speed\. A run lasts at least 1 sec, so when files are small, they are compressed/decompressed several times per run, in order to improve measurement accuracy\.
|
||||
.
|
||||
.SH "SEE ALSO"
|
||||
\fBzstdgrep\fR(1), \fBzstdless\fR(1), \fBgzip\fR(1), \fBxz\fR(1)
|
||||
.
|
||||
.P
|
||||
The \fIzstandard\fR format is specified in Y\. Collet, "Zstandard Compression and the \'application/zstd\' Media Type", https://www\.ietf\.org/rfc/rfc8878\.txt, Internet RFC 8878 (February 2021)\.
|
||||
.
|
||||
.SH "BUGS"
|
||||
Report bugs at: https://github\.com/facebook/zstd/issues
|
||||
.
|
||||
.SH "AUTHOR"
|
||||
Yann Collet
|
||||
|
||||
+191
-168
@@ -21,10 +21,11 @@ It is based on the **LZ77** family, with further FSE & huff0 entropy stages.
|
||||
`zstd` offers highly configurable compression speed,
|
||||
from fast modes at > 200 MB/s per core,
|
||||
to strong modes with excellent compression ratios.
|
||||
It also features a very fast decoder, with speeds > 500 MB/s per core.
|
||||
It also features a very fast decoder, with speeds > 500 MB/s per core,
|
||||
which remains roughly stable at all compression settings.
|
||||
|
||||
`zstd` command line syntax is generally similar to gzip,
|
||||
but features the following differences:
|
||||
but features the following few differences:
|
||||
|
||||
- Source files are preserved by default.
|
||||
It's possible to remove them automatically by using the `--rm` command.
|
||||
@@ -105,7 +106,11 @@ the last one takes effect.
|
||||
### Operation Modifiers
|
||||
|
||||
* `-#`:
|
||||
selects `#` compression level \[1-19\] (default: 3)
|
||||
selects `#` compression level \[1-19\] (default: 3).
|
||||
Higher compression levels *generally* produce higher compression ratio at the expense of speed and memory.
|
||||
A rough rule of thumb is that compression speed is expected to be divided by 2 every 2 levels.
|
||||
Technically, each level is mapped to a set of advanced parameters (that can also be modified individually, see below).
|
||||
Because the compressor's behavior highly depends on the content to compress, there's no guarantee of a smooth progression from one level to another.
|
||||
* `--ultra`:
|
||||
unlocks high compression levels 20+ (maximum 22), using a lot more memory.
|
||||
Note that decompression will also require more memory when using these levels.
|
||||
@@ -218,15 +223,24 @@ the last one takes effect.
|
||||
expected. This feature allows for controlling the guess when needed.
|
||||
Exact guesses result in better compression ratios. Overestimates result in slightly
|
||||
degraded compression ratios, while underestimates may result in significant degradation.
|
||||
* `-o FILE`:
|
||||
save result into `FILE`.
|
||||
* `--target-compressed-block-size=#`:
|
||||
Attempt to produce compressed blocks of approximately this size.
|
||||
This will split larger blocks in order to approach this target.
|
||||
This feature is notably useful for improved latency, when the receiver can leverage receiving early incomplete data.
|
||||
This parameter defines a loose target: compressed blocks will target this size "on average", but individual blocks can still be larger or smaller.
|
||||
Enabling this feature can decrease compression speed by up to ~10% at level 1.
|
||||
Higher levels will see smaller relative speed regression, becoming invisible at higher settings.
|
||||
* `-f`, `--force`:
|
||||
disable input and output checks. Allows overwriting existing files, input
|
||||
from console, output to stdout, operating on links, block devices, etc.
|
||||
During decompression and when the output destination is stdout, pass-through
|
||||
unrecognized formats as-is.
|
||||
* `-c`, `--stdout`:
|
||||
write to standard output (even if it is the console); keep original files unchanged.
|
||||
write to standard output (even if it is the console); keep original files (disable `--rm`).
|
||||
* `-o FILE`:
|
||||
save result into `FILE`.
|
||||
Note that this operation is in conflict with `-c`.
|
||||
If both operations are present on the command line, the last expressed one wins.
|
||||
* `--[no-]sparse`:
|
||||
enable / disable sparse FS support,
|
||||
to make files with many zeroes smaller on disk.
|
||||
@@ -283,10 +297,11 @@ the last one takes effect.
|
||||
* `-h`/`-H`, `--help`:
|
||||
display help/long help and exit
|
||||
* `-V`, `--version`:
|
||||
display version number and exit.
|
||||
display version number and immediately exit.
|
||||
note that, since it exits, flags specified after `-V` are effectively ignored.
|
||||
Advanced: `-vV` also displays supported formats.
|
||||
`-vvV` also displays POSIX support.
|
||||
`-q` will only display the version number, suitable for machine reading.
|
||||
`-qV` will only display the version number, suitable for machine reading.
|
||||
* `-v`, `--verbose`:
|
||||
verbose mode, display more information
|
||||
* `-q`, `--quiet`:
|
||||
@@ -297,6 +312,8 @@ the last one takes effect.
|
||||
* `--show-default-cparams`:
|
||||
shows the default compression parameters that will be used for a particular input file, based on the provided compression level and the input size.
|
||||
If the provided file is not a regular file (e.g. a pipe), this flag will output the parameters used for inputs of unknown size.
|
||||
* `--exclude-compressed`:
|
||||
only compress files that are not already compressed.
|
||||
* `--`:
|
||||
All arguments after `--` are treated as files
|
||||
|
||||
@@ -313,11 +330,10 @@ options that intend to mimic the `gzip` behavior:
|
||||
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Employing environment variables to set parameters has security implications.
|
||||
Therefore, this avenue is intentionally limited.
|
||||
Only `ZSTD_CLEVEL` and `ZSTD_NBTHREADS` are currently supported.
|
||||
They set the compression level and number of threads to use during compression, respectively.
|
||||
They set the default compression level and number of threads to use during compression, respectively.
|
||||
|
||||
`ZSTD_CLEVEL` can be used to set the level between 1 and 19 (the "normal" range).
|
||||
If the value of `ZSTD_CLEVEL` is not a valid integer, it will be ignored with a warning message.
|
||||
@@ -326,12 +342,171 @@ If the value of `ZSTD_CLEVEL` is not a valid integer, it will be ignored with a
|
||||
`ZSTD_NBTHREADS` can be used to set the number of threads `zstd` will attempt to use during compression.
|
||||
If the value of `ZSTD_NBTHREADS` is not a valid unsigned integer, it will be ignored with a warning message.
|
||||
`ZSTD_NBTHREADS` has a default value of (`1`), and is capped at ZSTDMT_NBWORKERS_MAX==200.
|
||||
`zstd` must be compiled with multithread support for this to have any effect.
|
||||
`zstd` must be compiled with multithread support for this variable to have any effect.
|
||||
|
||||
They can both be overridden by corresponding command line arguments:
|
||||
`-#` for compression level and `-T#` for number of compression threads.
|
||||
|
||||
|
||||
ADVANCED COMPRESSION OPTIONS
|
||||
----------------------------
|
||||
`zstd` provides 22 predefined regular compression levels plus the fast levels.
|
||||
A compression level is translated internally into multiple advanced parameters that control the behavior of the compressor
|
||||
(one can observe the result of this translation with `--show-default-cparams`).
|
||||
These advanced parameters can be overridden using advanced compression options.
|
||||
|
||||
### --zstd[=options]:
|
||||
The _options_ are provided as a comma-separated list.
|
||||
You may specify only the options you want to change and the rest will be
|
||||
taken from the selected or default compression level.
|
||||
The list of available _options_:
|
||||
|
||||
- `strategy`=_strat_, `strat`=_strat_:
|
||||
Specify a strategy used by a match finder.
|
||||
|
||||
There are 9 strategies numbered from 1 to 9, from fastest to strongest:
|
||||
1=`ZSTD_fast`, 2=`ZSTD_dfast`, 3=`ZSTD_greedy`,
|
||||
4=`ZSTD_lazy`, 5=`ZSTD_lazy2`, 6=`ZSTD_btlazy2`,
|
||||
7=`ZSTD_btopt`, 8=`ZSTD_btultra`, 9=`ZSTD_btultra2`.
|
||||
|
||||
- `windowLog`=_wlog_, `wlog`=_wlog_:
|
||||
Specify the maximum number of bits for a match distance.
|
||||
|
||||
The higher number of increases the chance to find a match which usually
|
||||
improves compression ratio.
|
||||
It also increases memory requirements for the compressor and decompressor.
|
||||
The minimum _wlog_ is 10 (1 KiB) and the maximum is 30 (1 GiB) on 32-bit
|
||||
platforms and 31 (2 GiB) on 64-bit platforms.
|
||||
|
||||
Note: If `windowLog` is set to larger than 27, `--long=windowLog` or
|
||||
`--memory=windowSize` needs to be passed to the decompressor.
|
||||
|
||||
- `hashLog`=_hlog_, `hlog`=_hlog_:
|
||||
Specify the maximum number of bits for a hash table.
|
||||
|
||||
Bigger hash tables cause fewer collisions which usually makes compression
|
||||
faster, but requires more memory during compression.
|
||||
|
||||
The minimum _hlog_ is 6 (64 entries / 256 B) and the maximum is 30 (1B entries / 4 GiB).
|
||||
|
||||
- `chainLog`=_clog_, `clog`=_clog_:
|
||||
Specify the maximum number of bits for the secondary search structure,
|
||||
whose form depends on the selected `strategy`.
|
||||
|
||||
Higher numbers of bits increases the chance to find a match which usually
|
||||
improves compression ratio.
|
||||
It also slows down compression speed and increases memory requirements for
|
||||
compression.
|
||||
This option is ignored for the `ZSTD_fast` `strategy`, which only has the primary hash table.
|
||||
|
||||
The minimum _clog_ is 6 (64 entries / 256 B) and the maximum is 29 (512M entries / 2 GiB) on 32-bit platforms
|
||||
and 30 (1B entries / 4 GiB) on 64-bit platforms.
|
||||
|
||||
- `searchLog`=_slog_, `slog`=_slog_:
|
||||
Specify the maximum number of searches in a hash chain or a binary tree
|
||||
using logarithmic scale.
|
||||
|
||||
More searches increases the chance to find a match which usually increases
|
||||
compression ratio but decreases compression speed.
|
||||
|
||||
The minimum _slog_ is 1 and the maximum is 'windowLog' - 1.
|
||||
|
||||
- `minMatch`=_mml_, `mml`=_mml_:
|
||||
Specify the minimum searched length of a match in a hash table.
|
||||
|
||||
Larger search lengths usually decrease compression ratio but improve
|
||||
decompression speed.
|
||||
|
||||
The minimum _mml_ is 3 and the maximum is 7.
|
||||
|
||||
- `targetLength`=_tlen_, `tlen`=_tlen_:
|
||||
The impact of this field vary depending on selected strategy.
|
||||
|
||||
For `ZSTD_btopt`, `ZSTD_btultra` and `ZSTD_btultra2`, it specifies
|
||||
the minimum match length that causes match finder to stop searching.
|
||||
A larger `targetLength` usually improves compression ratio
|
||||
but decreases compression speed.
|
||||
|
||||
For `ZSTD_fast`, it triggers ultra-fast mode when > 0.
|
||||
The value represents the amount of data skipped between match sampling.
|
||||
Impact is reversed: a larger `targetLength` increases compression speed
|
||||
but decreases compression ratio.
|
||||
|
||||
For all other strategies, this field has no impact.
|
||||
|
||||
The minimum _tlen_ is 0 and the maximum is 128 KiB.
|
||||
|
||||
- `overlapLog`=_ovlog_, `ovlog`=_ovlog_:
|
||||
Determine `overlapSize`, amount of data reloaded from previous job.
|
||||
This parameter is only available when multithreading is enabled.
|
||||
Reloading more data improves compression ratio, but decreases speed.
|
||||
|
||||
The minimum _ovlog_ is 0, and the maximum is 9.
|
||||
1 means "no overlap", hence completely independent jobs.
|
||||
9 means "full overlap", meaning up to `windowSize` is reloaded from previous job.
|
||||
Reducing _ovlog_ by 1 reduces the reloaded amount by a factor 2.
|
||||
For example, 8 means "windowSize/2", and 6 means "windowSize/8".
|
||||
Value 0 is special and means "default": _ovlog_ is automatically determined by `zstd`.
|
||||
In which case, _ovlog_ will range from 6 to 9, depending on selected _strat_.
|
||||
|
||||
- `ldmHashLog`=_lhlog_, `lhlog`=_lhlog_:
|
||||
Specify the maximum size for a hash table used for long distance matching.
|
||||
|
||||
This option is ignored unless long distance matching is enabled.
|
||||
|
||||
Bigger hash tables usually improve compression ratio at the expense of more
|
||||
memory during compression and a decrease in compression speed.
|
||||
|
||||
The minimum _lhlog_ is 6 and the maximum is 30 (default: 20).
|
||||
|
||||
- `ldmMinMatch`=_lmml_, `lmml`=_lmml_:
|
||||
Specify the minimum searched length of a match for long distance matching.
|
||||
|
||||
This option is ignored unless long distance matching is enabled.
|
||||
|
||||
Larger/very small values usually decrease compression ratio.
|
||||
|
||||
The minimum _lmml_ is 4 and the maximum is 4096 (default: 64).
|
||||
|
||||
- `ldmBucketSizeLog`=_lblog_, `lblog`=_lblog_:
|
||||
Specify the size of each bucket for the hash table used for long distance
|
||||
matching.
|
||||
|
||||
This option is ignored unless long distance matching is enabled.
|
||||
|
||||
Larger bucket sizes improve collision resolution but decrease compression
|
||||
speed.
|
||||
|
||||
The minimum _lblog_ is 1 and the maximum is 8 (default: 3).
|
||||
|
||||
- `ldmHashRateLog`=_lhrlog_, `lhrlog`=_lhrlog_:
|
||||
Specify the frequency of inserting entries into the long distance matching
|
||||
hash table.
|
||||
|
||||
This option is ignored unless long distance matching is enabled.
|
||||
|
||||
Larger values will improve compression speed. Deviating far from the
|
||||
default value will likely result in a decrease in compression ratio.
|
||||
|
||||
The default value is `wlog - lhlog`.
|
||||
|
||||
### Example
|
||||
The following parameters sets advanced compression options to something
|
||||
similar to predefined level 19 for files bigger than 256 KB:
|
||||
|
||||
`--zstd`=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6
|
||||
|
||||
### -B#:
|
||||
Specify the size of each compression job.
|
||||
This parameter is only available when multi-threading is enabled.
|
||||
Each compression job is run in parallel, so this value indirectly impacts the nb of active threads.
|
||||
Default job size varies depending on compression level (generally `4 * windowSize`).
|
||||
`-B#` makes it possible to manually select a custom size.
|
||||
Note that job size must respect a minimum value which is enforced transparently.
|
||||
This minimum is either 512 KB, or `overlapSize`, whichever is largest.
|
||||
Different job sizes will lead to non-identical compressed frames.
|
||||
|
||||
|
||||
DICTIONARY BUILDER
|
||||
------------------
|
||||
`zstd` offers _dictionary_ compression,
|
||||
@@ -484,178 +659,26 @@ Compression of small files similar to the sample set will be greatly improved.
|
||||
|
||||
BENCHMARK
|
||||
---------
|
||||
The `zstd` CLI provides a benchmarking mode that can be used to easily find suitable compression parameters, or alternatively to benchmark a computer's performance.
|
||||
Note that the results are highly dependent on the content being compressed.
|
||||
|
||||
* `-b#`:
|
||||
benchmark file(s) using compression level #
|
||||
* `-e#`:
|
||||
benchmark file(s) using multiple compression levels, from `-b#` to `-e#` (inclusive)
|
||||
* `-d`:
|
||||
benchmark decompression speed only (requires providing an already zstd-compressed content)
|
||||
* `-i#`:
|
||||
minimum evaluation time, in seconds (default: 3s), benchmark mode only
|
||||
* `-B#`, `--block-size=#`:
|
||||
cut file(s) into independent chunks of size # (default: no chunking)
|
||||
* `--priority=rt`:
|
||||
set process priority to real-time
|
||||
set process priority to real-time (Windows)
|
||||
|
||||
**Output Format:** CompressionLevel#Filename: InputSize -> OutputSize (CompressionRatio), CompressionSpeed, DecompressionSpeed
|
||||
|
||||
**Methodology:** For both compression and decompression speed, the entire input is compressed/decompressed in-memory to measure speed. A run lasts at least 1 sec, so when files are small, they are compressed/decompressed several times per run, in order to improve measurement accuracy.
|
||||
|
||||
ADVANCED COMPRESSION OPTIONS
|
||||
----------------------------
|
||||
### -B#:
|
||||
Specify the size of each compression job.
|
||||
This parameter is only available when multi-threading is enabled.
|
||||
Each compression job is run in parallel, so this value indirectly impacts the nb of active threads.
|
||||
Default job size varies depending on compression level (generally `4 * windowSize`).
|
||||
`-B#` makes it possible to manually select a custom size.
|
||||
Note that job size must respect a minimum value which is enforced transparently.
|
||||
This minimum is either 512 KB, or `overlapSize`, whichever is largest.
|
||||
Different job sizes will lead to non-identical compressed frames.
|
||||
|
||||
### --zstd[=options]:
|
||||
`zstd` provides 22 predefined regular compression levels plus the fast levels.
|
||||
This compression level is translated internally into a number of specific parameters that actually control the behavior of the compressor.
|
||||
(You can see the result of this translation with `--show-default-cparams`.)
|
||||
These specific parameters can be overridden with advanced compression options.
|
||||
The _options_ are provided as a comma-separated list.
|
||||
You may specify only the options you want to change and the rest will be
|
||||
taken from the selected or default compression level.
|
||||
The list of available _options_:
|
||||
|
||||
- `strategy`=_strat_, `strat`=_strat_:
|
||||
Specify a strategy used by a match finder.
|
||||
|
||||
There are 9 strategies numbered from 1 to 9, from fastest to strongest:
|
||||
1=`ZSTD_fast`, 2=`ZSTD_dfast`, 3=`ZSTD_greedy`,
|
||||
4=`ZSTD_lazy`, 5=`ZSTD_lazy2`, 6=`ZSTD_btlazy2`,
|
||||
7=`ZSTD_btopt`, 8=`ZSTD_btultra`, 9=`ZSTD_btultra2`.
|
||||
|
||||
- `windowLog`=_wlog_, `wlog`=_wlog_:
|
||||
Specify the maximum number of bits for a match distance.
|
||||
|
||||
The higher number of increases the chance to find a match which usually
|
||||
improves compression ratio.
|
||||
It also increases memory requirements for the compressor and decompressor.
|
||||
The minimum _wlog_ is 10 (1 KiB) and the maximum is 30 (1 GiB) on 32-bit
|
||||
platforms and 31 (2 GiB) on 64-bit platforms.
|
||||
|
||||
Note: If `windowLog` is set to larger than 27, `--long=windowLog` or
|
||||
`--memory=windowSize` needs to be passed to the decompressor.
|
||||
|
||||
- `hashLog`=_hlog_, `hlog`=_hlog_:
|
||||
Specify the maximum number of bits for a hash table.
|
||||
|
||||
Bigger hash tables cause fewer collisions which usually makes compression
|
||||
faster, but requires more memory during compression.
|
||||
|
||||
The minimum _hlog_ is 6 (64 entries / 256 B) and the maximum is 30 (1B entries / 4 GiB).
|
||||
|
||||
- `chainLog`=_clog_, `clog`=_clog_:
|
||||
Specify the maximum number of bits for the secondary search structure,
|
||||
whose form depends on the selected `strategy`.
|
||||
|
||||
Higher numbers of bits increases the chance to find a match which usually
|
||||
improves compression ratio.
|
||||
It also slows down compression speed and increases memory requirements for
|
||||
compression.
|
||||
This option is ignored for the `ZSTD_fast` `strategy`, which only has the primary hash table.
|
||||
|
||||
The minimum _clog_ is 6 (64 entries / 256 B) and the maximum is 29 (512M entries / 2 GiB) on 32-bit platforms
|
||||
and 30 (1B entries / 4 GiB) on 64-bit platforms.
|
||||
|
||||
- `searchLog`=_slog_, `slog`=_slog_:
|
||||
Specify the maximum number of searches in a hash chain or a binary tree
|
||||
using logarithmic scale.
|
||||
|
||||
More searches increases the chance to find a match which usually increases
|
||||
compression ratio but decreases compression speed.
|
||||
|
||||
The minimum _slog_ is 1 and the maximum is 'windowLog' - 1.
|
||||
|
||||
- `minMatch`=_mml_, `mml`=_mml_:
|
||||
Specify the minimum searched length of a match in a hash table.
|
||||
|
||||
Larger search lengths usually decrease compression ratio but improve
|
||||
decompression speed.
|
||||
|
||||
The minimum _mml_ is 3 and the maximum is 7.
|
||||
|
||||
- `targetLength`=_tlen_, `tlen`=_tlen_:
|
||||
The impact of this field vary depending on selected strategy.
|
||||
|
||||
For `ZSTD_btopt`, `ZSTD_btultra` and `ZSTD_btultra2`, it specifies
|
||||
the minimum match length that causes match finder to stop searching.
|
||||
A larger `targetLength` usually improves compression ratio
|
||||
but decreases compression speed.
|
||||
|
||||
For `ZSTD_fast`, it triggers ultra-fast mode when > 0.
|
||||
The value represents the amount of data skipped between match sampling.
|
||||
Impact is reversed: a larger `targetLength` increases compression speed
|
||||
but decreases compression ratio.
|
||||
|
||||
For all other strategies, this field has no impact.
|
||||
|
||||
The minimum _tlen_ is 0 and the maximum is 128 KiB.
|
||||
|
||||
- `overlapLog`=_ovlog_, `ovlog`=_ovlog_:
|
||||
Determine `overlapSize`, amount of data reloaded from previous job.
|
||||
This parameter is only available when multithreading is enabled.
|
||||
Reloading more data improves compression ratio, but decreases speed.
|
||||
|
||||
The minimum _ovlog_ is 0, and the maximum is 9.
|
||||
1 means "no overlap", hence completely independent jobs.
|
||||
9 means "full overlap", meaning up to `windowSize` is reloaded from previous job.
|
||||
Reducing _ovlog_ by 1 reduces the reloaded amount by a factor 2.
|
||||
For example, 8 means "windowSize/2", and 6 means "windowSize/8".
|
||||
Value 0 is special and means "default": _ovlog_ is automatically determined by `zstd`.
|
||||
In which case, _ovlog_ will range from 6 to 9, depending on selected _strat_.
|
||||
|
||||
- `ldmHashLog`=_lhlog_, `lhlog`=_lhlog_:
|
||||
Specify the maximum size for a hash table used for long distance matching.
|
||||
|
||||
This option is ignored unless long distance matching is enabled.
|
||||
|
||||
Bigger hash tables usually improve compression ratio at the expense of more
|
||||
memory during compression and a decrease in compression speed.
|
||||
|
||||
The minimum _lhlog_ is 6 and the maximum is 30 (default: 20).
|
||||
|
||||
- `ldmMinMatch`=_lmml_, `lmml`=_lmml_:
|
||||
Specify the minimum searched length of a match for long distance matching.
|
||||
|
||||
This option is ignored unless long distance matching is enabled.
|
||||
|
||||
Larger/very small values usually decrease compression ratio.
|
||||
|
||||
The minimum _lmml_ is 4 and the maximum is 4096 (default: 64).
|
||||
|
||||
- `ldmBucketSizeLog`=_lblog_, `lblog`=_lblog_:
|
||||
Specify the size of each bucket for the hash table used for long distance
|
||||
matching.
|
||||
|
||||
This option is ignored unless long distance matching is enabled.
|
||||
|
||||
Larger bucket sizes improve collision resolution but decrease compression
|
||||
speed.
|
||||
|
||||
The minimum _lblog_ is 1 and the maximum is 8 (default: 3).
|
||||
|
||||
- `ldmHashRateLog`=_lhrlog_, `lhrlog`=_lhrlog_:
|
||||
Specify the frequency of inserting entries into the long distance matching
|
||||
hash table.
|
||||
|
||||
This option is ignored unless long distance matching is enabled.
|
||||
|
||||
Larger values will improve compression speed. Deviating far from the
|
||||
default value will likely result in a decrease in compression ratio.
|
||||
|
||||
The default value is `wlog - lhlog`.
|
||||
|
||||
### Example
|
||||
The following parameters sets advanced compression options to something
|
||||
similar to predefined level 19 for files bigger than 256 KB:
|
||||
|
||||
`--zstd`=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
+35
-27
@@ -138,8 +138,8 @@ static int exeNameMatch(const char* exeName, const char* test)
|
||||
* Command Line
|
||||
**************************************/
|
||||
/* print help either in `stderr` or `stdout` depending on originating request
|
||||
* error (badusage) => stderr
|
||||
* help (usage_advanced) => stdout
|
||||
* error (badUsage) => stderr
|
||||
* help (usageAdvanced) => stdout
|
||||
*/
|
||||
static void usage(FILE* f, const char* programName)
|
||||
{
|
||||
@@ -175,7 +175,7 @@ static void usage(FILE* f, const char* programName)
|
||||
DISPLAY_F(f, "\n");
|
||||
}
|
||||
|
||||
static void usage_advanced(const char* programName)
|
||||
static void usageAdvanced(const char* programName)
|
||||
{
|
||||
DISPLAYOUT(WELCOME_MESSAGE);
|
||||
DISPLAYOUT("\n");
|
||||
@@ -316,9 +316,9 @@ static void usage_advanced(const char* programName)
|
||||
|
||||
}
|
||||
|
||||
static void badusage(const char* programName)
|
||||
static void badUsage(const char* programName, const char* parameter)
|
||||
{
|
||||
DISPLAYLEVEL(1, "Incorrect parameters \n");
|
||||
DISPLAYLEVEL(1, "Incorrect parameter: %s \n", parameter);
|
||||
if (g_displayLevel >= 2) usage(stderr, programName);
|
||||
}
|
||||
|
||||
@@ -589,7 +589,7 @@ static ZDICT_fastCover_params_t defaultFastCoverParams(void)
|
||||
|
||||
|
||||
/** parseAdaptParameters() :
|
||||
* reads adapt parameters from *stringPtr (e.g. "--zstd=min=1,max=19) and store them into adaptMinPtr and adaptMaxPtr.
|
||||
* reads adapt parameters from *stringPtr (e.g. "--adapt=min=1,max=19) and store them into adaptMinPtr and adaptMaxPtr.
|
||||
* Both adaptMinPtr and adaptMaxPtr must be already allocated and correctly initialized.
|
||||
* There is no guarantee that any of these values will be updated.
|
||||
* @return 1 means that parsing was successful,
|
||||
@@ -856,7 +856,7 @@ int main(int argCount, const char* argv[])
|
||||
ZSTD_paramSwitch_e useRowMatchFinder = ZSTD_ps_auto;
|
||||
FIO_compressionType_t cType = FIO_zstdCompression;
|
||||
unsigned nbWorkers = 0;
|
||||
double compressibility = 0.5;
|
||||
double compressibility = -1.0; /* lorem ipsum generator */
|
||||
unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */
|
||||
size_t blockSize = 0;
|
||||
|
||||
@@ -933,6 +933,7 @@ int main(int argCount, const char* argv[])
|
||||
/* command switches */
|
||||
for (argNb=1; argNb<argCount; argNb++) {
|
||||
const char* argument = argv[argNb];
|
||||
const char* const originalArgument = argument;
|
||||
if (!argument) continue; /* Protection if argument empty */
|
||||
|
||||
if (nextArgumentsAreFiles) {
|
||||
@@ -958,10 +959,10 @@ int main(int argCount, const char* argv[])
|
||||
if (!strcmp(argument, "--uncompress")) { operation=zom_decompress; continue; }
|
||||
if (!strcmp(argument, "--force")) { FIO_overwriteMode(prefs); forceStdin=1; forceStdout=1; followLinks=1; allowBlockDevices=1; continue; }
|
||||
if (!strcmp(argument, "--version")) { printVersion(); CLEAN_RETURN(0); }
|
||||
if (!strcmp(argument, "--help")) { usage_advanced(programName); CLEAN_RETURN(0); }
|
||||
if (!strcmp(argument, "--help")) { usageAdvanced(programName); CLEAN_RETURN(0); }
|
||||
if (!strcmp(argument, "--verbose")) { g_displayLevel++; continue; }
|
||||
if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; }
|
||||
if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; removeSrcFile=0; continue; }
|
||||
if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; continue; }
|
||||
if (!strcmp(argument, "--ultra")) { ultra=1; continue; }
|
||||
if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(prefs, 2); continue; }
|
||||
if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(prefs, 0); continue; }
|
||||
@@ -983,7 +984,7 @@ int main(int argCount, const char* argv[])
|
||||
if (!strcmp(argument, "--adapt")) { adapt = 1; continue; }
|
||||
if (!strcmp(argument, "--no-row-match-finder")) { useRowMatchFinder = ZSTD_ps_disable; continue; }
|
||||
if (!strcmp(argument, "--row-match-finder")) { useRowMatchFinder = ZSTD_ps_enable; continue; }
|
||||
if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badusage(programName); CLEAN_RETURN(1); } continue; }
|
||||
if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } continue; }
|
||||
if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; }
|
||||
if (!strcmp(argument, "--format=zstd")) { suffix = ZSTD_EXTENSION; cType = FIO_zstdCompression; continue; }
|
||||
if (!strcmp(argument, "--mmap-dict")) { mmapDict = ZSTD_ps_enable; continue; }
|
||||
@@ -1022,8 +1023,8 @@ int main(int argCount, const char* argv[])
|
||||
dict = cover;
|
||||
/* Allow optional arguments following an = */
|
||||
if (*argument == 0) { memset(&coverParams, 0, sizeof(coverParams)); }
|
||||
else if (*argument++ != '=') { badusage(programName); CLEAN_RETURN(1); }
|
||||
else if (!parseCoverParameters(argument, &coverParams)) { badusage(programName); CLEAN_RETURN(1); }
|
||||
else if (*argument++ != '=') { badUsage(programName, originalArgument); CLEAN_RETURN(1); }
|
||||
else if (!parseCoverParameters(argument, &coverParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); }
|
||||
continue;
|
||||
}
|
||||
if (longCommandWArg(&argument, "--train-fastcover")) {
|
||||
@@ -1033,8 +1034,8 @@ int main(int argCount, const char* argv[])
|
||||
dict = fastCover;
|
||||
/* Allow optional arguments following an = */
|
||||
if (*argument == 0) { memset(&fastCoverParams, 0, sizeof(fastCoverParams)); }
|
||||
else if (*argument++ != '=') { badusage(programName); CLEAN_RETURN(1); }
|
||||
else if (!parseFastCoverParameters(argument, &fastCoverParams)) { badusage(programName); CLEAN_RETURN(1); }
|
||||
else if (*argument++ != '=') { badUsage(programName, originalArgument); CLEAN_RETURN(1); }
|
||||
else if (!parseFastCoverParameters(argument, &fastCoverParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); }
|
||||
continue;
|
||||
}
|
||||
if (longCommandWArg(&argument, "--train-legacy")) {
|
||||
@@ -1044,8 +1045,8 @@ int main(int argCount, const char* argv[])
|
||||
dict = legacy;
|
||||
/* Allow optional arguments following an = */
|
||||
if (*argument == 0) { continue; }
|
||||
else if (*argument++ != '=') { badusage(programName); CLEAN_RETURN(1); }
|
||||
else if (!parseLegacyParameters(argument, &dictSelect)) { badusage(programName); CLEAN_RETURN(1); }
|
||||
else if (*argument++ != '=') { badUsage(programName, originalArgument); CLEAN_RETURN(1); }
|
||||
else if (!parseLegacyParameters(argument, &dictSelect)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); }
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
@@ -1056,7 +1057,7 @@ int main(int argCount, const char* argv[])
|
||||
if (longCommandWArg(&argument, "--block-size")) { NEXT_TSIZE(blockSize); continue; }
|
||||
if (longCommandWArg(&argument, "--maxdict")) { NEXT_UINT32(maxDictSize); continue; }
|
||||
if (longCommandWArg(&argument, "--dictID")) { NEXT_UINT32(dictID); continue; }
|
||||
if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) { badusage(programName); CLEAN_RETURN(1); } ; cType = FIO_zstdCompression; continue; }
|
||||
if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } ; cType = FIO_zstdCompression; continue; }
|
||||
if (longCommandWArg(&argument, "--stream-size")) { NEXT_TSIZE(streamSrcSize); continue; }
|
||||
if (longCommandWArg(&argument, "--target-compressed-block-size")) { NEXT_TSIZE(targetCBlockSize); continue; }
|
||||
if (longCommandWArg(&argument, "--size-hint")) { NEXT_TSIZE(srcSizeHint); continue; }
|
||||
@@ -1098,7 +1099,7 @@ int main(int argCount, const char* argv[])
|
||||
ldmWindowLog = readU32FromChar(&argument);
|
||||
} else if (*argument != 0) {
|
||||
/* Invalid character following --long */
|
||||
badusage(programName);
|
||||
badUsage(programName, originalArgument);
|
||||
CLEAN_RETURN(1);
|
||||
} else {
|
||||
ldmWindowLog = g_defaultMaxWindowLog;
|
||||
@@ -1120,12 +1121,12 @@ int main(int argCount, const char* argv[])
|
||||
if (fastLevel) {
|
||||
dictCLevel = cLevel = -(int)fastLevel;
|
||||
} else {
|
||||
badusage(programName);
|
||||
badUsage(programName, originalArgument);
|
||||
CLEAN_RETURN(1);
|
||||
}
|
||||
} else if (*argument != 0) {
|
||||
/* Invalid character following --fast */
|
||||
badusage(programName);
|
||||
badUsage(programName, originalArgument);
|
||||
CLEAN_RETURN(1);
|
||||
} else {
|
||||
cLevel = -1; /* default for --fast */
|
||||
@@ -1141,7 +1142,8 @@ int main(int argCount, const char* argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
/* fall-through, will trigger bad_usage() later on */
|
||||
badUsage(programName, originalArgument);
|
||||
CLEAN_RETURN(1);
|
||||
}
|
||||
|
||||
argument++;
|
||||
@@ -1159,7 +1161,7 @@ int main(int argCount, const char* argv[])
|
||||
{
|
||||
/* Display help */
|
||||
case 'V': printVersion(); CLEAN_RETURN(0); /* Version Only */
|
||||
case 'H': usage_advanced(programName); CLEAN_RETURN(0);
|
||||
case 'H': usageAdvanced(programName); CLEAN_RETURN(0);
|
||||
case 'h': usage(stdout, programName); CLEAN_RETURN(0);
|
||||
|
||||
/* Compress */
|
||||
@@ -1174,7 +1176,10 @@ int main(int argCount, const char* argv[])
|
||||
operation=zom_decompress; argument++; break;
|
||||
|
||||
/* Force stdout, even if stdout==console */
|
||||
case 'c': forceStdout=1; outFileName=stdoutmark; removeSrcFile=0; argument++; break;
|
||||
case 'c': forceStdout=1; outFileName=stdoutmark; argument++; break;
|
||||
|
||||
/* destination file name */
|
||||
case 'o': argument++; NEXT_FIELD(outFileName); break;
|
||||
|
||||
/* do not store filename - gzip compatibility - nothing to do */
|
||||
case 'n': argument++; break;
|
||||
@@ -1200,9 +1205,6 @@ int main(int argCount, const char* argv[])
|
||||
/* test compressed file */
|
||||
case 't': operation=zom_test; argument++; break;
|
||||
|
||||
/* destination file name */
|
||||
case 'o': argument++; NEXT_FIELD(outFileName); break;
|
||||
|
||||
/* limit memory */
|
||||
case 'M':
|
||||
argument++;
|
||||
@@ -1277,7 +1279,12 @@ int main(int argCount, const char* argv[])
|
||||
break;
|
||||
|
||||
/* unknown command */
|
||||
default : badusage(programName); CLEAN_RETURN(1);
|
||||
default :
|
||||
{ char shortArgument[3] = {'-', 0, 0};
|
||||
shortArgument[1] = argument[0];
|
||||
badUsage(programName, shortArgument);
|
||||
CLEAN_RETURN(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@@ -1368,6 +1375,7 @@ int main(int argCount, const char* argv[])
|
||||
CLEAN_RETURN(1);
|
||||
}
|
||||
benchParams.blockSize = blockSize;
|
||||
benchParams.targetCBlockSize = targetCBlockSize;
|
||||
benchParams.nbWorkers = (int)nbWorkers;
|
||||
benchParams.realTime = (unsigned)setRealTimePrio;
|
||||
benchParams.nbSeconds = bench_nbSeconds;
|
||||
|
||||
+11
-2
@@ -1,17 +1,26 @@
|
||||
.TH "ZSTDGREP" "1" "March 2023" "zstd 1.5.5" "User Commands"
|
||||
.
|
||||
.TH "ZSTDGREP" "1" "March 2024" "zstd 1.5.6" "User Commands"
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBzstdgrep\fR \- print lines matching a pattern in zstandard\-compressed files
|
||||
.
|
||||
.SH "SYNOPSIS"
|
||||
\fBzstdgrep\fR [\fIgrep\-flags\fR] [\-\-] \fIpattern\fR [\fIfiles\fR \|\.\|\.\|\.]
|
||||
\fBzstdgrep\fR [\fIgrep\-flags\fR] [\-\-] \fIpattern\fR [\fIfiles\fR \.\.\.]
|
||||
.
|
||||
.SH "DESCRIPTION"
|
||||
\fBzstdgrep\fR runs \fBgrep\fR(1) on files, or \fBstdin\fR if no files argument is given, after decompressing them with \fBzstdcat\fR(1)\.
|
||||
.
|
||||
.P
|
||||
The \fIgrep\-flags\fR and \fIpattern\fR arguments are passed on to \fBgrep\fR(1)\. If an \fB\-e\fR flag is found in the \fIgrep\-flags\fR, \fBzstdgrep\fR will not look for a \fIpattern\fR argument\.
|
||||
.
|
||||
.P
|
||||
Note that modern \fBgrep\fR alternatives such as \fBripgrep\fR (\fBrg\fR(1)) support \fBzstd\fR\-compressed files out of the box, and can prove better alternatives than \fBzstdgrep\fR notably for unsupported complex pattern searches\. Note though that such alternatives may also feature some minor command line differences\.
|
||||
.
|
||||
.SH "EXIT STATUS"
|
||||
In case of missing arguments or missing pattern, 1 will be returned, otherwise 0\.
|
||||
.
|
||||
.SH "SEE ALSO"
|
||||
\fBzstd\fR(1)
|
||||
.
|
||||
.SH "AUTHORS"
|
||||
Thomas Klausner \fIwiz@NetBSD\.org\fR
|
||||
|
||||
+7
-2
@@ -1,9 +1,14 @@
|
||||
.TH "ZSTDLESS" "1" "March 2023" "zstd 1.5.5" "User Commands"
|
||||
.
|
||||
.TH "ZSTDLESS" "1" "March 2024" "zstd 1.5.6" "User Commands"
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBzstdless\fR \- view zstandard\-compressed files
|
||||
.
|
||||
.SH "SYNOPSIS"
|
||||
\fBzstdless\fR [\fIflags\fR] [\fIfile\fR \|\.\|\.\|\.]
|
||||
\fBzstdless\fR [\fIflags\fR] [\fIfile\fR \.\.\.]
|
||||
.
|
||||
.SH "DESCRIPTION"
|
||||
\fBzstdless\fR runs \fBless\fR(1) on files or stdin, if no \fIfile\fR argument is given, after decompressing them with \fBzstdcat\fR(1)\.
|
||||
.
|
||||
.SH "SEE ALSO"
|
||||
\fBzstd\fR(1)
|
||||
|
||||
@@ -67,3 +67,6 @@ speedTest.pid
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Specific exclusions
|
||||
!golden-decompression/*.zst
|
||||
|
||||
+53
-44
@@ -20,43 +20,45 @@
|
||||
# zstreamtest32: Same as zstreamtest, but forced to compile in 32-bits mode
|
||||
# ##########################################################################
|
||||
|
||||
LIBZSTD = ../lib
|
||||
|
||||
ZSTD_LEGACY_SUPPORT ?= 0
|
||||
ZSTD_LEGACY_SUPPORT ?= 5
|
||||
export ZSTD_LEGACY_SUPPORT
|
||||
|
||||
DEBUGLEVEL ?= 2
|
||||
export DEBUGLEVEL # transmit value to sub-makefiles
|
||||
|
||||
include $(LIBZSTD)/libzstd.mk
|
||||
LIBZSTD_MK_DIR := ../lib
|
||||
include $(LIBZSTD_MK_DIR)/libzstd.mk
|
||||
|
||||
ZSTDDIR = $(LIBZSTD)
|
||||
PRGDIR = ../programs
|
||||
PYTHON ?= python3
|
||||
TESTARTEFACT := versionsTest
|
||||
|
||||
DEBUGFLAGS += -g -Wno-c++-compat
|
||||
CPPFLAGS += -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
|
||||
-I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR) \
|
||||
CPPFLAGS += -I$(LIB_SRCDIR) -I$(LIB_SRCDIR)/common -I$(LIB_SRCDIR)/compress -I$(LIB_SRCDIR)/legacy \
|
||||
-I$(LIB_SRCDIR)/dictBuilder -I$(LIB_SRCDIR)/deprecated -I$(PRGDIR) \
|
||||
-DZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY=1
|
||||
|
||||
ZSTDCOMMON_FILES := $(sort $(ZSTD_COMMON_FILES))
|
||||
ZSTDCOMP_FILES := $(sort $(ZSTD_COMPRESS_FILES))
|
||||
ZSTDDECOMP_FILES := $(sort $(ZSTD_DECOMPRESS_FILES))
|
||||
ZSTD_FILES := $(ZSTDDECOMP_FILES) $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES)
|
||||
ZSTDLEGACY_FILES := $(sort $(wildcard $(LIB_SRCDIR)/legacy/*.c))
|
||||
ZSTD_FILES := $(ZSTDDECOMP_FILES) $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) $(ZSTDLEGACY_FILES)
|
||||
ZDICT_FILES := $(sort $(ZSTD_DICTBUILDER_FILES))
|
||||
|
||||
ZSTD_F1 := $(sort $(wildcard $(ZSTD_FILES)))
|
||||
ZSTD_OBJ1 := $(subst $(ZSTDDIR)/common/,zstdm_,$(ZSTD_F1))
|
||||
ZSTD_OBJ2 := $(subst $(ZSTDDIR)/compress/,zstdc_,$(ZSTD_OBJ1))
|
||||
ZSTD_OBJ3 := $(subst $(ZSTDDIR)/decompress/,zstdd_,$(ZSTD_OBJ2))
|
||||
ZSTD_OBJ4 := $(ZSTD_OBJ3:.c=.o)
|
||||
ZSTD_OBJECTS := $(ZSTD_OBJ4:.S=.o)
|
||||
ZSTD_OBJ1 := $(subst $(LIB_SRCDIR)/common/,zstdm_,$(ZSTD_F1))
|
||||
ZSTD_OBJ2 := $(subst $(LIB_SRCDIR)/compress/,zstdc_,$(ZSTD_OBJ1))
|
||||
ZSTD_OBJ3 := $(subst $(LIB_SRCDIR)/decompress/,zstdd_,$(ZSTD_OBJ2))
|
||||
ZSTD_OBJ4 := $(subst $(LIB_SRCDIR)/legacy/,zstdl_,$(ZSTD_OBJ3))
|
||||
ZSTD_OBJ5 := $(ZSTD_OBJ4:.c=.o)
|
||||
ZSTD_OBJECTS := $(ZSTD_OBJ5:.S=.o)
|
||||
|
||||
ZSTDMT_OBJ1 := $(subst $(ZSTDDIR)/common/,zstdmt_m_,$(ZSTD_F1))
|
||||
ZSTDMT_OBJ2 := $(subst $(ZSTDDIR)/compress/,zstdmt_c_,$(ZSTDMT_OBJ1))
|
||||
ZSTDMT_OBJ3 := $(subst $(ZSTDDIR)/decompress/,zstdmt_d_,$(ZSTDMT_OBJ2))
|
||||
ZSTDMT_OBJ4 := $(ZSTDMT_OBJ3:.c=.o)
|
||||
ZSTDMT_OBJECTS := $(ZSTDMT_OBJ4:.S=.o)
|
||||
ZSTDMT_OBJ1 := $(subst $(LIB_SRCDIR)/common/,zstdmt_m_,$(ZSTD_F1))
|
||||
ZSTDMT_OBJ2 := $(subst $(LIB_SRCDIR)/compress/,zstdmt_c_,$(ZSTDMT_OBJ1))
|
||||
ZSTDMT_OBJ3 := $(subst $(LIB_SRCDIR)/decompress/,zstdmt_d_,$(ZSTDMT_OBJ2))
|
||||
ZSTDMT_OBJ4 := $(subst $(LIB_SRCDIR)/legacy/,zstdmt_l_,$(ZSTDMT_OBJ3))
|
||||
ZSTDMT_OBJ5 := $(ZSTDMT_OBJ4:.c=.o)
|
||||
ZSTDMT_OBJECTS := $(ZSTDMT_OBJ5:.S=.o)
|
||||
|
||||
# Define *.exe as extension for Windows systems
|
||||
ifneq (,$(filter Windows%,$(OS)))
|
||||
@@ -100,40 +102,46 @@ zstd zstd32 zstd-nolegacy zstd-dll:
|
||||
|
||||
.PHONY: libzstd
|
||||
libzstd :
|
||||
$(MAKE) -C $(ZSTDDIR) libzstd MOREFLAGS+="$(DEBUGFLAGS)"
|
||||
$(MAKE) -C $(LIB_SRCDIR) libzstd MOREFLAGS+="$(DEBUGFLAGS)"
|
||||
|
||||
%-dll : libzstd
|
||||
%-dll : LDFLAGS += -L$(ZSTDDIR) -lzstd
|
||||
%-dll : LDFLAGS += -L$(LIB_BINDIR) -lzstd
|
||||
|
||||
$(ZSTDDIR)/libzstd.a :
|
||||
$(MAKE) -C $(ZSTDDIR) libzstd.a
|
||||
$(LIB_BINDIR)/libzstd.a :
|
||||
$(MAKE) -C $(LIB_SRCDIR) libzstd.a
|
||||
|
||||
zstdm_%.o : $(ZSTDDIR)/common/%.c
|
||||
zstdm_%.o : $(LIB_SRCDIR)/common/%.c
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
zstdc_%.o : $(ZSTDDIR)/compress/%.c
|
||||
zstdc_%.o : $(LIB_SRCDIR)/compress/%.c
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
zstdd_%.o : $(ZSTDDIR)/decompress/%.c
|
||||
zstdd_%.o : $(LIB_SRCDIR)/decompress/%.c
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
zstdd_%.o : $(ZSTDDIR)/decompress/%.S
|
||||
zstdd_%.o : $(LIB_SRCDIR)/decompress/%.S
|
||||
$(CC) -c $(CPPFLAGS) $(ASFLAGS) $< -o $@
|
||||
|
||||
zstdl_%.o : $(LIB_SRCDIR)/legacy/%.c
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
zstdmt%.o : CPPFLAGS += $(MULTITHREAD_CPP)
|
||||
|
||||
zstdmt_m_%.o : $(ZSTDDIR)/common/%.c
|
||||
zstdmt_m_%.o : $(LIB_SRCDIR)/common/%.c
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
zstdmt_c_%.o : $(ZSTDDIR)/compress/%.c
|
||||
zstdmt_c_%.o : $(LIB_SRCDIR)/compress/%.c
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
zstdmt_d_%.o : $(ZSTDDIR)/decompress/%.c
|
||||
zstdmt_d_%.o : $(LIB_SRCDIR)/decompress/%.c
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
zstdmt_d_%.o : $(ZSTDDIR)/decompress/%.S
|
||||
zstdmt_d_%.o : $(LIB_SRCDIR)/decompress/%.S
|
||||
$(CC) -c $(CPPFLAGS) $(ASFLAGS) $< -o $@
|
||||
|
||||
zstdmt_l_%.o : $(LIB_SRCDIR)/legacy/%.c
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
FULLBENCHS := fullbench fullbench32
|
||||
CLEAN += $(FULLBENCHS)
|
||||
fullbench32: CPPFLAGS += -m32
|
||||
@@ -146,12 +154,12 @@ $(FULLBENCHS) : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR
|
||||
|
||||
CLEAN += fullbench-lib
|
||||
fullbench-lib : CPPFLAGS += -DXXH_NAMESPACE=ZSTD_
|
||||
fullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c $(ZSTDDIR)/libzstd.a fullbench.c
|
||||
fullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c $(LIB_SRCDIR)/libzstd.a fullbench.c
|
||||
$(LINK.c) $^ -o $@$(EXT)
|
||||
|
||||
# note : broken : requires symbols unavailable from dynamic library
|
||||
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) -DZSTD_DLL_IMPORT=1 $(LIB_SRCDIR)/dll/libzstd.dll
|
||||
$(LINK.c) $^ $(LDLIBS) -o $@$(EXT)
|
||||
|
||||
CLEAN += fuzzer fuzzer32
|
||||
@@ -165,7 +173,7 @@ fuzzer32 : $(ZSTD_FILES)
|
||||
$(LINK.c) $^ -o $@$(EXT)
|
||||
|
||||
# note : broken : requires symbols unavailable from dynamic library
|
||||
fuzzer-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c
|
||||
fuzzer-dll : $(LIB_SRCDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)
|
||||
|
||||
CLEAN += zstreamtest zstreamtest32
|
||||
@@ -196,17 +204,17 @@ zstreamtest_ubsan : $(ZSTREAMFILES)
|
||||
$(LINK.c) $(MULTITHREAD) $^ -o $@$(EXT)
|
||||
|
||||
# note : broken : requires symbols unavailable from dynamic library
|
||||
zstreamtest-dll : $(ZSTDDIR)/common/xxhash.c # xxh symbols not exposed from dll
|
||||
zstreamtest-dll : $(LIB_SRCDIR)/common/xxhash.c # xxh symbols not exposed from dll
|
||||
zstreamtest-dll : $(ZSTREAM_LOCAL_FILES)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)
|
||||
|
||||
CLEAN += paramgrill
|
||||
paramgrill : DEBUGFLAGS = # turn off debug for speed measurements
|
||||
paramgrill : LDLIBS += -lm
|
||||
paramgrill : $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.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 $(PRGDIR)/lorem.c paramgrill.c
|
||||
|
||||
CLEAN += datagen
|
||||
datagen : $(PRGDIR)/datagen.c datagencli.c
|
||||
datagen : $(PRGDIR)/datagen.c $(PRGDIR)/lorem.c loremOut.c datagencli.c
|
||||
$(LINK.c) $^ -o $@$(EXT)
|
||||
|
||||
CLEAN += roundTripCrash
|
||||
@@ -224,15 +232,15 @@ CLEAN += invalidDictionaries
|
||||
invalidDictionaries : $(ZSTD_OBJECTS) invalidDictionaries.c
|
||||
|
||||
CLEAN += legacy
|
||||
legacy : CPPFLAGS += -I$(ZSTDDIR)/legacy -UZSTD_LEGACY_SUPPORT -DZSTD_LEGACY_SUPPORT=4
|
||||
legacy : $(ZSTD_FILES) $(sort $(wildcard $(ZSTDDIR)/legacy/*.c)) legacy.c
|
||||
legacy : CPPFLAGS += -UZSTD_LEGACY_SUPPORT -DZSTD_LEGACY_SUPPORT=4
|
||||
legacy : $(ZSTD_FILES) legacy.c
|
||||
|
||||
CLEAN += decodecorpus
|
||||
decodecorpus : LDLIBS += -lm
|
||||
decodecorpus : $(filter-out zstdc_zstd_compress.o, $(ZSTD_OBJECTS)) $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c decodecorpus.c
|
||||
|
||||
CLEAN += poolTests
|
||||
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
|
||||
poolTests : $(PRGDIR)/util.c $(PRGDIR)/timefn.c poolTests.c $(LIB_SRCDIR)/common/pool.c $(LIB_SRCDIR)/common/threading.c $(LIB_SRCDIR)/common/zstd_common.c $(LIB_SRCDIR)/common/error_private.c
|
||||
$(LINK.c) $(MULTITHREAD) $^ -o $@$(EXT)
|
||||
|
||||
.PHONY: versionsTest
|
||||
@@ -245,14 +253,15 @@ automated_benchmarking: clean
|
||||
|
||||
# make checkTag : check that release tag corresponds to release version
|
||||
CLEAN += checkTag
|
||||
checkTag.o : $(ZSTDDIR)/zstd.h
|
||||
checkTag.o : $(LIB_SRCDIR)/zstd.h
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(MAKE) -C $(ZSTDDIR) clean
|
||||
$(MAKE) -C $(LIB_SRCDIR) clean
|
||||
$(MAKE) -C $(PRGDIR) clean
|
||||
$(RM) -fR $(TESTARTEFACT)
|
||||
$(RM) -rf tmp* # some test directories are named tmp*
|
||||
$(MAKE) -C fuzz clean
|
||||
$(RM) -R $(TESTARTEFACT)
|
||||
$(RM) -r tmp* # some test directories are named tmp*
|
||||
$(RM) $(CLEAN) core *.o *.tmp result* *.gcda dictionary *.zst \
|
||||
$(PRGDIR)/zstd$(EXT) $(PRGDIR)/zstd32$(EXT) \
|
||||
fullbench-dll$(EXT) fuzzer-dll$(EXT) zstreamtest-dll$(EXT)
|
||||
@@ -313,7 +322,7 @@ check: shortest
|
||||
fuzztest: test-fuzzer test-zstream test-decodecorpus
|
||||
|
||||
.PHONY: test
|
||||
test: test-zstd test-fullbench test-fuzzer test-zstream test-invalidDictionaries test-legacy test-decodecorpus test-cli-tests
|
||||
test: test-zstd test-cli-tests test-fullbench test-fuzzer test-zstream test-invalidDictionaries test-legacy test-decodecorpus
|
||||
ifeq ($(QEMU_SYS),)
|
||||
test: test-pool
|
||||
endif
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
println "+ zstd --blah" >&2
|
||||
zstd --blah
|
||||
println "+ zstd -xz" >&2
|
||||
zstd -xz
|
||||
println "+ zstd --adapt=min=1,maxx=2 file.txt" >&2
|
||||
zstd --adapt=min=1,maxx=2 file.txt
|
||||
println "+ zstd --train-cover=k=48,d=8,steps32 file.txt" >&2
|
||||
zstd --train-cover=k=48,d=8,steps32 file.txt
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,28 @@
|
||||
+ zstd --blah
|
||||
Incorrect parameter: --blah
|
||||
...
|
||||
Usage: zstd *
|
||||
|
||||
Options:
|
||||
...
|
||||
+ zstd -xz
|
||||
Incorrect parameter: -x
|
||||
...
|
||||
Usage: zstd *
|
||||
|
||||
Options:
|
||||
...
|
||||
+ zstd --adapt=min=1,maxx=2 file.txt
|
||||
Incorrect parameter: --adapt=min=1,maxx=2
|
||||
...
|
||||
Usage: zstd *
|
||||
|
||||
Options:
|
||||
...
|
||||
+ zstd --train-cover=k=48,d=8,steps32 file.txt
|
||||
Incorrect parameter: --train-cover=k=48,d=8,steps32
|
||||
...
|
||||
Usage: zstd *
|
||||
|
||||
Options:
|
||||
...
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# setup
|
||||
mkdir -p src/.hidden src/dir
|
||||
mkdir mid dst
|
||||
|
||||
echo "file1" > src/file1
|
||||
echo "file2" > src/.file2
|
||||
echo "file3" > src/.hidden/.file3
|
||||
echo "file4" > src/dir/.file4
|
||||
|
||||
# relative paths
|
||||
zstd -q -r --output-dir-mirror mid/ src/
|
||||
zstd -q -d -r --output-dir-mirror dst/ mid/src/
|
||||
|
||||
diff --brief --recursive --new-file src/ dst/mid/src/
|
||||
|
||||
# reset
|
||||
rm -rf mid dst
|
||||
mkdir mid dst
|
||||
|
||||
# from inside the directory
|
||||
(cd src; zstd -q -r --output-dir-mirror ../mid/ ./)
|
||||
(cd mid; zstd -q -d -r --output-dir-mirror ../dst/ ./)
|
||||
|
||||
diff --brief --recursive --new-file src/ dst/
|
||||
|
||||
# reset
|
||||
rm -rf mid dst
|
||||
mkdir mid dst
|
||||
|
||||
# absolute paths
|
||||
export BASE_PATH="$(pwd)"
|
||||
|
||||
zstd -q -r --output-dir-mirror mid/ "${BASE_PATH}/src/"
|
||||
zstd -q -d -r --output-dir-mirror dst/ "${BASE_PATH}/mid/${BASE_PATH}/src/"
|
||||
|
||||
diff --brief --recursive --new-file src/ "dst/${BASE_PATH}/mid/${BASE_PATH}/src/"
|
||||
|
||||
# reset
|
||||
rm -rf mid dst
|
||||
mkdir mid dst
|
||||
|
||||
# dots
|
||||
zstd -q -r --output-dir-mirror mid/ ./src/./
|
||||
zstd -q -d -r --output-dir-mirror dst/ ./mid/./src/./
|
||||
|
||||
diff --brief --recursive --new-file src/ dst/mid/src/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user