Compare commits
270
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88e9a984af | ||
|
|
5f2c3d9720 | ||
|
|
c7b03c217c | ||
|
|
0677b26b6d | ||
|
|
844c53ed75 | ||
|
|
4d8a2132d0 | ||
|
|
4bd96a61f1 | ||
|
|
fc946d131b | ||
|
|
26d88c05f0 | ||
|
|
1778222446 | ||
|
|
8dd943e42c | ||
|
|
7e679511a8 | ||
|
|
ff5d1daf33 | ||
|
|
ef1f9e80ff | ||
|
|
b12edddb37 | ||
|
|
4620ce6a9a | ||
|
|
c592b463ca | ||
|
|
3c2c3fbe4a | ||
|
|
c4f5116e95 | ||
|
|
6c50042355 | ||
|
|
35208f702f | ||
|
|
41ad7332dd | ||
|
|
a0b9520e38 | ||
|
|
213dc6110f | ||
|
|
8c53e526db | ||
|
|
6211bfee5e | ||
|
|
b1978d60ee | ||
|
|
9a9d1ec6f4 | ||
|
|
fb14e2288e | ||
|
|
ad7c9fc11e | ||
|
|
8da414231d | ||
|
|
4f63cb9755 | ||
|
|
0e83d1523b | ||
|
|
de9f52e945 | ||
|
|
a34ccad9a6 | ||
|
|
92a08eec72 | ||
|
|
e909fa627f | ||
|
|
681c81f06c | ||
|
|
6fa640ef70 | ||
|
|
321583ccf5 | ||
|
|
b7630a474b | ||
|
|
435f5a2e6d | ||
|
|
7ee35bad6b | ||
|
|
2068889146 | ||
|
|
1aed962216 | ||
|
|
bec7bbb5a4 | ||
|
|
aeff128331 | ||
|
|
75525fcb9f | ||
|
|
e145b58cfd | ||
|
|
b77fcac61f | ||
|
|
29e44bc554 | ||
|
|
eebf24bd2a | ||
|
|
14a0eaf73b | ||
|
|
41153071a0 | ||
|
|
abc694f53e | ||
|
|
1219b7f3e3 | ||
|
|
24960134d9 | ||
|
|
a9e43b37d0 | ||
|
|
85bd1e663b | ||
|
|
2624652a32 | ||
|
|
80a28f2078 | ||
|
|
9fc7f38e12 | ||
|
|
01adddc3e0 | ||
|
|
7c7b9244d6 | ||
|
|
47466d2192 | ||
|
|
9a32492730 | ||
|
|
925649b2d0 | ||
|
|
f829c32258 | ||
|
|
5c96146db3 | ||
|
|
5c63096269 | ||
|
|
8a724f91cb | ||
|
|
7a347769dc | ||
|
|
db1b408a2f | ||
|
|
c8d6067615 | ||
|
|
c5f1e826ca | ||
|
|
622fee6140 | ||
|
|
eaf786242d | ||
|
|
d5933a4009 | ||
|
|
2fbb1d10c1 | ||
|
|
99923dfc1a | ||
|
|
64205b7832 | ||
|
|
71c0c07c19 | ||
|
|
5e2fede604 | ||
|
|
05430b25a8 | ||
|
|
450fca9704 | ||
|
|
82a49c88f9 | ||
|
|
3e2a70b6fb | ||
|
|
6ca5f42402 | ||
|
|
b8434cb754 | ||
|
|
65404fe14a | ||
|
|
c69d13eb99 | ||
|
|
e0f9dc0dde | ||
|
|
252ef866fb | ||
|
|
e1ab2200ff | ||
|
|
c94cda283c | ||
|
|
ace6a7e746 | ||
|
|
22501cd283 | ||
|
|
4cc5e2818a | ||
|
|
c077b530a0 | ||
|
|
0c26d98c0d | ||
|
|
3d738307b4 | ||
|
|
57383d2317 | ||
|
|
3ce265fea8 | ||
|
|
8b40095b3f | ||
|
|
16241b7d26 | ||
|
|
9985e10fda | ||
|
|
a9cd6164d7 | ||
|
|
27e706de88 | ||
|
|
b94407b6cf | ||
|
|
859e0500ab | ||
|
|
33562c55de | ||
|
|
aa7729c9f3 | ||
|
|
fb3522a3fe | ||
|
|
9f1dee8fa5 | ||
|
|
1c7d2c4dd5 | ||
|
|
38dfc4699e | ||
|
|
9118ee04c2 | ||
|
|
b6b4c9a3da | ||
|
|
e7b0ae385e | ||
|
|
3d773d7013 | ||
|
|
ba7e8f1051 | ||
|
|
486472c453 | ||
|
|
d2c86ec898 | ||
|
|
fd6c34f641 | ||
|
|
c284569457 | ||
|
|
647c1b6615 | ||
|
|
014bbb29f8 | ||
|
|
a74a36985a | ||
|
|
1bf3d8a475 | ||
|
|
4a82bc9d00 | ||
|
|
e5bfaeede7 | ||
|
|
e688317652 | ||
|
|
01ecd6ffc0 | ||
|
|
d82d67d073 | ||
|
|
30b9db8ae4 | ||
|
|
1d025d871b | ||
|
|
a3ee9815c7 | ||
|
|
80a13fd645 | ||
|
|
21e28f5c24 | ||
|
|
a134737ad4 | ||
|
|
550410d05d | ||
|
|
ffbdc8ac57 | ||
|
|
b2fbd0a533 | ||
|
|
1e514feec6 | ||
|
|
39dced092e | ||
|
|
91f5891dd0 | ||
|
|
e89e847820 | ||
|
|
a71eed360b | ||
|
|
3f64b31585 | ||
|
|
c8767a4c74 | ||
|
|
9b97fdf74f | ||
|
|
49d578763d | ||
|
|
3133d1e86e | ||
|
|
8031dc7a48 | ||
|
|
e34e58b458 | ||
|
|
8f9f6442f5 | ||
|
|
906c3e9ccb | ||
|
|
c2260c1d45 | ||
|
|
d4713de5a3 | ||
|
|
a8adfa7f67 | ||
|
|
a7a469e095 | ||
|
|
360c2630e4 | ||
|
|
0356e05f07 | ||
|
|
5414dd7978 | ||
|
|
bf0a74663e | ||
|
|
7847c2fd68 | ||
|
|
ef2cba609d | ||
|
|
9bc94b2929 | ||
|
|
0907ab5f15 | ||
|
|
d7e1736375 | ||
|
|
7abebc847b | ||
|
|
20660a02e2 | ||
|
|
0a36c104ca | ||
|
|
944c71c07d | ||
|
|
e315a047c7 | ||
|
|
ebf664b744 | ||
|
|
7ce6f71c6f | ||
|
|
c2c6a4ab40 | ||
|
|
66079085f0 | ||
|
|
a37a8df532 | ||
|
|
f56de118a0 | ||
|
|
92c41c53ee | ||
|
|
e2d01863bc | ||
|
|
f343f27d17 | ||
|
|
b7d899d99d | ||
|
|
19eb459da3 | ||
|
|
8dba88c3f6 | ||
|
|
802ea885ef | ||
|
|
81b96205af | ||
|
|
27455638aa | ||
|
|
c67e07f34e | ||
|
|
ebbd675998 | ||
|
|
ddae153947 | ||
|
|
9b28c26cbf | ||
|
|
7fbd126e08 | ||
|
|
375e3aad6c | ||
|
|
365c91194c | ||
|
|
f6ffd39230 | ||
|
|
9ba07907c8 | ||
|
|
df9b7755cb | ||
|
|
63fe6198ed | ||
|
|
a071e00696 | ||
|
|
931778ed9b | ||
|
|
48572f52b1 | ||
|
|
61765cacd0 | ||
|
|
793b6cec73 | ||
|
|
d46995efeb | ||
|
|
379c62a7d4 | ||
|
|
0665d4c1c2 | ||
|
|
5375d75c55 | ||
|
|
b3888193d9 | ||
|
|
384744888e | ||
|
|
b10357ce65 | ||
|
|
b399b47467 | ||
|
|
04734ee84a | ||
|
|
23dd28df67 | ||
|
|
aba88fa996 | ||
|
|
2b2a5c449a | ||
|
|
518f06b281 | ||
|
|
12e177cba8 | ||
|
|
ad739e5959 | ||
|
|
082d6c6775 | ||
|
|
02be2a830f | ||
|
|
6a7ede3dfc | ||
|
|
0a794f5afe | ||
|
|
13cad3abb1 | ||
|
|
dad8a3cf34 | ||
|
|
abd717a5fa | ||
|
|
9d62957b31 | ||
|
|
1c2b02eee9 | ||
|
|
23c1a2d260 | ||
|
|
0bfc935add | ||
|
|
66e554fdad | ||
|
|
926d47004d | ||
|
|
b77d95b053 | ||
|
|
26486db9ab | ||
|
|
802745e88a | ||
|
|
9c9a5f3ff3 | ||
|
|
c6c482fe07 | ||
|
|
31316cf158 | ||
|
|
1bbb372e3e | ||
|
|
399644b1f1 | ||
|
|
79ca830766 | ||
|
|
168d0a3c89 | ||
|
|
c2c32839dc | ||
|
|
62536ef7da | ||
|
|
051b473e7e | ||
|
|
fcab4841aa | ||
|
|
47fd762ecc | ||
|
|
2cdfad538c | ||
|
|
6ae44c0db8 | ||
|
|
2ddef7c872 | ||
|
|
39f2491bfc | ||
|
|
db4e1b5479 | ||
|
|
a1ac7205d0 | ||
|
|
072ffaad67 | ||
|
|
1bdf041071 | ||
|
|
258c0623e1 | ||
|
|
52598d54e9 | ||
|
|
7868f38019 | ||
|
|
894f05e88d | ||
|
|
ae986fcdb8 | ||
|
|
e5ba858270 | ||
|
|
95f492ea17 | ||
|
|
cc22042da0 | ||
|
|
6ef6cd7999 | ||
|
|
399849e236 | ||
|
|
4d09952701 | ||
|
|
fa2a6d4746 | ||
|
|
e81d567547 |
@@ -15,12 +15,13 @@ jobs:
|
||||
name: Test
|
||||
command: |
|
||||
./tests/test-license.py
|
||||
cc -v; CFLAGS="-O0 -Werror -pedantic" make all && make clean
|
||||
make c99build && make clean
|
||||
make c11build && make clean
|
||||
make -j regressiontest&& make clean
|
||||
make shortest && make clean
|
||||
make cxxtest && make clean
|
||||
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
|
||||
# the second half of the jobs are in this test
|
||||
short-tests-1:
|
||||
docker:
|
||||
|
||||
@@ -10,6 +10,13 @@ on:
|
||||
branches: [ dev, release, actionsTest ]
|
||||
|
||||
jobs:
|
||||
make-all:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make all
|
||||
run: make all
|
||||
|
||||
# lasts ~24mn
|
||||
make-test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -150,6 +157,59 @@ jobs:
|
||||
make clean
|
||||
make -C tests test-fuzzer-stackmode
|
||||
|
||||
mingw-long-test:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: [
|
||||
{ compiler: clang, platform: x64, action: build, script: "MOREFLAGS='--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion -Wno-unused-command-line-argument -Wno-implicit-int-float-conversion' make -j allzstd V=1"},
|
||||
{ compiler: gcc, platform: x64, action: test, script: ""},
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Mingw long test
|
||||
run: |
|
||||
$env:PATH_ORIGINAL = $env:PATH
|
||||
$env:PATH_MINGW32 = "C:\msys64\mingw32\bin"
|
||||
$env:PATH_MINGW64 = "C:\msys64\mingw64\bin"
|
||||
COPY C:\msys64\usr\bin\make.exe C:\msys64\mingw32\bin\make.exe
|
||||
COPY C:\msys64\usr\bin\make.exe C:\msys64\mingw64\bin\make.exe
|
||||
IF ("${{matrix.platform}}" -eq "x64")
|
||||
{
|
||||
$env:PATH = $env:PATH_MINGW64 + ";" + $env:PATH_ORIGINAL
|
||||
}
|
||||
ELSEIF ("${{matrix.platform}}" -eq "x86")
|
||||
{
|
||||
$env:PATH = $env:PATH_MINGW32 + ";" + $env:PATH_ORIGINAL
|
||||
}
|
||||
IF ("${{matrix.action}}" -eq "build")
|
||||
{
|
||||
make -v
|
||||
sh -c "${{matrix.compiler}} -v"
|
||||
ECHO "Building zlib to static link"
|
||||
$env:CC = "${{matrix.compiler}}"
|
||||
sh -c "cd .. && git clone --depth 1 --branch v1.2.11 https://github.com/madler/zlib"
|
||||
sh -c "cd ../zlib && make -f win32/Makefile.gcc libz.a"
|
||||
ECHO "Building zstd"
|
||||
$env:CPPFLAGS = "-I../../zlib"
|
||||
$env:LDFLAGS = "../../zlib/libz.a"
|
||||
sh -c "${{matrix.script}}"
|
||||
}
|
||||
ELSEIF ("${{matrix.action}}" -eq "test")
|
||||
{
|
||||
ECHO "Testing ${{matrix.compiler}} ${{matrix.platform}}"
|
||||
$env:CC = "gcc"
|
||||
$env:CXX = "g++"
|
||||
MKDIR build\cmake\build
|
||||
CD build\cmake\build
|
||||
$env:FUZZERTEST = "-T2mn"
|
||||
$env:ZSTREAM_TESTTIME = "-T2mn"
|
||||
cmake -G "Visual Studio 14 2015 Win64" ..
|
||||
cd ..\..\..
|
||||
make clean
|
||||
}
|
||||
|
||||
# lasts ~20mn
|
||||
oss-fuzz:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -35,6 +35,18 @@ jobs:
|
||||
APT_PACKAGES="gcc-multilib" make apt-install
|
||||
CFLAGS="-m32 -O1 -fstack-protector" make check V=1
|
||||
|
||||
check-x32:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make check on x32 ABI # https://en.wikipedia.org/wiki/X32_ABI
|
||||
env:
|
||||
CHECK_CONSTRAINED_MEM: true
|
||||
run: |
|
||||
sudo apt update
|
||||
APT_PACKAGES="gcc-multilib" make apt-install
|
||||
CFLAGS="-mx32 -O1 -fstack-protector" make check V=1
|
||||
|
||||
gcc-7-libzstd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -117,11 +129,11 @@ jobs:
|
||||
make -C zlibWrapper test
|
||||
make -C zlibWrapper valgrindTest
|
||||
|
||||
lz4-threadpool-partial-libs:
|
||||
lz4-threadpool-libs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: LZ4, thread pool, and partial libs testslib wrapper test
|
||||
- name: LZ4, thread pool, and libs build testslib wrapper test
|
||||
run: |
|
||||
make lz4install
|
||||
make -C tests test-lz4
|
||||
@@ -129,7 +141,7 @@ jobs:
|
||||
make clean
|
||||
make -C tests test-pool
|
||||
make clean
|
||||
bash tests/libzstd_partial_builds.sh
|
||||
bash tests/libzstd_builds.sh
|
||||
|
||||
gcc-make-tests-32bit:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -162,6 +174,28 @@ jobs:
|
||||
make clean
|
||||
CC=clang MOREFLAGS="-Werror -Wimplicit-fallthrough -O0" make -C lib -j libzstd.a ZSTD_LEGACY_SUPPORT=0
|
||||
|
||||
cmake-visual-2019:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- generator: "Visual Studio 16 2019"
|
||||
flags: "-A x64"
|
||||
- generator: "Visual Studio 16 2019"
|
||||
flags: "-A Win32"
|
||||
- generator: "MinGW Makefiles"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
- name: Build
|
||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
||||
run: |
|
||||
cd build\cmake
|
||||
mkdir build
|
||||
cd build
|
||||
cmake.exe -G "${{matrix.generator}}" ${{matrix.flags}} ..
|
||||
cmake.exe --build .
|
||||
|
||||
visual-2019:
|
||||
runs-on: windows-latest
|
||||
@@ -292,14 +326,74 @@ jobs:
|
||||
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check
|
||||
- name: M68K
|
||||
if: ${{ matrix.name == 'M68K' }}
|
||||
continue-on-error: true # disable reporting errors (alignment issues)
|
||||
run: |
|
||||
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check
|
||||
|
||||
mingw-short-test:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: [
|
||||
{ compiler: gcc, platform: x64, script: "CFLAGS=-Werror make -j allzstd DEBUGLEVEL=2"},
|
||||
{ compiler: gcc, platform: x86, script: "CFLAGS=-Werror make -j allzstd"},
|
||||
{ compiler: clang, platform: x64, script: "CFLAGS='--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion' make -j allzstd V=1"},
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Mingw short test
|
||||
run: |
|
||||
ECHO "Building ${{matrix.compiler}} ${{matrix.platform}}"
|
||||
$env:PATH_ORIGINAL = $env:PATH
|
||||
$env:PATH_MINGW32 = "C:\msys64\mingw32\bin"
|
||||
$env:PATH_MINGW64 = "C:\msys64\mingw64\bin"
|
||||
COPY C:\msys64\usr\bin\make.exe C:\msys64\mingw32\bin\make.exe
|
||||
COPY C:\msys64\usr\bin\make.exe C:\msys64\mingw64\bin\make.exe
|
||||
IF ("${{matrix.platform}}" -eq "x64")
|
||||
{
|
||||
$env:PATH = $env:PATH_MINGW64 + ";" + $env:PATH_ORIGINAL
|
||||
}
|
||||
ELSEIF ("${{matrix.platform}}" -eq "x86")
|
||||
{
|
||||
$env:PATH = $env:PATH_MINGW32 + ";" + $env:PATH_ORIGINAL
|
||||
}
|
||||
make -v
|
||||
sh -c "${{matrix.compiler}} -v"
|
||||
$env:CC = "${{matrix.compiler}}"
|
||||
sh -c "${{matrix.script}}"
|
||||
ECHO "Testing ${{matrix.compiler}} ${{matrix.platform}}"
|
||||
make clean
|
||||
make check
|
||||
|
||||
|
||||
visual-runtime-tests:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [x64, Win32]
|
||||
configuration: [Release]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
- name: Build and run tests
|
||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
||||
env:
|
||||
ZSTD_BIN: ./zstd.exe
|
||||
DATAGEN_BIN: ./datagen.exe
|
||||
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
|
||||
run: |
|
||||
msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v142 /t:Clean,Build /p:Platform=${{matrix.platform}} /p:Configuration=${{matrix.configuration}}
|
||||
COPY build\VS2010\bin\${{matrix.platform}}_${{matrix.configuration}}\*.exe tests\
|
||||
CD tests
|
||||
sh -e playTests.sh
|
||||
DIR
|
||||
.\fuzzer.exe -T2m
|
||||
|
||||
# This test currently fails on Github Actions specifically.
|
||||
# Possible reason : TTY emulation.
|
||||
# Note that the same test works fine locally and on travisCI.
|
||||
# This will have to be fixed before transfering the test to GA.
|
||||
# This will have to be fixed before transferring the test to GA.
|
||||
# versions-compatibility:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
v1.5.1 (Dec, 2021)
|
||||
perf: rebalanced compression levels, to better match the intended speed/level curve, by @senhuang42
|
||||
perf: faster huffman decoder, using x64 assembly, by @terrelln
|
||||
perf: slightly faster high speed modes (strategies fast & dfast), by @felixhandte
|
||||
perf: improved binary size and faster compilation times, by @terrelln
|
||||
perf: new row64 mode, used notably in level 12, by @senhuang42
|
||||
perf: faster mid-level compression speed in presence of highly repetitive patterns, by @senhuang42
|
||||
perf: minor compression ratio improvements for small data at high levels, by @cyan4973
|
||||
perf: reduced stack usage (mostly useful for Linux Kernel), by @terrelln
|
||||
perf: faster compression speed on incompressible data, by @bindhvo
|
||||
perf: on-demand reduced ZSTD_DCtx state size, using build macro ZSTD_DECODER_INTERNAL_BUFFER, at a small cost of performance, by @bindhvo
|
||||
build: allows hiding static symbols in the dynamic library, using build macro, by @skitt
|
||||
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
|
||||
|
||||
v1.5.0 (May 11, 2021)
|
||||
api: Various functions promoted from experimental to stable API: (#2579-2581, @senhuang42)
|
||||
`ZSTD_defaultCLevel()`
|
||||
|
||||
+12
-12
@@ -47,7 +47,7 @@ Our contribution process works in three main stages:
|
||||
* Topic and development:
|
||||
* Make a new branch on your fork about the topic you're developing for
|
||||
```
|
||||
# branch names should be consise but sufficiently informative
|
||||
# branch names should be concise but sufficiently informative
|
||||
git checkout -b <branch-name>
|
||||
git push origin <branch-name>
|
||||
```
|
||||
@@ -104,7 +104,7 @@ Our contribution process works in three main stages:
|
||||
issue at hand, then please indicate this by requesting that an issue be closed by commenting.
|
||||
* Just because your changes have been merged does not mean the topic or larger issue is complete. Remember
|
||||
that the change must make it to an official zstd release for it to be meaningful. We recommend
|
||||
that contributers track the activity on their pull request and corresponding issue(s) page(s) until
|
||||
that contributors track the activity on their pull request and corresponding issue(s) page(s) until
|
||||
their change makes it to the next release of zstd. Users will often discover bugs in your code or
|
||||
suggest ways to refine and improve your initial changes even after the pull request is merged.
|
||||
|
||||
@@ -270,15 +270,15 @@ for level 1 compression on Zstd. Typically this means, you have identified a sec
|
||||
code that you think can be made to run faster.
|
||||
|
||||
The first thing you will want to do is make sure that the piece of code is actually taking up
|
||||
a notable amount of time to run. It is usually not worth optimzing something which accounts for less than
|
||||
a notable amount of time to run. It is usually not worth optimizing something which accounts for less than
|
||||
0.0001% of the total running time. Luckily, there are tools to help with this.
|
||||
Profilers will let you see how much time your code spends inside a particular function.
|
||||
If your target code snippit is only part of a function, it might be worth trying to
|
||||
isolate that snippit by moving it to its own function (this is usually not necessary but
|
||||
If your target code snippet is only part of a function, it might be worth trying to
|
||||
isolate that snippet by moving it to its own function (this is usually not necessary but
|
||||
might be).
|
||||
|
||||
Most profilers (including the profilers dicusssed below) will generate a call graph of
|
||||
functions for you. Your goal will be to find your function of interest in this call grapch
|
||||
Most profilers (including the profilers discussed below) will generate a call graph of
|
||||
functions for you. Your goal will be to find your function of interest in this call graph
|
||||
and then inspect the time spent inside of it. You might also want to to look at the
|
||||
annotated assembly which most profilers will provide you with.
|
||||
|
||||
@@ -301,16 +301,16 @@ $ zstd -b1 -i5 <my-data> # this will run for 5 seconds
|
||||
5. Once you run your benchmarking script, switch back over to instruments and attach your
|
||||
process to the time profiler. You can do this by:
|
||||
* Clicking on the `All Processes` drop down in the top left of the toolbar.
|
||||
* Selecting your process from the dropdown. In my case, it is just going to be labled
|
||||
* Selecting your process from the dropdown. In my case, it is just going to be labeled
|
||||
`zstd`
|
||||
* Hitting the bright red record circle button on the top left of the toolbar
|
||||
6. You profiler will now start collecting metrics from your bencharking script. Once
|
||||
6. You profiler will now start collecting metrics from your benchmarking script. Once
|
||||
you think you have collected enough samples (usually this is the case after 3 seconds of
|
||||
recording), stop your profiler.
|
||||
7. Make sure that in toolbar of the bottom window, `profile` is selected.
|
||||
8. You should be able to see your call graph.
|
||||
* If you don't see the call graph or an incomplete call graph, make sure you have compiled
|
||||
zstd and your benchmarking scripg using debug flags. On mac and linux, this just means
|
||||
zstd and your benchmarking script using debug flags. On mac and linux, this just means
|
||||
you will have to supply the `-g` flag alone with your build script. You might also
|
||||
have to provide the `-fno-omit-frame-pointer` flag
|
||||
9. Dig down the graph to find your function call and then inspect it by double clicking
|
||||
@@ -329,7 +329,7 @@ Some general notes on perf:
|
||||
counter statistics. Perf uses a high resolution timer and this is likely one
|
||||
of the first things your team will run when assessing your PR.
|
||||
* Perf has a long list of hardware counters that can be viewed with `perf --list`.
|
||||
When measuring optimizations, something worth trying is to make sure the handware
|
||||
When measuring optimizations, something worth trying is to make sure the hardware
|
||||
counters you expect to be impacted by your change are in fact being so. For example,
|
||||
if you expect the L1 cache misses to decrease with your change, you can look at the
|
||||
counter `L1-dcache-load-misses`
|
||||
@@ -368,7 +368,7 @@ Follow these steps to link travis-ci with your github fork of zstd
|
||||
TODO
|
||||
|
||||
### appveyor
|
||||
Follow these steps to link circle-ci with your girhub fork of zstd
|
||||
Follow these steps to link circle-ci with your github fork of zstd
|
||||
|
||||
1. Make sure you are logged into your github account
|
||||
2. Go to https://www.appveyor.com/
|
||||
|
||||
@@ -29,6 +29,7 @@ VOID = /dev/null
|
||||
# fail on other tested distros (ubuntu, debian) even
|
||||
# without manually specifying the TARGET_SYSTEM.
|
||||
TARGET_SYSTEM ?= $(OS)
|
||||
CP ?= cp
|
||||
|
||||
ifneq (,$(filter Windows%,$(TARGET_SYSTEM)))
|
||||
EXT =.exe
|
||||
@@ -69,7 +70,7 @@ zstd zstd-release:
|
||||
.PHONY: zstdmt
|
||||
zstdmt:
|
||||
$(Q)$(MAKE) -C $(PRGDIR) $@
|
||||
$(Q)cp $(PRGDIR)/zstd$(EXT) ./zstdmt$(EXT)
|
||||
$(Q)$(CP) $(PRGDIR)/zstd$(EXT) ./zstdmt$(EXT)
|
||||
|
||||
.PHONY: zlibwrapper
|
||||
zlibwrapper: lib
|
||||
@@ -148,10 +149,12 @@ clean:
|
||||
#------------------------------------------------------------------------------
|
||||
# make install is validated only for Linux, macOS, Hurd and some BSD targets
|
||||
#------------------------------------------------------------------------------
|
||||
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD DragonFly NetBSD MSYS_NT Haiku))
|
||||
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD DragonFly NetBSD MSYS_NT Haiku AIX))
|
||||
|
||||
HOST_OS = POSIX
|
||||
|
||||
MKDIR ?= mkdir -p
|
||||
|
||||
HAVE_COLORNEVER = $(shell echo a | egrep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0)
|
||||
EGREP_OPTIONS ?=
|
||||
ifeq ($HAVE_COLORNEVER, 1)
|
||||
@@ -284,6 +287,22 @@ uasanregressiontest:
|
||||
msanregressiontest:
|
||||
$(MAKE) -C $(FUZZDIR) regressiontest CC=clang CXX=clang++ CFLAGS="-O3 -fsanitize=memory" CXXFLAGS="-O3 -fsanitize=memory"
|
||||
|
||||
update_regressionResults : REGRESS_RESULTS_DIR := /tmp/regress_results_dir/
|
||||
update_regressionResults:
|
||||
$(MAKE) -C programs zstd
|
||||
$(MAKE) -C tests/regression test
|
||||
$(RM) -rf $(REGRESS_RESULTS_DIR)
|
||||
$(MKDIR) $(REGRESS_RESULTS_DIR)
|
||||
./tests/regression/test \
|
||||
--cache tests/regression/cache \
|
||||
--output $(REGRESS_RESULTS_DIR)/results.csv \
|
||||
--zstd programs/zstd
|
||||
echo "Showing results differences"
|
||||
! diff tests/regression/results.csv $(REGRESS_RESULTS_DIR)/results.csv
|
||||
echo "Updating results.csv"
|
||||
$(CP) $(REGRESS_RESULTS_DIR)/results.csv tests/regression/results.csv
|
||||
|
||||
|
||||
# run UBsan with -fsanitize-recover=pointer-overflow
|
||||
# this only works with recent compilers such as gcc 8+
|
||||
usan: clean
|
||||
@@ -372,7 +391,7 @@ ifneq (,$(filter $(HOST_OS),MSYS POSIX))
|
||||
cmakebuild:
|
||||
cmake --version
|
||||
$(RM) -r $(BUILDIR)/cmake/build
|
||||
mkdir $(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;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// swift-tools-version:5.0
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "zstd",
|
||||
platforms: [
|
||||
.macOS(.v10_10), .iOS(.v9), .tvOS(.v9)
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||
.library(
|
||||
name: "libzstd",
|
||||
targets: [ "libzstd" ])
|
||||
],
|
||||
dependencies: [
|
||||
// Dependencies declare other packages that this package depends on.
|
||||
// .package(url: /* package url */, from: "1.0.0"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||
.target(
|
||||
name: "libzstd",
|
||||
path: "lib",
|
||||
sources: [ "common", "compress", "decompress", "dictBuilder" ],
|
||||
publicHeadersPath: ".",
|
||||
cSettings: [
|
||||
.headerSearchPath(".")
|
||||
])
|
||||
],
|
||||
swiftLanguageVersions: [.v5],
|
||||
cLanguageStandard: .gnu11,
|
||||
cxxLanguageStandard: .gnucxx14
|
||||
)
|
||||
@@ -32,8 +32,8 @@ a list of known ports and bindings is provided on [Zstandard homepage](http://ww
|
||||
## Benchmarks
|
||||
|
||||
For reference, several fast compression algorithms were tested and compared
|
||||
on a server running Arch Linux (`Linux version 5.5.11-arch1-1`),
|
||||
with a Core i9-9900K CPU @ 5.0GHz,
|
||||
on a desktop running Ubuntu 20.04 (`Linux 5.11.0-41-generic`),
|
||||
with a Core i7-9700K CPU @ 4.9GHz,
|
||||
using [lzbench], an open-source in-memory benchmark by @inikep
|
||||
compiled with [gcc] 9.3.0,
|
||||
on the [Silesia compression corpus].
|
||||
@@ -44,25 +44,24 @@ on the [Silesia compression corpus].
|
||||
|
||||
| Compressor name | Ratio | Compression| Decompress.|
|
||||
| --------------- | ------| -----------| ---------- |
|
||||
| **zstd 1.4.5 -1** | 2.884 | 500 MB/s | 1660 MB/s |
|
||||
| zlib 1.2.11 -1 | 2.743 | 90 MB/s | 400 MB/s |
|
||||
| brotli 1.0.7 -0 | 2.703 | 400 MB/s | 450 MB/s |
|
||||
| **zstd 1.4.5 --fast=1** | 2.434 | 570 MB/s | 2200 MB/s |
|
||||
| **zstd 1.4.5 --fast=3** | 2.312 | 640 MB/s | 2300 MB/s |
|
||||
| quicklz 1.5.0 -1 | 2.238 | 560 MB/s | 710 MB/s |
|
||||
| **zstd 1.4.5 --fast=5** | 2.178 | 700 MB/s | 2420 MB/s |
|
||||
| lzo1x 2.10 -1 | 2.106 | 690 MB/s | 820 MB/s |
|
||||
| lz4 1.9.2 | 2.101 | 740 MB/s | 4530 MB/s |
|
||||
| **zstd 1.4.5 --fast=7** | 2.096 | 750 MB/s | 2480 MB/s |
|
||||
| lzf 3.6 -1 | 2.077 | 410 MB/s | 860 MB/s |
|
||||
| snappy 1.1.8 | 2.073 | 560 MB/s | 1790 MB/s |
|
||||
| **zstd 1.5.1 -1** | 2.887 | 530 MB/s | 1700 MB/s |
|
||||
| [zlib] 1.2.11 -1 | 2.743 | 95 MB/s | 400 MB/s |
|
||||
| brotli 1.0.9 -0 | 2.702 | 395 MB/s | 450 MB/s |
|
||||
| **zstd 1.5.1 --fast=1** | 2.437 | 600 MB/s | 2150 MB/s |
|
||||
| **zstd 1.5.1 --fast=3** | 2.239 | 670 MB/s | 2250 MB/s |
|
||||
| quicklz 1.5.0 -1 | 2.238 | 540 MB/s | 760 MB/s |
|
||||
| **zstd 1.5.1 --fast=4** | 2.148 | 710 MB/s | 2300 MB/s |
|
||||
| lzo1x 2.10 -1 | 2.106 | 660 MB/s | 845 MB/s |
|
||||
| [lz4] 1.9.3 | 2.101 | 740 MB/s | 4500 MB/s |
|
||||
| lzf 3.6 -1 | 2.077 | 410 MB/s | 830 MB/s |
|
||||
| snappy 1.1.9 | 2.073 | 550 MB/s | 1750 MB/s |
|
||||
|
||||
[zlib]: http://www.zlib.net/
|
||||
[LZ4]: http://www.lz4.org/
|
||||
[lz4]: http://www.lz4.org/
|
||||
|
||||
The negative compression levels, specified with `--fast=#`,
|
||||
offer faster compression and decompression speed in exchange for some loss in
|
||||
compression ratio compared to level 1, as seen in the table above.
|
||||
offer faster compression and decompression speed
|
||||
at the cost of compression ratio (compared to level 1).
|
||||
|
||||
Zstd can also offer stronger compression ratios at the cost of compression speed.
|
||||
Speed vs Compression trade-off is configurable by small increments.
|
||||
|
||||
+30
-109
@@ -23,34 +23,6 @@
|
||||
SCRIPT: "make allzstd MOREFLAGS=-static"
|
||||
ARTIFACT: "true"
|
||||
BUILD: "true"
|
||||
- COMPILER: "clang"
|
||||
HOST: "mingw"
|
||||
PLATFORM: "x64"
|
||||
SCRIPT: "MOREFLAGS='--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion' make -j allzstd V=1"
|
||||
BUILD: "true"
|
||||
|
||||
- COMPILER: "gcc"
|
||||
HOST: "mingw"
|
||||
PLATFORM: "x64"
|
||||
SCRIPT: ""
|
||||
TEST: "cmake"
|
||||
|
||||
- COMPILER: "visual"
|
||||
HOST: "visual"
|
||||
PLATFORM: "x64"
|
||||
CONFIGURATION: "Debug"
|
||||
- COMPILER: "visual"
|
||||
HOST: "visual"
|
||||
PLATFORM: "Win32"
|
||||
CONFIGURATION: "Debug"
|
||||
- COMPILER: "visual"
|
||||
HOST: "visual"
|
||||
PLATFORM: "x64"
|
||||
CONFIGURATION: "Release"
|
||||
- COMPILER: "visual"
|
||||
HOST: "visual"
|
||||
PLATFORM: "Win32"
|
||||
CONFIGURATION: "Release"
|
||||
|
||||
- COMPILER: "clang-cl"
|
||||
HOST: "cmake-visual"
|
||||
@@ -113,46 +85,6 @@
|
||||
appveyor PushArtifact zstd-win-release-%PLATFORM%.zip
|
||||
)
|
||||
)
|
||||
- if [%HOST%]==[visual] (
|
||||
ECHO *** &&
|
||||
ECHO *** Building Visual Studio 2008 %PLATFORM%\%CONFIGURATION% in %APPVEYOR_BUILD_FOLDER% &&
|
||||
ECHO *** &&
|
||||
msbuild "build\VS2008\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v90 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
|
||||
DIR build\VS2008\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
|
||||
MD5sum build/VS2008/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
|
||||
COPY build\VS2008\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2008_%PLATFORM%_%CONFIGURATION%.exe &&
|
||||
ECHO *** &&
|
||||
ECHO *** Building Visual Studio 2010 %PLATFORM%\%CONFIGURATION% &&
|
||||
ECHO *** &&
|
||||
msbuild "build\VS2010\zstd.sln" %ADDITIONALPARAM% /m /verbosity:minimal /property:PlatformToolset=v100 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\build\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
|
||||
DIR build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe &&
|
||||
MD5sum build/VS2010/bin/%PLATFORM%_%CONFIGURATION%/*.exe &&
|
||||
msbuild "build\VS2010\zstd.sln" %ADDITIONALPARAM% /m /verbosity:minimal /property:PlatformToolset=v100 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
|
||||
DIR build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe &&
|
||||
MD5sum build/VS2010/bin/%PLATFORM%_%CONFIGURATION%/*.exe &&
|
||||
COPY build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2010_%PLATFORM%_%CONFIGURATION%.exe &&
|
||||
ECHO *** &&
|
||||
ECHO *** Building Visual Studio 2012 %PLATFORM%\%CONFIGURATION% &&
|
||||
ECHO *** &&
|
||||
msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\build\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
|
||||
DIR build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe &&
|
||||
MD5sum build/VS2010/bin/%PLATFORM%_%CONFIGURATION%/*.exe &&
|
||||
msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
|
||||
DIR build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe &&
|
||||
MD5sum build/VS2010/bin/%PLATFORM%_%CONFIGURATION%/*.exe &&
|
||||
COPY build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2012_%PLATFORM%_%CONFIGURATION%.exe &&
|
||||
ECHO *** &&
|
||||
ECHO *** Building Visual Studio 2013 %PLATFORM%\%CONFIGURATION% &&
|
||||
ECHO *** &&
|
||||
msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v120 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\build\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
|
||||
DIR build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe &&
|
||||
MD5sum build/VS2010/bin/%PLATFORM%_%CONFIGURATION%/*.exe &&
|
||||
msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v120 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
|
||||
DIR build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe &&
|
||||
MD5sum build/VS2010/bin/%PLATFORM%_%CONFIGURATION%/*.exe &&
|
||||
COPY build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2013_%PLATFORM%_%CONFIGURATION%.exe &&
|
||||
COPY build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe tests\
|
||||
)
|
||||
- if [%HOST%]==[cmake-visual] (
|
||||
ECHO *** &&
|
||||
ECHO *** Building %CMAKE_GENERATOR% ^(%CMAKE_GENERATOR_TOOLSET%^) %PLATFORM%\%CONFIGURATION% &&
|
||||
@@ -176,18 +108,6 @@
|
||||
cd ..\..\.. &&
|
||||
make clean
|
||||
)
|
||||
- SET "FUZZERTEST=-T30s"
|
||||
- if [%HOST%]==[visual] if [%CONFIGURATION%]==[Release] (
|
||||
CD tests &&
|
||||
SET ZSTD_BIN=./zstd.exe&&
|
||||
SET DATAGEN_BIN=./datagen.exe&&
|
||||
sh -e playTests.sh --test-large-data &&
|
||||
fullbench.exe -i1 &&
|
||||
fullbench.exe -i1 -P0 &&
|
||||
fuzzer_VS2012_%PLATFORM%_Release.exe %FUZZERTEST% &&
|
||||
fuzzer_VS2013_%PLATFORM%_Release.exe %FUZZERTEST% &&
|
||||
fuzzer_VS2015_%PLATFORM%_Release.exe %FUZZERTEST%
|
||||
)
|
||||
|
||||
|
||||
# The following tests are for regular pushes
|
||||
@@ -198,21 +118,26 @@
|
||||
version: 1.0.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- COMPILER: "visual"
|
||||
HOST: "visual"
|
||||
PLATFORM: "x64"
|
||||
CONFIGURATION: "Debug"
|
||||
- COMPILER: "visual"
|
||||
HOST: "visual"
|
||||
PLATFORM: "Win32"
|
||||
CONFIGURATION: "Debug"
|
||||
- COMPILER: "visual"
|
||||
HOST: "visual"
|
||||
PLATFORM: "x64"
|
||||
CONFIGURATION: "Release"
|
||||
- COMPILER: "visual"
|
||||
HOST: "visual"
|
||||
PLATFORM: "Win32"
|
||||
CONFIGURATION: "Release"
|
||||
|
||||
- COMPILER: "gcc"
|
||||
HOST: "cygwin"
|
||||
PLATFORM: "x64"
|
||||
- COMPILER: "gcc"
|
||||
HOST: "mingw"
|
||||
PLATFORM: "x64"
|
||||
SCRIPT: "CFLAGS=-Werror make -j allzstd DEBUGLEVEL=2"
|
||||
- COMPILER: "gcc"
|
||||
HOST: "mingw"
|
||||
PLATFORM: "x86"
|
||||
SCRIPT: "CFLAGS=-Werror make -j allzstd"
|
||||
- COMPILER: "clang"
|
||||
HOST: "mingw"
|
||||
PLATFORM: "x64"
|
||||
SCRIPT: "CFLAGS='--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion' make -j allzstd V=1"
|
||||
|
||||
- COMPILER: "clang-cl"
|
||||
HOST: "cmake-visual"
|
||||
@@ -233,11 +158,8 @@
|
||||
cmake,^
|
||||
make
|
||||
)
|
||||
- if [%HOST%]==[mingw] (
|
||||
SET "PATH_MINGW32=C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin" &&
|
||||
SET "PATH_MINGW64=C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin" &&
|
||||
COPY C:\msys64\usr\bin\make.exe C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin\make.exe &&
|
||||
COPY C:\msys64\usr\bin\make.exe C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin\make.exe
|
||||
- IF [%HOST%]==[visual] IF [%PLATFORM%]==[x64] (
|
||||
SET ADDITIONALPARAM=/p:LibraryPath="C:\Program Files\Microsoft SDKs\Windows\v7.1\lib\x64;c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64;C:\Program Files (x86)\Microsoft Visual Studio 10.0\;C:\Program Files (x86)\Microsoft Visual Studio 10.0\lib\amd64;"
|
||||
)
|
||||
|
||||
build_script:
|
||||
@@ -253,17 +175,6 @@
|
||||
ctest -V -L Medium;
|
||||
"
|
||||
)
|
||||
- if [%HOST%]==[mingw] (
|
||||
( if [%PLATFORM%]==[x64] (
|
||||
SET "PATH=%PATH_MINGW64%;%PATH_ORIGINAL%"
|
||||
) else if [%PLATFORM%]==[x86] (
|
||||
SET "PATH=%PATH_MINGW32%;%PATH_ORIGINAL%"
|
||||
) ) &&
|
||||
make -v &&
|
||||
sh -c "%COMPILER% -v" &&
|
||||
set "CC=%COMPILER%" &&
|
||||
sh -c "%SCRIPT%"
|
||||
)
|
||||
- if [%HOST%]==[cmake-visual] (
|
||||
ECHO *** &&
|
||||
ECHO *** Building %CMAKE_GENERATOR% ^(%CMAKE_GENERATOR_TOOLSET%^) %PLATFORM%\%CONFIGURATION% &&
|
||||
@@ -273,12 +184,22 @@
|
||||
POPD &&
|
||||
ECHO ***
|
||||
)
|
||||
- if [%HOST%]==[visual] (
|
||||
ECHO *** &&
|
||||
ECHO *** Building Visual Studio 2012 %PLATFORM%\%CONFIGURATION% &&
|
||||
ECHO *** &&
|
||||
msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\build\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
|
||||
DIR build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe &&
|
||||
msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
|
||||
DIR build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe
|
||||
)
|
||||
|
||||
|
||||
test_script:
|
||||
- ECHO Testing %COMPILER% %PLATFORM% %CONFIGURATION%
|
||||
- SET "FUZZERTEST=-T10s"
|
||||
- if [%HOST%]==[mingw] (
|
||||
set "CC=%COMPILER%" &&
|
||||
make clean &&
|
||||
make check
|
||||
)
|
||||
)
|
||||
@@ -92,8 +92,14 @@ else ()
|
||||
add_definitions(-DZSTD_LEGACY_SUPPORT=0)
|
||||
endif ()
|
||||
|
||||
if (ANDROID)
|
||||
set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT OFF)
|
||||
else()
|
||||
set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
# Multi-threading support
|
||||
option(ZSTD_MULTITHREAD_SUPPORT "MULTITHREADING SUPPORT" ON)
|
||||
option(ZSTD_MULTITHREAD_SUPPORT "MULTITHREADING SUPPORT" ${ZSTD_MULTITHREAD_SUPPORT_DEFAULT})
|
||||
|
||||
if (ZSTD_MULTITHREAD_SUPPORT)
|
||||
message(STATUS "ZSTD_MULTITHREAD_SUPPORT is enabled")
|
||||
|
||||
@@ -106,7 +106,7 @@ if (MSVC)
|
||||
endif ()
|
||||
|
||||
# With MSVC static library needs to be renamed to avoid conflict with import library
|
||||
if (MSVC)
|
||||
if (MSVC OR (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT MINGW))
|
||||
set(STATIC_LIBRARY_BASE_NAME zstd_static)
|
||||
else ()
|
||||
set(STATIC_LIBRARY_BASE_NAME zstd)
|
||||
|
||||
@@ -37,7 +37,6 @@ libzstd_sources = [join_paths(zstd_rootdir, 'lib/common/entropy_common.c'),
|
||||
join_paths(zstd_rootdir, 'lib/compress/zstd_opt.c'),
|
||||
join_paths(zstd_rootdir, 'lib/compress/zstd_ldm.c'),
|
||||
join_paths(zstd_rootdir, 'lib/decompress/huf_decompress.c'),
|
||||
join_paths(zstd_rootdir, 'lib/decompress/huf_decompress_amd64.S'),
|
||||
join_paths(zstd_rootdir, 'lib/decompress/zstd_decompress.c'),
|
||||
join_paths(zstd_rootdir, 'lib/decompress/zstd_decompress_block.c'),
|
||||
join_paths(zstd_rootdir, 'lib/decompress/zstd_ddict.c'),
|
||||
@@ -46,6 +45,15 @@ libzstd_sources = [join_paths(zstd_rootdir, 'lib/common/entropy_common.c'),
|
||||
join_paths(zstd_rootdir, 'lib/dictBuilder/divsufsort.c'),
|
||||
join_paths(zstd_rootdir, 'lib/dictBuilder/zdict.c')]
|
||||
|
||||
# really we need anything that defines __GNUC__ as that is what ZSTD_ASM_SUPPORTED is gated on
|
||||
# but these are the two compilers that are supported in tree and actually handle this correctly
|
||||
# Otherwise, explicitly disable assmebly.
|
||||
if [compiler_gcc, compiler_clang].contains(cc_id)
|
||||
libzstd_sources += join_paths(zstd_rootdir, 'lib/decompress/huf_decompress_amd64.S')
|
||||
else
|
||||
add_project_arguments('-DZSTD_DISABLE_ASM', language: 'c')
|
||||
endif
|
||||
|
||||
# Explicit define legacy support
|
||||
add_project_arguments('-DZSTD_LEGACY_SUPPORT=@0@'.format(legacy_level),
|
||||
language: 'c')
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* Note: MEM_MODULE stops xxhash redefining BYTE, U16, etc., which are also
|
||||
* defined in mem.h (breaking C99 compatibility).
|
||||
*
|
||||
* Note: the undefs for xxHash allow Zstd's implementation to coinside with with
|
||||
* Note: the undefs for xxHash allow Zstd's implementation to coincide with with
|
||||
* standalone xxHash usage (with global defines).
|
||||
*
|
||||
* Note: multithreading is enabled for all platforms apart from Emscripten.
|
||||
@@ -44,7 +44,7 @@
|
||||
#endif
|
||||
#define ZSTD_TRACE 0
|
||||
/* TODO: Can't amalgamate ASM function */
|
||||
#define HUF_DISABLE_ASM 1
|
||||
#define ZSTD_DISABLE_ASM 1
|
||||
|
||||
/* Include zstd_deps.h first with all the options we need enabled. */
|
||||
#define ZSTD_DEPS_NEED_MALLOC
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* Note: MEM_MODULE stops xxhash redefining BYTE, U16, etc., which are also
|
||||
* defined in mem.h (breaking C99 compatibility).
|
||||
*
|
||||
* Note: the undefs for xxHash allow Zstd's implementation to coinside with with
|
||||
* Note: the undefs for xxHash allow Zstd's implementation to coincide with with
|
||||
* standalone xxHash usage (with global defines).
|
||||
*/
|
||||
#define DEBUGLEVEL 0
|
||||
@@ -40,7 +40,7 @@
|
||||
#define ZSTD_STRIP_ERROR_STRINGS
|
||||
#define ZSTD_TRACE 0
|
||||
/* TODO: Can't amalgamate ASM function */
|
||||
#define HUF_DISABLE_ASM 1
|
||||
#define ZSTD_DISABLE_ASM 1
|
||||
|
||||
/* Include zstd_deps.h first with all the options we need enabled. */
|
||||
#define ZSTD_DEPS_NEED_MALLOC
|
||||
|
||||
@@ -41,7 +41,6 @@ libzstd:
|
||||
-DZSTD_MEMORY_SANITIZER=0 \
|
||||
-DZSTD_DATAFLOW_SANITIZER=0 \
|
||||
-DZSTD_COMPRESS_HEAPMODE=1 \
|
||||
-UZSTD_NO_INLINE \
|
||||
-UNO_PREFETCH \
|
||||
-U__cplusplus \
|
||||
-UZSTD_DLL_EXPORT \
|
||||
@@ -55,7 +54,8 @@ libzstd:
|
||||
-RZSTD_FALLTHROUGH=fallthrough \
|
||||
-DZSTD_HAVE_WEAK_SYMBOLS=0 \
|
||||
-DZSTD_TRACE=0 \
|
||||
-DZSTD_NO_TRACE
|
||||
-DZSTD_NO_TRACE \
|
||||
-DZSTD_LINUX_KERNEL
|
||||
mv linux/lib/zstd/zstd.h linux/include/linux/zstd_lib.h
|
||||
mv linux/lib/zstd/zstd_errors.h linux/include/linux/
|
||||
cp linux_zstd.h linux/include/linux/zstd.h
|
||||
|
||||
@@ -16,16 +16,17 @@
|
||||
* decompression.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Disable the ASM Huffman implementation because we need to
|
||||
* include all the sources.
|
||||
*/
|
||||
#define ZSTD_DISABLE_ASM 1
|
||||
|
||||
#include "common/debug.c"
|
||||
#include "common/entropy_common.c"
|
||||
#include "common/error_private.c"
|
||||
#include "common/fse_decompress.c"
|
||||
#include "common/zstd_common.c"
|
||||
/*
|
||||
* Disable the ASM Huffman implementation because we need to
|
||||
* include all the sources.
|
||||
*/
|
||||
#define HUF_DISABLE_ASM 1
|
||||
#include "decompress/huf_decompress.c"
|
||||
#include "decompress/zstd_ddict.c"
|
||||
#include "decompress/zstd_decompress.c"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
obj-$(CONFIG_ZSTD_COMPRESS) += zstd_compress.o
|
||||
obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd_decompress.o
|
||||
|
||||
ccflags-y += -O3
|
||||
ccflags-y += -Wno-error=deprecated-declarations
|
||||
|
||||
zstd_compress-y := \
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
* Basic Types
|
||||
*****************************************************************/
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint8_t U8;
|
||||
typedef int8_t S8;
|
||||
typedef uint16_t U16;
|
||||
typedef int16_t S16;
|
||||
typedef uint32_t U32;
|
||||
|
||||
@@ -36,7 +36,6 @@ test_not_present "ZSTD_NO_INTRINSICS"
|
||||
test_not_present "ZSTD_NO_UNUSED_FUNCTIONS"
|
||||
test_not_present "ZSTD_LEGACY_SUPPORT"
|
||||
test_not_present "STATIC_BMI2"
|
||||
test_not_present "ZSTD_NO_INLINE"
|
||||
test_not_present "ZSTD_DLL_EXPORT"
|
||||
test_not_present "ZSTD_DLL_IMPORT"
|
||||
test_not_present "__ICCARM__"
|
||||
|
||||
@@ -87,7 +87,7 @@ void usage() {
|
||||
std::fprintf(stderr, " -V, --version : display version number and exit\n");
|
||||
std::fprintf(stderr, " -v, --verbose : verbose mode; specify multiple times to increase log level (default:2)\n");
|
||||
std::fprintf(stderr, " -q, --quiet : suppress warnings; specify twice to suppress errors too\n");
|
||||
std::fprintf(stderr, " -c, --stdout : force write to standard output, even if it is the console\n");
|
||||
std::fprintf(stderr, " -c, --stdout : write to standard output (even if it is the console)\n");
|
||||
#ifdef UTIL_HAS_CREATEFILELIST
|
||||
std::fprintf(stderr, " -r : operate recursively on directories\n");
|
||||
#endif
|
||||
|
||||
@@ -45,7 +45,7 @@ class Buffer {
|
||||
: buffer_(buffer), range_(data) {}
|
||||
|
||||
Buffer(Buffer&&) = default;
|
||||
Buffer& operator=(Buffer&&) & = default;
|
||||
Buffer& operator=(Buffer&&) = default;
|
||||
|
||||
/**
|
||||
* Splits the data into two pieces: [begin, begin + n), [begin + n, end).
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* 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).
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* A subset of `folly/Range.h`.
|
||||
* All code copied verbatim modulo formatting
|
||||
@@ -83,8 +83,8 @@ class Range {
|
||||
Range(const Range&) = default;
|
||||
Range(Range&&) = default;
|
||||
|
||||
Range& operator=(const Range&) & = default;
|
||||
Range& operator=(Range&&) & = default;
|
||||
Range& operator=(const Range&) = default;
|
||||
Range& operator=(Range&&) = default;
|
||||
|
||||
constexpr size_type size() const {
|
||||
return e_ - b_;
|
||||
|
||||
@@ -2145,7 +2145,7 @@ static void FSE_init_dtable(FSE_dtable *const dtable,
|
||||
|
||||
// "All remaining symbols are sorted in their natural order. Starting from
|
||||
// symbol 0 and table position 0, each symbol gets attributed as many cells
|
||||
// as its probability. Cell allocation is spreaded, not linear."
|
||||
// as its probability. Cell allocation is spread, not linear."
|
||||
// Place the rest in the table
|
||||
const u16 step = (size >> 1) + (size >> 3) + 3;
|
||||
const u16 mask = size - 1;
|
||||
|
||||
@@ -1124,7 +1124,7 @@ These symbols define a full state reset, reading `Accuracy_Log` bits.
|
||||
Then, all remaining symbols, sorted in natural order, are allocated cells.
|
||||
Starting from symbol `0` (if it exists), and table position `0`,
|
||||
each symbol gets allocated as many cells as its probability.
|
||||
Cell allocation is spreaded, not linear :
|
||||
Cell allocation is spread, not linear :
|
||||
each successor position follows this rule :
|
||||
|
||||
```
|
||||
|
||||
+109
-71
@@ -1,10 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>zstd 1.5.0 Manual</title>
|
||||
<title>zstd 1.5.1 Manual</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>zstd 1.5.0 Manual</h1>
|
||||
<h1>zstd 1.5.1 Manual</h1>
|
||||
<hr>
|
||||
<a name="Contents"></a><h2>Contents</h2>
|
||||
<ol>
|
||||
@@ -357,7 +357,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); </b>/* accept NULL pointer */<b>
|
||||
* ZSTD_c_stableOutBuffer
|
||||
* ZSTD_c_blockDelimiters
|
||||
* ZSTD_c_validateSequences
|
||||
* ZSTD_c_splitBlocks
|
||||
* ZSTD_c_useBlockSplitter
|
||||
* ZSTD_c_useRowMatchFinder
|
||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||
* note : never ever use experimentalParam? names directly;
|
||||
@@ -803,7 +803,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_decompress(). Dictionaries are sticky, and
|
||||
ZSTD_compressStream2(), and ZSTD_decompressDCtx(). Dictionaries are sticky, and
|
||||
only reset with the context is reset with ZSTD_reset_parameters or
|
||||
ZSTD_reset_session_and_parameters. Prefixes are single-use.
|
||||
<BR></pre>
|
||||
@@ -1072,14 +1072,18 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
} ZSTD_literalCompressionMode_e;
|
||||
</b></pre><BR>
|
||||
<pre><b>typedef enum {
|
||||
ZSTD_urm_auto = 0, </b>/* Automatically determine whether or not we use row matchfinder */<b>
|
||||
ZSTD_urm_disableRowMatchFinder = 1, </b>/* Never use row matchfinder */<b>
|
||||
ZSTD_urm_enableRowMatchFinder = 2 </b>/* Always use row matchfinder when applicable */<b>
|
||||
} ZSTD_useRowMatchFinderMode_e;
|
||||
</b>/* Note: This enum controls features which are conditionally beneficial. Zstd typically will make a final<b>
|
||||
* decision on whether or not to enable the feature (ZSTD_ps_auto), but setting the switch to ZSTD_ps_enable
|
||||
* or ZSTD_ps_disable allow for a force enable/disable the feature.
|
||||
*/
|
||||
ZSTD_ps_auto = 0, </b>/* Let the library automatically determine whether the feature shall be enabled */<b>
|
||||
ZSTD_ps_enable = 1, </b>/* Force-enable the feature */<b>
|
||||
ZSTD_ps_disable = 2 </b>/* Do not use the feature */<b>
|
||||
} ZSTD_paramSwitch_e;
|
||||
</b></pre><BR>
|
||||
<a name="Chapter15"></a><h2>Frame size functions</h2><pre></pre>
|
||||
|
||||
<pre><b>unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
|
||||
</b><p> `src` should point to the start of a series of ZSTD encoded and/or skippable frames
|
||||
`srcSize` must be the _exact_ size of this series
|
||||
(i.e. there should be a frame boundary at `src + srcSize`)
|
||||
@@ -1102,7 +1106,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
however it does mean that all frame data must be present and valid.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
|
||||
</b><p> `src` should point to the start of a series of ZSTD encoded and/or skippable frames
|
||||
`srcSize` must be the _exact_ size of this series
|
||||
(i.e. there should be a frame boundary at `src + srcSize`)
|
||||
@@ -1117,7 +1121,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
|
||||
</b><p> srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
|
||||
@return : size of the Frame Header,
|
||||
or an error code (if srcSize is too small)
|
||||
@@ -1144,7 +1148,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);
|
||||
</b><p> Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals
|
||||
by merging them into into the literals of the next sequence.
|
||||
|
||||
@@ -1157,7 +1161,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize,
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize,
|
||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t srcSize);
|
||||
</b><p> Compress an array of ZSTD_Sequence, generated from the original source buffer, into dst.
|
||||
@@ -1189,7 +1193,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize, unsigned magicVariant);
|
||||
</b><p> Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.
|
||||
|
||||
@@ -1205,12 +1209,31 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
|
||||
const void* src, size_t srcSize);
|
||||
</b><p> Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
|
||||
|
||||
The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
|
||||
i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
|
||||
in the magicVariant.
|
||||
|
||||
Returns an error if destination buffer is not large enough, or if the frame is not skippable.
|
||||
|
||||
@return : number of bytes written or a ZSTD error.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);
|
||||
</b><p> Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter16"></a><h2>Memory management</h2><pre></pre>
|
||||
|
||||
<pre><b>size_t ZSTD_estimateCCtxSize(int compressionLevel);
|
||||
size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);
|
||||
size_t ZSTD_estimateDCtxSize(void);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
|
||||
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.
|
||||
|
||||
@@ -1235,11 +1258,11 @@ size_t ZSTD_estimateDCtxSize(void);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_estimateCStreamSize(int compressionLevel);
|
||||
size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);
|
||||
size_t ZSTD_estimateDStreamSize(size_t windowSize);
|
||||
size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
|
||||
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_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.
|
||||
If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
|
||||
@@ -1254,17 +1277,17 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
|
||||
In this case, get total size by adding ZSTD_estimate?DictSize
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
|
||||
size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
|
||||
size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
|
||||
</b><p> ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict().
|
||||
ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced().
|
||||
Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
|
||||
ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); </b>/**< same as ZSTD_initStaticCCtx() */<b>
|
||||
<pre><b>ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
|
||||
ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); </b>/**< same as ZSTD_initStaticCCtx() */<b>
|
||||
</b><p> Initialize an object using a pre-allocated fixed-size buffer.
|
||||
workspace: The memory area to emplace the object into.
|
||||
Provided pointer *must be 8-bytes aligned*.
|
||||
@@ -1287,7 +1310,7 @@ ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); </b>/**< same as ZSTD_initStaticDCtx() */<b>
|
||||
<pre><b>ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); </b>/**< same as ZSTD_initStaticDCtx() */<b>
|
||||
</b></pre><BR>
|
||||
<pre><b>typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
|
||||
typedef void (*ZSTD_freeFunction) (void* opaque, void* address);
|
||||
@@ -1303,9 +1326,24 @@ ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; </b>/**< this con
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>typedef struct POOL_ctx_s ZSTD_threadPool;
|
||||
ZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
|
||||
ZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); </b>/* accept NULL pointer */<b>
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
|
||||
</b><p> These prototypes make it possible to share a thread pool among multiple compression contexts.
|
||||
This can limit resources for applications with multiple threads where each one uses
|
||||
a threaded compression mode (via ZSTD_c_nbWorkers parameter).
|
||||
ZSTD_createThreadPool creates a new thread pool with a given number of threads.
|
||||
Note that the lifetime of such pool must exist while being used.
|
||||
ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
|
||||
to use an internal thread pool).
|
||||
ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<a name="Chapter17"></a><h2>Advanced compression functions</h2><pre></pre>
|
||||
|
||||
<pre><b>ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||
<pre><b>ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||
</b><p> Create a digested dictionary for compression
|
||||
Dictionary content is just referenced, not duplicated.
|
||||
As a consequence, `dictBuffer` **must** outlive CDict,
|
||||
@@ -1313,22 +1351,22 @@ ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; </b>/**< this con
|
||||
note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
</b><p> @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
||||
`estimatedSrcSize` value is optional, select 0 if not known
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
</b><p> same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
|
||||
All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
</b><p> Ensure param values remain within authorized range.
|
||||
@return 0 on success, or an error code (can be checked with ZSTD_isError())
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
|
||||
</b><p> optimize params for a given `srcSize` and `dictSize`.
|
||||
`srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
`dictSize` must be `0` when there is no dictionary.
|
||||
@@ -1358,31 +1396,31 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
|
||||
This prototype will generate compilation warnings.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
||||
</b><p> Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx.
|
||||
It saves some memory, but also requires that `dict` outlives its usage within `cctx`
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
|
||||
</b><p> Same as ZSTD_CCtx_loadDictionary(), but gives finer control over
|
||||
how to load the dictionary (by copy ? by reference ?)
|
||||
and how to interpret it (automatic ? force raw mode ? full mode only ?)
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
|
||||
</b><p> Same as ZSTD_CCtx_refPrefix(), but gives finer control over
|
||||
how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?)
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
|
||||
</b><p> Get the requested compression parameter value, selected by enum ZSTD_cParameter,
|
||||
and store it into int* value.
|
||||
@return : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
|
||||
size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); </b>/* accept NULL pointer */<b>
|
||||
<pre><b>ZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); </b>/* accept NULL pointer */<b>
|
||||
</b><p> Quick howto :
|
||||
- ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
|
||||
- ZSTD_CCtxParams_setParameter() : Push parameters one by one into
|
||||
@@ -1401,24 +1439,24 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); </b>/* accept NULL pointe
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
|
||||
</b><p> Reset params to default values.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
|
||||
</b><p> Initializes the compression parameters of cctxParams according to
|
||||
compression level. All other parameters are reset to their default values.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
|
||||
</b><p> Initializes the compression and frame parameters of cctxParams according to
|
||||
params. All other parameters are reset to their default values.
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
|
||||
</b><p> Similar to ZSTD_CCtx_setParameter.
|
||||
Set one compression parameter, selected by enum ZSTD_cParameter.
|
||||
Parameters must be applied to a ZSTD_CCtx using
|
||||
@@ -1428,14 +1466,14 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); </b>/* accept NULL pointe
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
||||
</b><p> Similar to ZSTD_CCtx_getParameter.
|
||||
Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
|
||||
@result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
||||
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);
|
||||
</b><p> Apply a set of ZSTD_CCtx_params to the compression context.
|
||||
This can be done even after compression is started,
|
||||
@@ -1445,7 +1483,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); </b>/* accept NULL pointe
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_compressStream2_simpleArgs (
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs (
|
||||
ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity, size_t* dstPos,
|
||||
const void* src, size_t srcSize, size_t* srcPos,
|
||||
@@ -1459,40 +1497,40 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); </b>/* accept NULL pointe
|
||||
|
||||
<a name="Chapter18"></a><h2>Advanced decompression functions</h2><pre></pre>
|
||||
|
||||
<pre><b>unsigned ZSTD_isFrame(const void* buffer, size_t size);
|
||||
<pre><b>ZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
|
||||
</b><p> Tells if the content of `buffer` starts with a valid Frame Identifier.
|
||||
Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
|
||||
Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
|
||||
Note 3 : Skippable Frame Identifiers are considered valid.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
|
||||
</b><p> Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||
Dictionary content is referenced, and therefore stays in dictBuffer.
|
||||
It is important that dictBuffer outlives DDict,
|
||||
it must remain read accessible throughout the lifetime of DDict
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
||||
</b><p> Same as ZSTD_DCtx_loadDictionary(),
|
||||
but references `dict` content instead of copying it into `dctx`.
|
||||
This saves memory if `dict` remains around.,
|
||||
However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression.
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
|
||||
</b><p> Same as ZSTD_DCtx_loadDictionary(),
|
||||
but gives direct control over
|
||||
how to load the dictionary (by copy ? by reference ?)
|
||||
and how to interpret it (automatic ? force raw mode ? full mode only ?).
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
|
||||
</b><p> Same as ZSTD_DCtx_refPrefix(), but gives finer control over
|
||||
how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?)
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
|
||||
</b><p> Refuses allocating internal buffers for frames requiring a window size larger than provided limit.
|
||||
This protects a decoder context from reserving too much memory for itself (potential attack scenario).
|
||||
This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
|
||||
@@ -1501,7 +1539,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); </b>/* accept NULL pointe
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);
|
||||
</b><p> Get the requested decompression parameter value, selected by enum ZSTD_dParameter,
|
||||
and store it into int* value.
|
||||
@return : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
@@ -1517,7 +1555,7 @@ size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
|
||||
@return : 0, or an error code (which can be tested using ZSTD_isError()).
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_decompressStream_simpleArgs (
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs (
|
||||
ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity, size_t* dstPos,
|
||||
const void* src, size_t srcSize, size_t* srcPos);
|
||||
@@ -1594,7 +1632,7 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
|
||||
</b><p> This function is DEPRECATED, and equivalent to:
|
||||
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
ZSTD_CCtx_refCDict(zcs, cdict);
|
||||
|
||||
|
||||
note : cdict will just be referenced, and must outlive compression session
|
||||
This prototype will generate compilation warnings.
|
||||
|
||||
@@ -1651,7 +1689,7 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
||||
unsigned nbActiveWorkers; </b>/* MT only : nb of workers actively compressing at probe time */<b>
|
||||
} ZSTD_frameProgression;
|
||||
</b></pre><BR>
|
||||
<pre><b>size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
|
||||
</b><p> Tell how many bytes are ready to be flushed immediately.
|
||||
Useful for multithreading scenarios (nbWorkers >= 1).
|
||||
Probe the oldest active job, defined as oldest job not yet entirely flushed,
|
||||
@@ -1667,7 +1705,7 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
||||
</p></pre><BR>
|
||||
|
||||
<h3>Advanced Streaming decompression functions</h3><pre></pre><b><pre></pre></b><BR>
|
||||
<pre><b>size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
|
||||
</b><p>
|
||||
ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
ZSTD_DCtx_loadDictionary(zds, dict, dictSize);
|
||||
@@ -1677,7 +1715,7 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
|
||||
</b><p>
|
||||
ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
ZSTD_DCtx_refDDict(zds, ddict);
|
||||
@@ -1687,7 +1725,7 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
||||
|
||||
</p></pre><BR>
|
||||
|
||||
<pre><b>size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
</b><p>
|
||||
ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
|
||||
@@ -1731,10 +1769,10 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
||||
`ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again.
|
||||
<BR></pre>
|
||||
|
||||
<h3>Buffer-less streaming compression functions</h3><pre></pre><b><pre>size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
|
||||
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
|
||||
size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); </b>/**< note: fails if cdict==NULL */<b>
|
||||
size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); </b>/**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */<b>
|
||||
<h3>Buffer-less streaming compression functions</h3><pre></pre><b><pre>ZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); </b>/**< note: fails if cdict==NULL */<b>
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); </b>/**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */<b>
|
||||
</pre></b><BR>
|
||||
<pre><b>size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); </b>/**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */<b>
|
||||
</b></pre><BR>
|
||||
@@ -1820,12 +1858,12 @@ typedef struct {
|
||||
unsigned checksumFlag;
|
||||
} ZSTD_frameHeader;
|
||||
</pre></b><BR>
|
||||
<pre><b>size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); </b>/**< doesn't consume input */<b>
|
||||
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); </b>/**< doesn't consume input */<b>
|
||||
</b>/*! ZSTD_getFrameHeader_advanced() :<b>
|
||||
* same as ZSTD_getFrameHeader(),
|
||||
* with added capability to select a format (like ZSTD_f_zstd1_magicless) */
|
||||
size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
|
||||
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); </b>/**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */<b>
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); </b>/**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */<b>
|
||||
</b><p> decode Frame Header, or requires larger `srcSize`.
|
||||
@return : 0, `zfhPtr` is correctly filled,
|
||||
>0, `srcSize` is too small, value is wanted `srcSize` amount,
|
||||
@@ -1861,10 +1899,10 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
|
||||
Use ZSTD_insertBlock() for such a case.
|
||||
</p></pre><BR>
|
||||
|
||||
<h3>Raw zstd block functions</h3><pre></pre><b><pre>size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
|
||||
size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); </b>/**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */<b>
|
||||
<h3>Raw zstd block functions</h3><pre></pre><b><pre>ZSTDLIB_STATIC_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); </b>/**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */<b>
|
||||
</pre></b><BR>
|
||||
</html>
|
||||
</body>
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ typedef enum {
|
||||
* Check the zstd error code and die if an error occurred after printing a
|
||||
* message.
|
||||
*/
|
||||
#define CHECK_ZSTD(fn, ...) \
|
||||
#define CHECK_ZSTD(fn) \
|
||||
do { \
|
||||
size_t const err = (fn); \
|
||||
CHECK(!ZSTD_isError(err), "%s", ZSTD_getErrorName(err)); \
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
#include <zstd.h> // presumes zstd library is installed
|
||||
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||
|
||||
|
||||
static void compressFile_orDie(const char* fname, const char* outName, int cLevel)
|
||||
static void compressFile_orDie(const char* fname, const char* outName, int cLevel,
|
||||
int nbThreads)
|
||||
{
|
||||
fprintf (stderr, "Starting compression of %s with level %d, using %d threads\n",
|
||||
fname, cLevel, nbThreads);
|
||||
|
||||
/* Open the input and output files. */
|
||||
FILE* const fin = fopen_orDie(fname, "rb");
|
||||
FILE* const fout = fopen_orDie(outName, "wb");
|
||||
@@ -39,7 +42,7 @@ static void compressFile_orDie(const char* fname, const char* outName, int cLeve
|
||||
*/
|
||||
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel) );
|
||||
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) );
|
||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 4);
|
||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads);
|
||||
|
||||
/* This loop read from the input file, compresses that entire chunk,
|
||||
* and writes all output produced to the output file.
|
||||
@@ -106,19 +109,32 @@ int main(int argc, const char** argv)
|
||||
{
|
||||
const char* const exeName = argv[0];
|
||||
|
||||
if (argc!=2) {
|
||||
if (argc < 2) {
|
||||
printf("wrong arguments\n");
|
||||
printf("usage:\n");
|
||||
printf("%s FILE\n", exeName);
|
||||
printf("%s FILE [LEVEL] [THREADS]\n", exeName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cLevel = 1;
|
||||
int nbThreads = 4;
|
||||
|
||||
if (argc >= 3) {
|
||||
cLevel = atoi (argv[2]);
|
||||
CHECK(cLevel != 0, "can't parse LEVEL!");
|
||||
}
|
||||
|
||||
if (argc >= 4) {
|
||||
nbThreads = atoi (argv[3]);
|
||||
CHECK(nbThreads != 0, "can't parse THREADS!");
|
||||
}
|
||||
|
||||
const char* const inFilename = argv[1];
|
||||
|
||||
char* const outFilename = createOutFilename_orDie(inFilename);
|
||||
compressFile_orDie(inFilename, outFilename, 1);
|
||||
compressFile_orDie(inFilename, outFilename, cLevel, nbThreads);
|
||||
|
||||
free(outFilename); /* not strictly required, since program execution stops there,
|
||||
* but some static analyzer main complain otherwise */
|
||||
* but some static analyzer may complain otherwise */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,10 @@ typedef struct compress_args
|
||||
|
||||
static void *compressFile_orDie(void *data)
|
||||
{
|
||||
const int nbThreads = 16;
|
||||
|
||||
compress_args_t *args = (compress_args_t *)data;
|
||||
fprintf (stderr, "Starting compression of %s with level %d\n", args->fname, args->cLevel);
|
||||
fprintf (stderr, "Starting compression of %s with level %d, using %d threads\n", args->fname, args->cLevel, nbThreads);
|
||||
/* Open the input and output files. */
|
||||
FILE* const fin = fopen_orDie(args->fname, "rb");
|
||||
FILE* const fout = fopen_orDie(args->outName, "wb");
|
||||
@@ -56,9 +58,9 @@ static void *compressFile_orDie(void *data)
|
||||
*/
|
||||
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, args->cLevel) );
|
||||
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) );
|
||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 16);
|
||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads);
|
||||
|
||||
/* This loop read from the input file, compresses that entire chunk,
|
||||
/* This loop reads from the input file, compresses that entire chunk,
|
||||
* and writes all output produced to the output file.
|
||||
*/
|
||||
size_t const toRead = buffInSize;
|
||||
|
||||
+15
-11
@@ -57,9 +57,9 @@ VERSION := $(ZSTD_VERSION)
|
||||
.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_DYNLIB += -DZSTD_MULTITHREAD # dynamic library build defaults to multi-threaded
|
||||
LDFLAGS_DYNLIB += -pthread
|
||||
CPPFLAGS_STATLIB += # static library build defaults to single-threaded
|
||||
|
||||
|
||||
ifeq ($(findstring GCC,$(CCVER)),GCC)
|
||||
@@ -75,7 +75,11 @@ ifeq ($(UNAME), Darwin)
|
||||
SHARED_EXT_VER = $(LIBVER).$(SHARED_EXT)
|
||||
SONAME_FLAGS = -install_name $(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR) -compatibility_version $(LIBVER_MAJOR) -current_version $(LIBVER)
|
||||
else
|
||||
SONAME_FLAGS = -Wl,-soname=libzstd.$(SHARED_EXT).$(LIBVER_MAJOR)
|
||||
ifeq ($(UNAME), AIX)
|
||||
SONAME_FLAGS =
|
||||
else
|
||||
SONAME_FLAGS = -Wl,-soname=libzstd.$(SHARED_EXT).$(LIBVER_MAJOR)
|
||||
endif
|
||||
SHARED_EXT = so
|
||||
SHARED_EXT_MAJOR = $(SHARED_EXT).$(LIBVER_MAJOR)
|
||||
SHARED_EXT_VER = $(SHARED_EXT).$(LIBVER)
|
||||
@@ -245,9 +249,9 @@ clean:
|
||||
#-----------------------------------------------------------------------------
|
||||
# make install is validated only for below listed environments
|
||||
#-----------------------------------------------------------------------------
|
||||
ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku))
|
||||
ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX))
|
||||
|
||||
all: libzstd.pc
|
||||
lib: libzstd.pc
|
||||
|
||||
HAS_EXPLICIT_EXEC_PREFIX := $(if $(or $(EXEC_PREFIX),$(exec_prefix)),1,)
|
||||
|
||||
@@ -292,16 +296,16 @@ INSTALL_PROGRAM ?= $(INSTALL)
|
||||
INSTALL_DATA ?= $(INSTALL) -m 644
|
||||
|
||||
|
||||
libzstd.pc:
|
||||
libzstd.pc: libzstd.pc.in
|
||||
@echo creating pkgconfig
|
||||
@sed $(SED_ERE_OPT) \
|
||||
-e 's|@PREFIX@|$(PREFIX)|' \
|
||||
-e 's|@EXEC_PREFIX@|$(PCEXEC_PREFIX)|' \
|
||||
-e 's|@INCLUDEDIR@|$(PCINCPREFIX)$(PCINCDIR)|' \
|
||||
-e 's|@LIBDIR@|$(PCLIBPREFIX)$(PCLIBDIR)|' \
|
||||
-e 's|@VERSION@|$(VERSION)|' \
|
||||
$< >$@
|
||||
-e 's|@INCLUDEDIR@|$(PCINCPREFIX)$(PCINCDIR)|' \
|
||||
-e 's|@LIBDIR@|$(PCLIBPREFIX)$(PCLIBDIR)|' \
|
||||
-e 's|@VERSION@|$(VERSION)|' \
|
||||
-e 's|@LIBS_PRIVATE@|$(LDFLAGS_DYNLIB)|' \
|
||||
$< >$@
|
||||
|
||||
.PHONY: install
|
||||
install: install-pc install-static install-shared install-includes
|
||||
|
||||
+7
-1
@@ -125,7 +125,7 @@ The file structure is designed to make this selection manually achievable for an
|
||||
`ZSTD_getErrorName` (implied by `ZSTD_LIB_MINIFY`).
|
||||
|
||||
Finally, when integrating into your application, make sure you're doing link-
|
||||
time optimation and unused symbol garbage collection (via some combination of,
|
||||
time optimization and unused symbol garbage collection (via some combination of,
|
||||
e.g., `-flto`, `-ffat-lto-objects`, `-fuse-linker-plugin`,
|
||||
`-ffunction-sections`, `-fdata-sections`, `-fmerge-all-constants`,
|
||||
`-Wl,--gc-sections`, `-Wl,-z,norelro`, and an archiver that understands
|
||||
@@ -155,6 +155,12 @@ The file structure is designed to make this selection manually achievable for an
|
||||
- The build macro `ZSTD_NO_INTRINSICS` can be defined to disable all explicit intrinsics.
|
||||
Compiler builtins are still used.
|
||||
|
||||
- The build macro `ZSTD_DECODER_INTERNAL_BUFFER` can be set to control
|
||||
the amount of extra memory used during decompression to store literals.
|
||||
This defaults to 64kB. Reducing this value reduces the memory footprint of
|
||||
`ZSTD_DCtx` decompression contexts,
|
||||
but might also result in a small decompression speed cost.
|
||||
|
||||
|
||||
#### Windows : using MinGW+MSYS to create DLL
|
||||
|
||||
|
||||
@@ -143,10 +143,16 @@ MEM_STATIC unsigned BIT_highbit32 (U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
# if STATIC_BMI2 == 1
|
||||
return _lzcnt_u32(val) ^ 31;
|
||||
return _lzcnt_u32(val) ^ 31;
|
||||
# else
|
||||
unsigned long r = 0;
|
||||
return _BitScanReverse(&r, val) ? (unsigned)r : 0;
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanReverse(&r, val);
|
||||
return (unsigned)r;
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# endif
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
||||
return __builtin_clz (val) ^ 31;
|
||||
|
||||
+40
-53
@@ -11,6 +11,8 @@
|
||||
#ifndef ZSTD_COMPILER_H
|
||||
#define ZSTD_COMPILER_H
|
||||
|
||||
#include "portability_macros.h"
|
||||
|
||||
/*-*******************************************************
|
||||
* Compiler specifics
|
||||
*********************************************************/
|
||||
@@ -40,7 +42,7 @@
|
||||
|
||||
/**
|
||||
On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).
|
||||
This explictly marks such functions as __cdecl so that the code will still compile
|
||||
This explicitly marks such functions as __cdecl so that the code will still compile
|
||||
if a CC other than __cdecl has been made the default.
|
||||
*/
|
||||
#if defined(_MSC_VER)
|
||||
@@ -92,29 +94,17 @@
|
||||
|
||||
|
||||
/* target attribute */
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
||||
#endif
|
||||
#if defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
|
||||
#else
|
||||
# define TARGET_ATTRIBUTE(target)
|
||||
#endif
|
||||
|
||||
/* Enable runtime BMI2 dispatch based on the CPU.
|
||||
* Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
|
||||
/* Target attribute for BMI2 dynamic dispatch.
|
||||
* Enable lzcnt, bmi, and bmi2.
|
||||
* We test for bmi1 & bmi2. lzcnt is included in bmi1.
|
||||
*/
|
||||
#ifndef DYNAMIC_BMI2
|
||||
#if ((defined(__clang__) && __has_attribute(__target__)) \
|
||||
|| (defined(__GNUC__) \
|
||||
&& (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
|
||||
&& (defined(__x86_64__) || defined(_M_X64)) \
|
||||
&& !defined(__BMI2__)
|
||||
# define DYNAMIC_BMI2 1
|
||||
#else
|
||||
# define DYNAMIC_BMI2 0
|
||||
#endif
|
||||
#endif
|
||||
#define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE("lzcnt,bmi,bmi2")
|
||||
|
||||
/* prefetch
|
||||
* can be disabled, by declaring NO_PREFETCH build macro */
|
||||
@@ -214,16 +204,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* compat. with non-clang compilers */
|
||||
#ifndef __has_builtin
|
||||
# define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
/* compat. with non-clang compilers */
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
/* C-language Attributes are added in C23. */
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)
|
||||
# define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
|
||||
@@ -251,29 +231,47 @@
|
||||
# elif ZSTD_HAS_CPP_ATTRIBUTE(fallthrough)
|
||||
# define ZSTD_FALLTHROUGH [[fallthrough]]
|
||||
# elif __has_attribute(__fallthrough__)
|
||||
# define ZSTD_FALLTHROUGH __attribute__((__fallthrough__))
|
||||
/* Leading semicolon is to satisfy gcc-11 with -pedantic. Without the semicolon
|
||||
* gcc complains about: a label can only be part of a statement and a declaration is not a statement.
|
||||
*/
|
||||
# define ZSTD_FALLTHROUGH ; __attribute__((__fallthrough__))
|
||||
# else
|
||||
# define ZSTD_FALLTHROUGH
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* detects whether we are being compiled under msan */
|
||||
#ifndef ZSTD_MEMORY_SANITIZER
|
||||
# if __has_feature(memory_sanitizer)
|
||||
# define ZSTD_MEMORY_SANITIZER 1
|
||||
# else
|
||||
# define ZSTD_MEMORY_SANITIZER 0
|
||||
# endif
|
||||
#endif
|
||||
/*-**************************************************************
|
||||
* Alignment check
|
||||
*****************************************************************/
|
||||
|
||||
/* this test was initially positioned in mem.h,
|
||||
* but this file is removed (or replaced) for linux kernel
|
||||
* so it's now hosted in compiler.h,
|
||||
* which remains valid for both user & kernel spaces.
|
||||
*/
|
||||
|
||||
#ifndef ZSTD_ALIGNOF
|
||||
# if defined(__GNUC__) || defined(_MSC_VER)
|
||||
/* covers gcc, clang & MSVC */
|
||||
/* note : this section must come first, before C11,
|
||||
* due to a limitation in the kernel source generator */
|
||||
# define ZSTD_ALIGNOF(T) __alignof(T)
|
||||
|
||||
# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
||||
/* C11 support */
|
||||
# include <stdalign.h>
|
||||
# define ZSTD_ALIGNOF(T) alignof(T)
|
||||
|
||||
/* detects whether we are being compiled undef dfsan */
|
||||
#ifndef ZSTD_DATAFLOW_SANITIZER
|
||||
# if __has_feature(dataflow_sanitizer)
|
||||
# define ZSTD_DATAFLOW_SANITIZER 1
|
||||
# else
|
||||
# define ZSTD_DATAFLOW_SANITIZER 0
|
||||
/* No known support for alignof() - imperfect backup */
|
||||
# define ZSTD_ALIGNOF(T) (sizeof(void*) < sizeof(T) ? sizeof(void*) : sizeof(T))
|
||||
|
||||
# endif
|
||||
#endif
|
||||
#endif /* ZSTD_ALIGNOF */
|
||||
|
||||
/*-**************************************************************
|
||||
* Sanitizer
|
||||
*****************************************************************/
|
||||
|
||||
#if ZSTD_MEMORY_SANITIZER
|
||||
/* Not all platforms that support msan provide sanitizers/msan_interface.h.
|
||||
@@ -296,17 +294,6 @@ void __msan_poison(const volatile void *a, size_t size);
|
||||
intptr_t __msan_test_shadow(const volatile void *x, size_t size);
|
||||
#endif
|
||||
|
||||
/* detects whether we are being compiled under asan */
|
||||
#ifndef ZSTD_ADDRESS_SANITIZER
|
||||
# if __has_feature(address_sanitizer)
|
||||
# define ZSTD_ADDRESS_SANITIZER 1
|
||||
# elif defined(__SANITIZE_ADDRESS__)
|
||||
# define ZSTD_ADDRESS_SANITIZER 1
|
||||
# else
|
||||
# define ZSTD_ADDRESS_SANITIZER 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ZSTD_ADDRESS_SANITIZER
|
||||
/* Not all platforms that support asan provide sanitizers/asan_interface.h.
|
||||
* We therefore declare the functions we need ourselves, rather than trying to
|
||||
|
||||
@@ -43,8 +43,14 @@ static U32 FSE_ctz(U32 val)
|
||||
assert(val != 0);
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
unsigned long r=0;
|
||||
return _BitScanForward(&r, val) ? (unsigned)r : 0;
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanForward(&r, val);
|
||||
return (unsigned)r;
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
|
||||
return __builtin_ctz(val);
|
||||
# elif defined(__ICCARM__) /* IAR Intrinsic */
|
||||
@@ -217,7 +223,7 @@ static size_t FSE_readNCount_body_default(
|
||||
}
|
||||
|
||||
#if DYNAMIC_BMI2
|
||||
TARGET_ATTRIBUTE("bmi2") static size_t FSE_readNCount_body_bmi2(
|
||||
BMI2_TARGET_ATTRIBUTE static size_t FSE_readNCount_body_bmi2(
|
||||
short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
|
||||
const void* headerBuffer, size_t hbSize)
|
||||
{
|
||||
@@ -337,7 +343,7 @@ static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* r
|
||||
}
|
||||
|
||||
#if DYNAMIC_BMI2
|
||||
static TARGET_ATTRIBUTE("bmi2") size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
static BMI2_TARGET_ATTRIBUTE size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||
const void* src, size_t srcSize,
|
||||
void* workSpace, size_t wkspSize)
|
||||
|
||||
@@ -365,7 +365,7 @@ static size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, co
|
||||
}
|
||||
|
||||
#if DYNAMIC_BMI2
|
||||
TARGET_ATTRIBUTE("bmi2") static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
|
||||
BMI2_TARGET_ATTRIBUTE static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
|
||||
{
|
||||
return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ extern "C" {
|
||||
# include <stdint.h> /* intptr_t */
|
||||
# endif
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint8_t U8;
|
||||
typedef int8_t S8;
|
||||
typedef uint16_t U16;
|
||||
typedef int16_t S16;
|
||||
typedef uint32_t U32;
|
||||
@@ -63,6 +65,8 @@ extern "C" {
|
||||
# error "this implementation requires char to be exactly 8-bit type"
|
||||
#endif
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned char U8;
|
||||
typedef signed char S8;
|
||||
#if USHRT_MAX != 65535
|
||||
# error "this implementation requires short to be exactly 16-bit type"
|
||||
#endif
|
||||
|
||||
+11
-6
@@ -86,7 +86,7 @@ static void* POOL_thread(void* opaque) {
|
||||
{ POOL_job const job = ctx->queue[ctx->queueHead];
|
||||
ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
|
||||
ctx->numThreadsBusy++;
|
||||
ctx->queueEmpty = ctx->queueHead == ctx->queueTail;
|
||||
ctx->queueEmpty = (ctx->queueHead == ctx->queueTail);
|
||||
/* Unlock the mutex, signal a pusher, and run the job */
|
||||
ZSTD_pthread_cond_signal(&ctx->queuePushCond);
|
||||
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||
@@ -105,6 +105,7 @@ static void* POOL_thread(void* opaque) {
|
||||
assert(0); /* Unreachable */
|
||||
}
|
||||
|
||||
/* ZSTD_createThreadPool() : public access point */
|
||||
POOL_ctx* ZSTD_createThreadPool(size_t numThreads) {
|
||||
return POOL_create (numThreads, 0);
|
||||
}
|
||||
@@ -114,7 +115,8 @@ POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
|
||||
}
|
||||
|
||||
POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
|
||||
ZSTD_customMem customMem) {
|
||||
ZSTD_customMem customMem)
|
||||
{
|
||||
POOL_ctx* ctx;
|
||||
/* Check parameters */
|
||||
if (!numThreads) { return NULL; }
|
||||
@@ -192,7 +194,7 @@ void ZSTD_freeThreadPool (ZSTD_threadPool* pool) {
|
||||
POOL_free (pool);
|
||||
}
|
||||
|
||||
size_t POOL_sizeof(POOL_ctx *ctx) {
|
||||
size_t POOL_sizeof(const POOL_ctx* ctx) {
|
||||
if (ctx==NULL) return 0; /* supports sizeof NULL */
|
||||
return sizeof(*ctx)
|
||||
+ ctx->queueSize * sizeof(POOL_job)
|
||||
@@ -257,7 +259,8 @@ static int isQueueFull(POOL_ctx const* ctx) {
|
||||
}
|
||||
|
||||
|
||||
static void POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
|
||||
static void
|
||||
POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
|
||||
{
|
||||
POOL_job const job = {function, opaque};
|
||||
assert(ctx != NULL);
|
||||
@@ -313,7 +316,9 @@ POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
|
||||
return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
|
||||
}
|
||||
|
||||
POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem) {
|
||||
POOL_ctx*
|
||||
POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem)
|
||||
{
|
||||
(void)numThreads;
|
||||
(void)queueSize;
|
||||
(void)customMem;
|
||||
@@ -341,7 +346,7 @@ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t POOL_sizeof(POOL_ctx* ctx) {
|
||||
size_t POOL_sizeof(const POOL_ctx* ctx) {
|
||||
if (ctx==NULL) return 0; /* supports sizeof NULL */
|
||||
assert(ctx == &g_poolCtx);
|
||||
return sizeof(*ctx);
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ int POOL_resize(POOL_ctx* ctx, size_t numThreads);
|
||||
* @return threadpool memory usage
|
||||
* note : compatible with NULL (returns 0 in this case)
|
||||
*/
|
||||
size_t POOL_sizeof(POOL_ctx* ctx);
|
||||
size_t POOL_sizeof(const POOL_ctx* ctx);
|
||||
|
||||
/*! POOL_function :
|
||||
* The function type that can be added to a thread pool.
|
||||
@@ -70,7 +70,7 @@ void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque);
|
||||
|
||||
|
||||
/*! POOL_tryAdd() :
|
||||
* Add the job `function(opaque)` to thread pool _if_ a worker is available.
|
||||
* Add the job `function(opaque)` to thread pool _if_ a queue slot is available.
|
||||
* Returns immediately even if not (does not block).
|
||||
* @return : 1 if successful, 0 if not.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#ifndef ZSTD_PORTABILITY_MACROS_H
|
||||
#define ZSTD_PORTABILITY_MACROS_H
|
||||
|
||||
/**
|
||||
* This header file contains macro defintions to support portability.
|
||||
* This header is shared between C and ASM code, so it MUST only
|
||||
* contain macro definitions. It MUST not contain any C code.
|
||||
*
|
||||
* This header ONLY defines macros to detect platforms/feature support.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* compat. with non-clang compilers */
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
/* compat. with non-clang compilers */
|
||||
#ifndef __has_builtin
|
||||
# define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
/* compat. with non-clang compilers */
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
/* detects whether we are being compiled under msan */
|
||||
#ifndef ZSTD_MEMORY_SANITIZER
|
||||
# if __has_feature(memory_sanitizer)
|
||||
# define ZSTD_MEMORY_SANITIZER 1
|
||||
# else
|
||||
# define ZSTD_MEMORY_SANITIZER 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* detects whether we are being compiled under asan */
|
||||
#ifndef ZSTD_ADDRESS_SANITIZER
|
||||
# if __has_feature(address_sanitizer)
|
||||
# define ZSTD_ADDRESS_SANITIZER 1
|
||||
# elif defined(__SANITIZE_ADDRESS__)
|
||||
# define ZSTD_ADDRESS_SANITIZER 1
|
||||
# else
|
||||
# define ZSTD_ADDRESS_SANITIZER 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* detects whether we are being compiled under dfsan */
|
||||
#ifndef ZSTD_DATAFLOW_SANITIZER
|
||||
# if __has_feature(dataflow_sanitizer)
|
||||
# define ZSTD_DATAFLOW_SANITIZER 1
|
||||
# else
|
||||
# define ZSTD_DATAFLOW_SANITIZER 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Enable runtime BMI2 dispatch based on the CPU.
|
||||
* Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
|
||||
*/
|
||||
#ifndef DYNAMIC_BMI2
|
||||
#if ((defined(__clang__) && __has_attribute(__target__)) \
|
||||
|| (defined(__GNUC__) \
|
||||
&& (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
|
||||
&& (defined(__x86_64__) || defined(_M_X64)) \
|
||||
&& !defined(__BMI2__)
|
||||
# define DYNAMIC_BMI2 1
|
||||
#else
|
||||
# define DYNAMIC_BMI2 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Only enable assembly for GNUC comptabile compilers,
|
||||
* because other platforms may not support GAS assembly syntax.
|
||||
*
|
||||
* Only enable assembly for Linux / MacOS, other platforms may
|
||||
* work, but they haven't been tested. This could likely be
|
||||
* extended to BSD systems.
|
||||
*
|
||||
* Disable assembly when MSAN is enabled, because MSAN requires
|
||||
* 100% of code to be instrumented to work.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
# if defined(__linux__) || defined(__linux) || defined(__APPLE__)
|
||||
# if ZSTD_MEMORY_SANITIZER
|
||||
# define ZSTD_ASM_SUPPORTED 0
|
||||
# elif ZSTD_DATAFLOW_SANITIZER
|
||||
# define ZSTD_ASM_SUPPORTED 0
|
||||
# else
|
||||
# define ZSTD_ASM_SUPPORTED 1
|
||||
# endif
|
||||
# else
|
||||
# define ZSTD_ASM_SUPPORTED 0
|
||||
# endif
|
||||
#else
|
||||
# define ZSTD_ASM_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Determines whether we should enable assembly for x86-64
|
||||
* with BMI2.
|
||||
*
|
||||
* Enable if all of the following conditions hold:
|
||||
* - ASM hasn't been explicitly disabled by defining ZSTD_DISABLE_ASM
|
||||
* - Assembly is supported
|
||||
* - We are compiling for x86-64 and either:
|
||||
* - DYNAMIC_BMI2 is enabled
|
||||
* - BMI2 is supported at compile time
|
||||
*/
|
||||
#if !defined(ZSTD_DISABLE_ASM) && \
|
||||
ZSTD_ASM_SUPPORTED && \
|
||||
defined(__x86_64__) && \
|
||||
(DYNAMIC_BMI2 || defined(__BMI2__))
|
||||
# define ZSTD_ENABLE_ASM_X86_64_BMI2 1
|
||||
#else
|
||||
# define ZSTD_ENABLE_ASM_X86_64_BMI2 0
|
||||
#endif
|
||||
|
||||
#endif /* ZSTD_PORTABILITY_MACROS_H */
|
||||
+6
-806
@@ -5,7 +5,7 @@
|
||||
* You can contact the author at :
|
||||
* - xxHash homepage: http://www.xxhash.com
|
||||
* - xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||
*
|
||||
*
|
||||
* 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).
|
||||
@@ -13,812 +13,12 @@
|
||||
*/
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Tuning parameters
|
||||
***************************************/
|
||||
/*!XXH_FORCE_MEMORY_ACCESS :
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method doesn't depend on compiler but violate C standard.
|
||||
* It can generate buggy code on targets which do not support unaligned memory accesses.
|
||||
* But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://stackoverflow.com/a/32095106/646947 for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
|
||||
/*
|
||||
* xxhash.c instantiates functions defined in xxhash.h
|
||||
*/
|
||||
#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \
|
||||
defined(__ICCARM__)
|
||||
# define XXH_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*!XXH_ACCEPT_NULL_INPUT_POINTER :
|
||||
* If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
|
||||
* When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
|
||||
* By default, this option is disabled. To enable it, uncomment below define :
|
||||
*/
|
||||
/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
|
||||
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
|
||||
#define XXH_IMPLEMENTATION /* access definitions */
|
||||
|
||||
/*!XXH_FORCE_NATIVE_FORMAT :
|
||||
* By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
|
||||
* Results are therefore identical for little-endian and big-endian CPU.
|
||||
* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
|
||||
* Should endian-independence be of no importance for your application, you may set the #define below to 1,
|
||||
* to improve speed for Big-endian CPU.
|
||||
* This option has no impact on Little_Endian CPU.
|
||||
*/
|
||||
#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */
|
||||
# define XXH_FORCE_NATIVE_FORMAT 0
|
||||
#endif
|
||||
|
||||
/*!XXH_FORCE_ALIGN_CHECK :
|
||||
* This is a minor performance trick, only useful with lots of very small keys.
|
||||
* It means : check for aligned/unaligned input.
|
||||
* The check costs one initial branch per hash; set to 0 when the input data
|
||||
* is guaranteed to be aligned.
|
||||
*/
|
||||
#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
|
||||
# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
# define XXH_FORCE_ALIGN_CHECK 0
|
||||
# else
|
||||
# define XXH_FORCE_ALIGN_CHECK 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Includes & Memory related functions
|
||||
***************************************/
|
||||
/* Modify the local functions below should you wish to use some other memory routines */
|
||||
/* for ZSTD_malloc(), ZSTD_free() */
|
||||
#define ZSTD_DEPS_NEED_MALLOC
|
||||
#include "zstd_deps.h" /* size_t, ZSTD_malloc, ZSTD_free, ZSTD_memcpy */
|
||||
static void* XXH_malloc(size_t s) { return ZSTD_malloc(s); }
|
||||
static void XXH_free (void* p) { ZSTD_free(p); }
|
||||
static void* XXH_memcpy(void* dest, const void* src, size_t size) { return ZSTD_memcpy(dest,src,size); }
|
||||
|
||||
#ifndef XXH_STATIC_LINKING_ONLY
|
||||
# define XXH_STATIC_LINKING_ONLY
|
||||
#endif
|
||||
#include "xxhash.h"
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Compiler Specific Options
|
||||
***************************************/
|
||||
#include "compiler.h"
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Basic Types
|
||||
***************************************/
|
||||
#include "mem.h" /* BYTE, U32, U64, size_t */
|
||||
|
||||
#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
|
||||
|
||||
/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
|
||||
static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign;
|
||||
|
||||
static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
|
||||
#else
|
||||
|
||||
/* portable and safe solution. Generally efficient.
|
||||
* see : http://stackoverflow.com/a/32095106/646947
|
||||
*/
|
||||
|
||||
static U32 XXH_read32(const void* memPtr)
|
||||
{
|
||||
U32 val;
|
||||
ZSTD_memcpy(&val, memPtr, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static U64 XXH_read64(const void* memPtr)
|
||||
{
|
||||
U64 val;
|
||||
ZSTD_memcpy(&val, memPtr, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* Compiler-specific Functions and Macros
|
||||
******************************************/
|
||||
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
|
||||
/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
|
||||
#if defined(_MSC_VER)
|
||||
# define XXH_rotl32(x,r) _rotl(x,r)
|
||||
# define XXH_rotl64(x,r) _rotl64(x,r)
|
||||
#else
|
||||
#if defined(__ICCARM__)
|
||||
# include <intrinsics.h>
|
||||
# define XXH_rotl32(x,r) __ROR(x,(32 - r))
|
||||
#else
|
||||
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
#endif
|
||||
# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
# define XXH_swap32 _byteswap_ulong
|
||||
# define XXH_swap64 _byteswap_uint64
|
||||
#elif GCC_VERSION >= 403
|
||||
# define XXH_swap32 __builtin_bswap32
|
||||
# define XXH_swap64 __builtin_bswap64
|
||||
#else
|
||||
static U32 XXH_swap32 (U32 x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
((x >> 8) & 0x0000ff00 ) |
|
||||
((x >> 24) & 0x000000ff );
|
||||
}
|
||||
static U64 XXH_swap64 (U64 x)
|
||||
{
|
||||
return ((x << 56) & 0xff00000000000000ULL) |
|
||||
((x << 40) & 0x00ff000000000000ULL) |
|
||||
((x << 24) & 0x0000ff0000000000ULL) |
|
||||
((x << 8) & 0x000000ff00000000ULL) |
|
||||
((x >> 8) & 0x00000000ff000000ULL) |
|
||||
((x >> 24) & 0x0000000000ff0000ULL) |
|
||||
((x >> 40) & 0x000000000000ff00ULL) |
|
||||
((x >> 56) & 0x00000000000000ffULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Architecture Macros
|
||||
***************************************/
|
||||
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
|
||||
|
||||
/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */
|
||||
#ifndef XXH_CPU_LITTLE_ENDIAN
|
||||
static const int g_one = 1;
|
||||
# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one))
|
||||
#endif
|
||||
|
||||
|
||||
/* ***************************
|
||||
* Memory reads
|
||||
*****************************/
|
||||
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
|
||||
|
||||
FORCE_INLINE_TEMPLATE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
static U32 XXH_readBE32(const void* ptr)
|
||||
{
|
||||
return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
static U64 XXH_readBE64(const void* ptr)
|
||||
{
|
||||
return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
|
||||
}
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Macros
|
||||
***************************************/
|
||||
#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
static const U32 PRIME32_1 = 2654435761U;
|
||||
static const U32 PRIME32_2 = 2246822519U;
|
||||
static const U32 PRIME32_3 = 3266489917U;
|
||||
static const U32 PRIME32_4 = 668265263U;
|
||||
static const U32 PRIME32_5 = 374761393U;
|
||||
|
||||
static const U64 PRIME64_1 = 11400714785074694791ULL;
|
||||
static const U64 PRIME64_2 = 14029467366897019727ULL;
|
||||
static const U64 PRIME64_3 = 1609587929392839161ULL;
|
||||
static const U64 PRIME64_4 = 9650029242287828579ULL;
|
||||
static const U64 PRIME64_5 = 2870177450012600261ULL;
|
||||
|
||||
XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
|
||||
|
||||
|
||||
/* **************************
|
||||
* Utils
|
||||
****************************/
|
||||
XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dstState, const XXH32_state_t* restrict srcState)
|
||||
{
|
||||
ZSTD_memcpy(dstState, srcState, sizeof(*dstState));
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dstState, const XXH64_state_t* restrict srcState)
|
||||
{
|
||||
ZSTD_memcpy(dstState, srcState, sizeof(*dstState));
|
||||
}
|
||||
|
||||
|
||||
/* ***************************
|
||||
* Simple Hash Functions
|
||||
*****************************/
|
||||
|
||||
static U32 XXH32_round(U32 seed, U32 input)
|
||||
{
|
||||
seed += input * PRIME32_2;
|
||||
seed = XXH_rotl32(seed, 13);
|
||||
seed *= PRIME32_1;
|
||||
return seed;
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
U32 h32;
|
||||
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL) {
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)16;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=16) {
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
U32 v2 = seed + PRIME32_2;
|
||||
U32 v3 = seed + 0;
|
||||
U32 v4 = seed - PRIME32_1;
|
||||
|
||||
do {
|
||||
v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4;
|
||||
v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4;
|
||||
v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4;
|
||||
v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4;
|
||||
} while (p<=limit);
|
||||
|
||||
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
|
||||
} else {
|
||||
h32 = seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) len;
|
||||
|
||||
while (p+4<=bEnd) {
|
||||
h32 += XXH_get32bits(p) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd) {
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed)
|
||||
{
|
||||
#if 0
|
||||
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
|
||||
XXH32_CREATESTATE_STATIC(state);
|
||||
XXH32_reset(state, seed);
|
||||
XXH32_update(state, input, len);
|
||||
return XXH32_digest(state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if (XXH_FORCE_ALIGN_CHECK) {
|
||||
if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
} }
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static U64 XXH64_round(U64 acc, U64 input)
|
||||
{
|
||||
acc += input * PRIME64_2;
|
||||
acc = XXH_rotl64(acc, 31);
|
||||
acc *= PRIME64_1;
|
||||
return acc;
|
||||
}
|
||||
|
||||
static U64 XXH64_mergeRound(U64 acc, U64 val)
|
||||
{
|
||||
val = XXH64_round(0, val);
|
||||
acc ^= val;
|
||||
acc = acc * PRIME64_1 + PRIME64_4;
|
||||
return acc;
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
U64 h64;
|
||||
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL) {
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)32;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=32) {
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
U64 v2 = seed + PRIME64_2;
|
||||
U64 v3 = seed + 0;
|
||||
U64 v4 = seed - PRIME64_1;
|
||||
|
||||
do {
|
||||
v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8;
|
||||
v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8;
|
||||
v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8;
|
||||
v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8;
|
||||
} while (p<=limit);
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
h64 = XXH64_mergeRound(h64, v1);
|
||||
h64 = XXH64_mergeRound(h64, v2);
|
||||
h64 = XXH64_mergeRound(h64, v3);
|
||||
h64 = XXH64_mergeRound(h64, v4);
|
||||
|
||||
} else {
|
||||
h64 = seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) len;
|
||||
|
||||
while (p+8<=bEnd) {
|
||||
U64 const k1 = XXH64_round(0, XXH_get64bits(p));
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd) {
|
||||
h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd) {
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
|
||||
{
|
||||
#if 0
|
||||
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
|
||||
XXH64_CREATESTATE_STATIC(state);
|
||||
XXH64_reset(state, seed);
|
||||
XXH64_update(state, input, len);
|
||||
return XXH64_digest(state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if (XXH_FORCE_ALIGN_CHECK) {
|
||||
if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
} }
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* **************************************************
|
||||
* Advanced Hash Functions
|
||||
****************************************************/
|
||||
|
||||
XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)
|
||||
{
|
||||
return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
|
||||
}
|
||||
XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
|
||||
{
|
||||
return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
|
||||
}
|
||||
XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
/*** Hash feed ***/
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed)
|
||||
{
|
||||
XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
|
||||
ZSTD_memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */
|
||||
state.v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
state.v2 = seed + PRIME32_2;
|
||||
state.v3 = seed + 0;
|
||||
state.v4 = seed - PRIME32_1;
|
||||
ZSTD_memcpy(statePtr, &state, sizeof(state));
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed)
|
||||
{
|
||||
XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
|
||||
ZSTD_memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */
|
||||
state.v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
state.v2 = seed + PRIME64_2;
|
||||
state.v3 = seed + 0;
|
||||
state.v4 = seed - PRIME64_1;
|
||||
ZSTD_memcpy(statePtr, &state, sizeof(state));
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len_32 += (unsigned)len;
|
||||
state->large_len |= (len>=16) | (state->total_len_32>=16);
|
||||
|
||||
if (state->memsize + len < 16) { /* fill in tmp buffer */
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
|
||||
state->memsize += (unsigned)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) { /* some data left from previous update */
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
|
||||
{ const U32* p32 = state->mem32;
|
||||
state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++;
|
||||
state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++;
|
||||
state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++;
|
||||
state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); p32++;
|
||||
}
|
||||
p += 16-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p <= bEnd-16) {
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = state->v1;
|
||||
U32 v2 = state->v2;
|
||||
U32 v3 = state->v3;
|
||||
U32 v4 = state->v4;
|
||||
|
||||
do {
|
||||
v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4;
|
||||
v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4;
|
||||
v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4;
|
||||
v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4;
|
||||
} while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd) {
|
||||
XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));
|
||||
state->memsize = (unsigned)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian)
|
||||
{
|
||||
const BYTE * p = (const BYTE*)state->mem32;
|
||||
const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize;
|
||||
U32 h32;
|
||||
|
||||
if (state->large_len) {
|
||||
h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
|
||||
} else {
|
||||
h32 = state->v3 /* == seed */ + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += state->total_len_32;
|
||||
|
||||
while (p+4<=bEnd) {
|
||||
h32 += XXH_readLE32(p, endian) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd) {
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* **** XXH64 **** */
|
||||
|
||||
FORCE_INLINE_TEMPLATE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 32) { /* fill in tmp buffer */
|
||||
if (input != NULL) {
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
|
||||
}
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) { /* tmp buffer is full */
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
|
||||
state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian));
|
||||
state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian));
|
||||
state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian));
|
||||
state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian));
|
||||
p += 32-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p+32 <= bEnd) {
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
do {
|
||||
v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8;
|
||||
v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8;
|
||||
v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8;
|
||||
v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8;
|
||||
} while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd) {
|
||||
XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));
|
||||
state->memsize = (unsigned)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian)
|
||||
{
|
||||
const BYTE * p = (const BYTE*)state->mem64;
|
||||
const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize;
|
||||
U64 h64;
|
||||
|
||||
if (state->total_len >= 32) {
|
||||
U64 const v1 = state->v1;
|
||||
U64 const v2 = state->v2;
|
||||
U64 const v3 = state->v3;
|
||||
U64 const v4 = state->v4;
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
h64 = XXH64_mergeRound(h64, v1);
|
||||
h64 = XXH64_mergeRound(h64, v2);
|
||||
h64 = XXH64_mergeRound(h64, v3);
|
||||
h64 = XXH64_mergeRound(h64, v4);
|
||||
} else {
|
||||
h64 = state->v3 + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) state->total_len;
|
||||
|
||||
while (p+8<=bEnd) {
|
||||
U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian));
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd) {
|
||||
h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd) {
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
/* **************************
|
||||
* Canonical representation
|
||||
****************************/
|
||||
|
||||
/*! Default XXH result types are basic unsigned 32 and 64 bits.
|
||||
* The canonical representation follows human-readable write convention, aka big-endian (large digits first).
|
||||
* These functions allow transformation of hash result into and from its canonical format.
|
||||
* This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs.
|
||||
*/
|
||||
|
||||
XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
|
||||
if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
|
||||
ZSTD_memcpy(dst, &hash, sizeof(*dst));
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
|
||||
if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
|
||||
ZSTD_memcpy(dst, &hash, sizeof(*dst));
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
|
||||
{
|
||||
return XXH_readBE32(src);
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)
|
||||
{
|
||||
return XXH_readBE64(src);
|
||||
}
|
||||
|
||||
+5573
-172
File diff suppressed because it is too large
Load Diff
+57
-21
@@ -20,6 +20,7 @@
|
||||
* Dependencies
|
||||
***************************************/
|
||||
#include "compiler.h"
|
||||
#include "cpu.h"
|
||||
#include "mem.h"
|
||||
#include "debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */
|
||||
#include "error_private.h"
|
||||
@@ -57,6 +58,7 @@ extern "C" {
|
||||
#undef MAX
|
||||
#define MIN(a,b) ((a)<(b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a)>(b) ? (a) : (b))
|
||||
#define BOUNDED(min,val,max) (MAX(min,MIN(val,max)))
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -65,7 +67,6 @@ extern "C" {
|
||||
#define ZSTD_OPT_NUM (1<<12)
|
||||
|
||||
#define ZSTD_REP_NUM 3 /* number of repcodes */
|
||||
#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1)
|
||||
static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
|
||||
|
||||
#define KB *(1 <<10)
|
||||
@@ -117,7 +118,7 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
|
||||
/* Each table cannot take more than #symbols * FSELog bits */
|
||||
#define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8)
|
||||
|
||||
static UNUSED_ATTR const U32 LL_bits[MaxLL+1] = {
|
||||
static UNUSED_ATTR const U8 LL_bits[MaxLL+1] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 2, 2, 3, 3,
|
||||
@@ -134,7 +135,7 @@ static UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = {
|
||||
#define LL_DEFAULTNORMLOG 6 /* for static allocation */
|
||||
static UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
|
||||
|
||||
static UNUSED_ATTR const U32 ML_bits[MaxML+1] = {
|
||||
static UNUSED_ATTR const U8 ML_bits[MaxML+1] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -175,13 +176,24 @@ 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; }
|
||||
|
||||
/* 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
|
||||
literal buffer is, there can be partial overlaps in this call on the final
|
||||
copy if the literal is being shifted by less than 16 bytes. */
|
||||
static void ZSTD_copy16(void* dst, const void* src) {
|
||||
#if defined(ZSTD_ARCH_ARM_NEON)
|
||||
vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src));
|
||||
#elif defined(ZSTD_ARCH_X86_SSE2)
|
||||
_mm_storeu_si128((__m128i*)dst, _mm_loadu_si128((const __m128i*)src));
|
||||
#elif defined(__clang__)
|
||||
ZSTD_memmove(dst, src, 16);
|
||||
#else
|
||||
ZSTD_memcpy(dst, src, 16);
|
||||
/* ZSTD_memmove is not inlined properly by gcc */
|
||||
BYTE copy16_buf[16];
|
||||
ZSTD_memcpy(copy16_buf, src, 16);
|
||||
ZSTD_memcpy(dst, copy16_buf, 16);
|
||||
#endif
|
||||
}
|
||||
#define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; }
|
||||
@@ -210,8 +222,6 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e
|
||||
BYTE* op = (BYTE*)dst;
|
||||
BYTE* const oend = op + length;
|
||||
|
||||
assert(diff >= 8 || (ovtype == ZSTD_no_overlap && diff <= -WILDCOPY_VECLEN));
|
||||
|
||||
if (ovtype == ZSTD_overlap_src_before_dst && diff < WILDCOPY_VECLEN) {
|
||||
/* Handle short offset copies. */
|
||||
do {
|
||||
@@ -274,9 +284,9 @@ typedef enum {
|
||||
* Private declarations
|
||||
*********************************************/
|
||||
typedef struct seqDef_s {
|
||||
U32 offset; /* offset == rawOffset + ZSTD_REP_NUM, or equivalently, offCode + 1 */
|
||||
U32 offBase; /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */
|
||||
U16 litLength;
|
||||
U16 matchLength;
|
||||
U16 mlBase; /* mlBase == matchLength - MINMATCH */
|
||||
} seqDef;
|
||||
|
||||
/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */
|
||||
@@ -318,7 +328,7 @@ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore
|
||||
{
|
||||
ZSTD_sequenceLength seqLen;
|
||||
seqLen.litLength = seq->litLength;
|
||||
seqLen.matchLength = seq->matchLength + MINMATCH;
|
||||
seqLen.matchLength = seq->mlBase + MINMATCH;
|
||||
if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) {
|
||||
if (seqStore->longLengthType == ZSTD_llt_literalLength) {
|
||||
seqLen.litLength += 0xFFFF;
|
||||
@@ -358,8 +368,14 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus
|
||||
# if STATIC_BMI2 == 1
|
||||
return _lzcnt_u32(val)^31;
|
||||
# else
|
||||
unsigned long r=0;
|
||||
return _BitScanReverse(&r, val) ? (unsigned)r : 0;
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanReverse(&r, val);
|
||||
return (unsigned)r;
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# endif
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
|
||||
return __builtin_clz (val) ^ 31;
|
||||
@@ -379,10 +395,10 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes CTZ on a U64.
|
||||
* This will be slow on 32-bit mode, and on unsupported compilers.
|
||||
* If you need this function to be fast (because it is hot) expand
|
||||
* support.
|
||||
* Counts the number of trailing zeros of a `size_t`.
|
||||
* Most compilers should support CTZ as a builtin. A backup
|
||||
* implementation is provided if the builtin isn't supported, but
|
||||
* it may not be terribly efficient.
|
||||
*/
|
||||
MEM_STATIC unsigned ZSTD_countTrailingZeros(size_t val)
|
||||
{
|
||||
@@ -391,8 +407,14 @@ MEM_STATIC unsigned ZSTD_countTrailingZeros(size_t val)
|
||||
# if STATIC_BMI2
|
||||
return _tzcnt_u64(val);
|
||||
# else
|
||||
unsigned long r = 0;
|
||||
return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0;
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanForward64(&r, (U64)val);
|
||||
return (unsigned)r;
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# endif
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
return __builtin_ctzll((U64)val);
|
||||
@@ -409,10 +431,16 @@ MEM_STATIC unsigned ZSTD_countTrailingZeros(size_t val)
|
||||
# endif
|
||||
} else { /* 32 bits */
|
||||
# if defined(_MSC_VER)
|
||||
unsigned long r=0;
|
||||
return _BitScanForward( &r, (U32)val ) ? (unsigned)(r >> 3) : 0;
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanForward(&r, (U32)val);
|
||||
return (unsigned)r;
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (__builtin_ctz((U32)val) >> 3);
|
||||
return __builtin_ctz((U32)val);
|
||||
# else
|
||||
static const int DeBruijnBytePos[32] = { 0, 1, 28, 2, 29, 14, 24, 3,
|
||||
30, 22, 20, 15, 25, 17, 4, 8,
|
||||
@@ -449,6 +477,14 @@ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
|
||||
size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
/**
|
||||
* @returns true iff the CPU supports dynamic BMI2 dispatch.
|
||||
*/
|
||||
MEM_STATIC int ZSTD_cpuSupportsBmi2(void)
|
||||
{
|
||||
ZSTD_cpuid_t cpuid = ZSTD_cpuid();
|
||||
return ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid);
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#ifndef ZSTD_CLEVELS_H
|
||||
#define ZSTD_CLEVELS_H
|
||||
|
||||
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */
|
||||
#include "../zstd.h"
|
||||
|
||||
/*-===== Pre-defined compression levels =====-*/
|
||||
|
||||
#define ZSTD_MAX_CLEVEL 22
|
||||
|
||||
#ifdef __GNUC__
|
||||
__attribute__((__unused__))
|
||||
#endif
|
||||
|
||||
static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
|
||||
{ /* "default" - for any srcSize > 256 KB */
|
||||
/* W, C, H, S, L, TL, strat */
|
||||
{ 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
|
||||
{ 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
|
||||
{ 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
|
||||
{ 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */
|
||||
{ 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */
|
||||
{ 21, 18, 19, 3, 5, 2, ZSTD_greedy }, /* level 5 */
|
||||
{ 21, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6 */
|
||||
{ 21, 19, 20, 4, 5, 8, ZSTD_lazy }, /* level 7 */
|
||||
{ 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 8 */
|
||||
{ 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 11 */
|
||||
{ 22, 22, 23, 6, 5, 32, ZSTD_lazy2 }, /* level 12 */
|
||||
{ 22, 22, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */
|
||||
{ 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
|
||||
{ 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
|
||||
{ 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */
|
||||
{ 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */
|
||||
{ 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */
|
||||
{ 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */
|
||||
{ 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */
|
||||
{ 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */
|
||||
{ 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */
|
||||
},
|
||||
{ /* for srcSize <= 256 KB */
|
||||
/* W, C, H, S, L, T, strat */
|
||||
{ 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
||||
{ 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
|
||||
{ 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */
|
||||
{ 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */
|
||||
{ 18, 16, 17, 3, 5, 2, ZSTD_greedy }, /* level 4.*/
|
||||
{ 18, 17, 18, 5, 5, 2, ZSTD_greedy }, /* level 5.*/
|
||||
{ 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
|
||||
{ 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */
|
||||
{ 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
|
||||
{ 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/
|
||||
{ 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/
|
||||
{ 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */
|
||||
{ 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
|
||||
{ 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/
|
||||
{ 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/
|
||||
{ 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/
|
||||
{ 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/
|
||||
{ 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
|
||||
{ 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/
|
||||
{ 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/
|
||||
{ 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/
|
||||
},
|
||||
{ /* for srcSize <= 128 KB */
|
||||
/* W, C, H, S, L, T, strat */
|
||||
{ 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
||||
{ 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
|
||||
{ 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
|
||||
{ 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */
|
||||
{ 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */
|
||||
{ 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
|
||||
{ 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
|
||||
{ 17, 16, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
|
||||
{ 17, 16, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
|
||||
{ 17, 16, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 17, 16, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */
|
||||
{ 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */
|
||||
{ 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/
|
||||
{ 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
|
||||
{ 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/
|
||||
{ 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/
|
||||
{ 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/
|
||||
{ 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/
|
||||
{ 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/
|
||||
{ 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/
|
||||
{ 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
|
||||
{ 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/
|
||||
},
|
||||
{ /* for srcSize <= 16 KB */
|
||||
/* W, C, H, S, L, T, strat */
|
||||
{ 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
||||
{ 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
|
||||
{ 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
|
||||
{ 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */
|
||||
{ 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */
|
||||
{ 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
|
||||
{ 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
|
||||
{ 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */
|
||||
{ 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/
|
||||
{ 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/
|
||||
{ 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/
|
||||
{ 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/
|
||||
{ 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/
|
||||
{ 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/
|
||||
{ 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/
|
||||
{ 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/
|
||||
{ 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/
|
||||
{ 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/
|
||||
{ 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/
|
||||
{ 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
|
||||
{ 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/
|
||||
{ 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
|
||||
{ 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* ZSTD_CLEVELS_H */
|
||||
@@ -97,7 +97,7 @@ static size_t HUF_compressWeights(void* dst, size_t dstSize, const void* weightT
|
||||
|
||||
unsigned maxSymbolValue = HUF_TABLELOG_MAX;
|
||||
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
|
||||
HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, sizeof(U32));
|
||||
HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32));
|
||||
|
||||
if (workspaceSize < sizeof(HUF_CompressWeightsWksp)) return ERROR(GENERIC);
|
||||
|
||||
@@ -176,7 +176,7 @@ size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize,
|
||||
HUF_CElt const* const ct = CTable + 1;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
U32 n;
|
||||
HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, sizeof(U32));
|
||||
HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32));
|
||||
|
||||
/* check conditions */
|
||||
if (workspaceSize < sizeof(HUF_WriteCTableWksp)) return ERROR(GENERIC);
|
||||
@@ -471,8 +471,7 @@ static void HUF_swapNodes(nodeElt* a, nodeElt* b) {
|
||||
}
|
||||
|
||||
/* Returns 0 if the huffNode array is not sorted by descending count */
|
||||
UNUSED_ATTR
|
||||
static int HUF_isSorted(nodeElt huffNode[], U32 const maxSymbolValue1) {
|
||||
MEM_STATIC int HUF_isSorted(nodeElt huffNode[], U32 const maxSymbolValue1) {
|
||||
U32 i;
|
||||
for (i = 1; i < maxSymbolValue1; ++i) {
|
||||
if (huffNode[i].count > huffNode[i-1].count) {
|
||||
@@ -680,7 +679,7 @@ static void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, i
|
||||
|
||||
size_t HUF_buildCTable_wksp (HUF_CElt* CTable, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
|
||||
{
|
||||
HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)HUF_alignUpWorkspace(workSpace, &wkspSize, sizeof(U32));
|
||||
HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(U32));
|
||||
nodeElt* const huffNode0 = wksp_tables->huffNodeTbl;
|
||||
nodeElt* const huffNode = huffNode0+1;
|
||||
int nonNullRank;
|
||||
@@ -761,7 +760,7 @@ typedef struct {
|
||||
} HUF_CStream_t;
|
||||
|
||||
/**! HUF_initCStream():
|
||||
* Initializes the bistream.
|
||||
* Initializes the bitstream.
|
||||
* @returns 0 or an error code.
|
||||
*/
|
||||
static size_t HUF_initCStream(HUF_CStream_t* bitC,
|
||||
@@ -780,7 +779,7 @@ static size_t HUF_initCStream(HUF_CStream_t* bitC,
|
||||
*
|
||||
* @param elt The element we're adding. This is a (nbBits, value) pair.
|
||||
* See the HUF_CStream_t docs for the format.
|
||||
* @param idx Insert into the bistream at this idx.
|
||||
* @param idx Insert into the bitstream at this idx.
|
||||
* @param kFast This is a template parameter. If the bitstream is guaranteed
|
||||
* to have at least 4 unused bits after this call it may be 1,
|
||||
* otherwise it must be 0. HUF_addBits() is faster when fast is set.
|
||||
@@ -1030,7 +1029,7 @@ HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,
|
||||
|
||||
#if DYNAMIC_BMI2
|
||||
|
||||
static TARGET_ATTRIBUTE("bmi2") size_t
|
||||
static BMI2_TARGET_ATTRIBUTE size_t
|
||||
HUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
const HUF_CElt* CTable)
|
||||
@@ -1184,7 +1183,7 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
||||
HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
|
||||
const int bmi2, unsigned suspectUncompressible)
|
||||
{
|
||||
HUF_compress_tables_t* const table = (HUF_compress_tables_t*)HUF_alignUpWorkspace(workSpace, &wkspSize, sizeof(size_t));
|
||||
HUF_compress_tables_t* const table = (HUF_compress_tables_t*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(size_t));
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
BYTE* op = ostart;
|
||||
|
||||
+149
-249
@@ -12,7 +12,6 @@
|
||||
* Dependencies
|
||||
***************************************/
|
||||
#include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */
|
||||
#include "../common/cpu.h"
|
||||
#include "../common/mem.h"
|
||||
#include "hist.h" /* HIST_countFast_wksp */
|
||||
#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
|
||||
@@ -100,7 +99,7 @@ static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)
|
||||
assert(cctx != NULL);
|
||||
ZSTD_memset(cctx, 0, sizeof(*cctx));
|
||||
cctx->customMem = memManager;
|
||||
cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
||||
cctx->bmi2 = ZSTD_cpuSupportsBmi2();
|
||||
{ size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);
|
||||
assert(!ZSTD_isError(err));
|
||||
(void)err;
|
||||
@@ -723,36 +722,36 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
case ZSTD_c_windowLog :
|
||||
if (value!=0) /* 0 => use default */
|
||||
BOUNDCHECK(ZSTD_c_windowLog, value);
|
||||
CCtxParams->cParams.windowLog = (unsigned)value;
|
||||
CCtxParams->cParams.windowLog = (U32)value;
|
||||
return CCtxParams->cParams.windowLog;
|
||||
|
||||
case ZSTD_c_hashLog :
|
||||
if (value!=0) /* 0 => use default */
|
||||
BOUNDCHECK(ZSTD_c_hashLog, value);
|
||||
CCtxParams->cParams.hashLog = (unsigned)value;
|
||||
CCtxParams->cParams.hashLog = (U32)value;
|
||||
return CCtxParams->cParams.hashLog;
|
||||
|
||||
case ZSTD_c_chainLog :
|
||||
if (value!=0) /* 0 => use default */
|
||||
BOUNDCHECK(ZSTD_c_chainLog, value);
|
||||
CCtxParams->cParams.chainLog = (unsigned)value;
|
||||
CCtxParams->cParams.chainLog = (U32)value;
|
||||
return CCtxParams->cParams.chainLog;
|
||||
|
||||
case ZSTD_c_searchLog :
|
||||
if (value!=0) /* 0 => use default */
|
||||
BOUNDCHECK(ZSTD_c_searchLog, value);
|
||||
CCtxParams->cParams.searchLog = (unsigned)value;
|
||||
CCtxParams->cParams.searchLog = (U32)value;
|
||||
return (size_t)value;
|
||||
|
||||
case ZSTD_c_minMatch :
|
||||
if (value!=0) /* 0 => use default */
|
||||
BOUNDCHECK(ZSTD_c_minMatch, value);
|
||||
CCtxParams->cParams.minMatch = (unsigned)value;
|
||||
CCtxParams->cParams.minMatch = value;
|
||||
return CCtxParams->cParams.minMatch;
|
||||
|
||||
case ZSTD_c_targetLength :
|
||||
BOUNDCHECK(ZSTD_c_targetLength, value);
|
||||
CCtxParams->cParams.targetLength = (unsigned)value;
|
||||
CCtxParams->cParams.targetLength = value;
|
||||
return CCtxParams->cParams.targetLength;
|
||||
|
||||
case ZSTD_c_strategy :
|
||||
@@ -765,12 +764,12 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
/* Content size written in frame header _when known_ (default:1) */
|
||||
DEBUGLOG(4, "set content size flag = %u", (value!=0));
|
||||
CCtxParams->fParams.contentSizeFlag = value != 0;
|
||||
return (size_t)CCtxParams->fParams.contentSizeFlag;
|
||||
return CCtxParams->fParams.contentSizeFlag;
|
||||
|
||||
case ZSTD_c_checksumFlag :
|
||||
/* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
|
||||
CCtxParams->fParams.checksumFlag = value != 0;
|
||||
return (size_t)CCtxParams->fParams.checksumFlag;
|
||||
return CCtxParams->fParams.checksumFlag;
|
||||
|
||||
case ZSTD_c_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
|
||||
DEBUGLOG(4, "set dictIDFlag = %u", (value!=0));
|
||||
@@ -779,11 +778,11 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
|
||||
case ZSTD_c_forceMaxWindow :
|
||||
CCtxParams->forceWindow = (value != 0);
|
||||
return (size_t)CCtxParams->forceWindow;
|
||||
return CCtxParams->forceWindow;
|
||||
|
||||
case ZSTD_c_forceAttachDict : {
|
||||
const ZSTD_dictAttachPref_e pref = (ZSTD_dictAttachPref_e)value;
|
||||
BOUNDCHECK(ZSTD_c_forceAttachDict, (int)pref);
|
||||
BOUNDCHECK(ZSTD_c_forceAttachDict, pref);
|
||||
CCtxParams->attachDictPref = pref;
|
||||
return CCtxParams->attachDictPref;
|
||||
}
|
||||
@@ -866,8 +865,8 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
return CCtxParams->ldmParams.bucketSizeLog;
|
||||
|
||||
case ZSTD_c_ldmHashRateLog :
|
||||
RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
|
||||
parameter_outOfBound, "Param out of bounds!");
|
||||
if (value!=0) /* 0 ==> default */
|
||||
BOUNDCHECK(ZSTD_c_ldmHashRateLog, value);
|
||||
CCtxParams->ldmParams.hashRateLog = value;
|
||||
return CCtxParams->ldmParams.hashRateLog;
|
||||
|
||||
@@ -1076,7 +1075,7 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
|
||||
size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
|
||||
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
||||
@@ -1156,14 +1155,14 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
|
||||
size_t ZSTD_CCtx_loadDictionary_byReference(
|
||||
ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
|
||||
{
|
||||
return ZSTD_CCtx_loadDictionary_advanced(
|
||||
cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
|
||||
}
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
|
||||
size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
|
||||
{
|
||||
return ZSTD_CCtx_loadDictionary_advanced(
|
||||
cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
|
||||
@@ -1333,7 +1332,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
||||
break;
|
||||
case ZSTD_cpm_createCDict:
|
||||
/* Assume a small source size when creating a dictionary
|
||||
* with an unkown source size.
|
||||
* with an unknown source size.
|
||||
*/
|
||||
if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
|
||||
srcSize = minSrcSize;
|
||||
@@ -1465,7 +1464,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
const size_t buffOutSize,
|
||||
const U64 pledgedSrcSize)
|
||||
{
|
||||
size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << cParams->windowLog), pledgedSrcSize));
|
||||
size_t const windowSize = (size_t) BOUNDED(1ULL, 1ULL << cParams->windowLog, pledgedSrcSize);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
|
||||
U32 const divider = (cParams->minMatch==3) ? 3 : 4;
|
||||
size_t const maxNbSeq = blockSize / divider;
|
||||
@@ -1783,7 +1782,7 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
||||
if (ms->tagTable) ZSTD_memset(ms->tagTable, 0, tagTableSize);
|
||||
}
|
||||
{ /* Switch to 32-entry rows if searchLog is 5 (or more) */
|
||||
U32 const rowLog = MAX(MIN(cParams->searchLog, 6), 4);
|
||||
U32 const rowLog = BOUNDED(4, cParams->searchLog, 6);
|
||||
assert(cParams->hashLog >= rowLog);
|
||||
ms->rowHashLog = cParams->hashLog - rowLog;
|
||||
}
|
||||
@@ -1911,7 +1910,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
|
||||
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
|
||||
zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE);
|
||||
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
|
||||
RETURN_ERROR_IF(zc->entropyWorkspace == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
|
||||
} }
|
||||
|
||||
ZSTD_cwksp_clear(ws);
|
||||
@@ -2311,6 +2310,8 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
|
||||
int const nbRows = (int)size / ZSTD_ROWSIZE;
|
||||
int cellNb = 0;
|
||||
int rowNb;
|
||||
/* Protect special index values < ZSTD_WINDOW_START_INDEX. */
|
||||
U32 const reducerThreshold = reducerValue + ZSTD_WINDOW_START_INDEX;
|
||||
assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
|
||||
assert(size < (1U<<31)); /* can be casted to int */
|
||||
|
||||
@@ -2330,12 +2331,17 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
|
||||
for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
|
||||
int column;
|
||||
for (column=0; column<ZSTD_ROWSIZE; column++) {
|
||||
if (preserveMark) {
|
||||
U32 const adder = (table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) ? reducerValue : 0;
|
||||
table[cellNb] += adder;
|
||||
U32 newVal;
|
||||
if (preserveMark && table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) {
|
||||
/* This write is pointless, but is required(?) for the compiler
|
||||
* to auto-vectorize the loop. */
|
||||
newVal = ZSTD_DUBT_UNSORTED_MARK;
|
||||
} else if (table[cellNb] < reducerThreshold) {
|
||||
newVal = 0;
|
||||
} else {
|
||||
newVal = table[cellNb] - reducerValue;
|
||||
}
|
||||
if (table[cellNb] < reducerValue) table[cellNb] = 0;
|
||||
else table[cellNb] -= reducerValue;
|
||||
table[cellNb] = newVal;
|
||||
cellNb++;
|
||||
} }
|
||||
}
|
||||
@@ -2390,9 +2396,9 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
||||
assert(nbSeq <= seqStorePtr->maxNbSeq);
|
||||
for (u=0; u<nbSeq; u++) {
|
||||
U32 const llv = sequences[u].litLength;
|
||||
U32 const mlv = sequences[u].matchLength;
|
||||
U32 const mlv = sequences[u].mlBase;
|
||||
llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
|
||||
ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
|
||||
ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offBase);
|
||||
mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
|
||||
}
|
||||
if (seqStorePtr->longLengthType==ZSTD_llt_literalLength)
|
||||
@@ -2904,9 +2910,9 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
|
||||
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].offset - ZSTD_REP_NUM;
|
||||
U32 rawOffset = seqStoreSeqs[i].offBase - ZSTD_REP_NUM;
|
||||
outSeqs[i].litLength = seqStoreSeqs[i].litLength;
|
||||
outSeqs[i].matchLength = seqStoreSeqs[i].matchLength + MINMATCH;
|
||||
outSeqs[i].matchLength = seqStoreSeqs[i].mlBase + MINMATCH;
|
||||
outSeqs[i].rep = 0;
|
||||
|
||||
if (i == seqStore->longLengthPos) {
|
||||
@@ -2917,9 +2923,9 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
|
||||
}
|
||||
}
|
||||
|
||||
if (seqStoreSeqs[i].offset <= ZSTD_REP_NUM) {
|
||||
if (seqStoreSeqs[i].offBase <= ZSTD_REP_NUM) {
|
||||
/* Derive the correct offset corresponding to a repcode */
|
||||
outSeqs[i].rep = seqStoreSeqs[i].offset;
|
||||
outSeqs[i].rep = seqStoreSeqs[i].offBase;
|
||||
if (outSeqs[i].litLength != 0) {
|
||||
rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1];
|
||||
} else {
|
||||
@@ -2933,9 +2939,9 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
|
||||
outSeqs[i].offset = rawOffset;
|
||||
/* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode
|
||||
so we provide seqStoreSeqs[i].offset - 1 */
|
||||
updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep,
|
||||
seqStoreSeqs[i].offset - 1,
|
||||
seqStoreSeqs[i].litLength == 0);
|
||||
ZSTD_updateRep(updatedRepcodes.rep,
|
||||
seqStoreSeqs[i].offBase - 1,
|
||||
seqStoreSeqs[i].litLength == 0);
|
||||
literalsRead += outSeqs[i].litLength;
|
||||
}
|
||||
/* Insert last literals (if any exist) in the block as a sequence with ml == off == 0.
|
||||
@@ -3257,7 +3263,7 @@ static size_t ZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSiz
|
||||
static size_t ZSTD_estimateBlockSize_symbolType(symbolEncodingType_e type,
|
||||
const BYTE* codeTable, size_t nbSeq, unsigned maxCode,
|
||||
const FSE_CTable* fseCTable,
|
||||
const U32* additionalBits,
|
||||
const U8* additionalBits,
|
||||
short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
|
||||
void* workspace, size_t wkspSize)
|
||||
{
|
||||
@@ -3379,7 +3385,7 @@ static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore) {
|
||||
size_t i;
|
||||
for (i = 0; i < nbSeqs; ++i) {
|
||||
seqDef seq = seqStore->sequencesStart[i];
|
||||
matchBytes += seq.matchLength + MINMATCH;
|
||||
matchBytes += seq.mlBase + MINMATCH;
|
||||
if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_matchLength) {
|
||||
matchBytes += 0x10000;
|
||||
}
|
||||
@@ -3428,11 +3434,13 @@ static void ZSTD_deriveSeqStoreChunk(seqStore_t* resultSeqStore,
|
||||
|
||||
/**
|
||||
* Returns the raw offset represented by the combination of offCode, ll0, and repcode history.
|
||||
* offCode must be an offCode representing a repcode, therefore in the range of [0, 2].
|
||||
* offCode must represent a repcode in the numeric representation of ZSTD_storeSeq().
|
||||
*/
|
||||
static U32 ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offCode, const U32 ll0) {
|
||||
U32 const adjustedOffCode = offCode + ll0;
|
||||
assert(offCode < ZSTD_REP_NUM);
|
||||
static U32
|
||||
ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offCode, const U32 ll0)
|
||||
{
|
||||
U32 const adjustedOffCode = STORED_REPCODE(offCode) - 1 + ll0; /* [ 0 - 3 ] */
|
||||
assert(STORED_IS_REPCODE(offCode));
|
||||
if (adjustedOffCode == ZSTD_REP_NUM) {
|
||||
/* litlength == 0 and offCode == 2 implies selection of first repcode - 1 */
|
||||
assert(rep[0] > 0);
|
||||
@@ -3443,11 +3451,16 @@ static U32 ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32
|
||||
|
||||
/**
|
||||
* ZSTD_seqStore_resolveOffCodes() reconciles any possible divergences in offset history that may arise
|
||||
* due to emission of RLE/raw blocks that disturb the offset history, and replaces any repcodes within
|
||||
* the seqStore that may be invalid.
|
||||
* due to emission of RLE/raw blocks that disturb the offset history,
|
||||
* and replaces any repcodes within the seqStore that may be invalid.
|
||||
*
|
||||
* dRepcodes are updated as would be on the decompression side. cRepcodes are updated exactly in
|
||||
* accordance with the seqStore.
|
||||
* dRepcodes are updated as would be on the decompression side.
|
||||
* cRepcodes are updated exactly in accordance with the seqStore.
|
||||
*
|
||||
* Note : this function assumes seq->offBase respects the following numbering scheme :
|
||||
* 0 : invalid
|
||||
* 1-3 : repcode 1-3
|
||||
* 4+ : real_offset+3
|
||||
*/
|
||||
static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRepcodes,
|
||||
seqStore_t* const seqStore, U32 const nbSeq) {
|
||||
@@ -3455,9 +3468,9 @@ static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_
|
||||
for (; idx < nbSeq; ++idx) {
|
||||
seqDef* const seq = seqStore->sequencesStart + idx;
|
||||
U32 const ll0 = (seq->litLength == 0);
|
||||
U32 offCode = seq->offset - 1;
|
||||
assert(seq->offset > 0);
|
||||
if (offCode <= ZSTD_REP_MOVE) {
|
||||
U32 const offCode = OFFBASE_TO_STORED(seq->offBase);
|
||||
assert(seq->offBase > 0);
|
||||
if (STORED_IS_REPCODE(offCode)) {
|
||||
U32 const dRawOffset = ZSTD_resolveRepcodeToRawOffset(dRepcodes->rep, offCode, ll0);
|
||||
U32 const cRawOffset = ZSTD_resolveRepcodeToRawOffset(cRepcodes->rep, offCode, ll0);
|
||||
/* Adjust simulated decompression repcode history if we come across a mismatch. Replace
|
||||
@@ -3465,14 +3478,14 @@ static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_
|
||||
* repcode history.
|
||||
*/
|
||||
if (dRawOffset != cRawOffset) {
|
||||
seq->offset = cRawOffset + ZSTD_REP_NUM;
|
||||
seq->offBase = cRawOffset + ZSTD_REP_NUM;
|
||||
}
|
||||
}
|
||||
/* Compression repcode history is always updated with values directly from the unmodified seqStore.
|
||||
* Decompression repcode history may use modified seq->offset value taken from compression repcode history.
|
||||
*/
|
||||
*dRepcodes = ZSTD_updateRep(dRepcodes->rep, seq->offset - 1, ll0);
|
||||
*cRepcodes = ZSTD_updateRep(cRepcodes->rep, offCode, ll0);
|
||||
ZSTD_updateRep(dRepcodes->rep, OFFBASE_TO_STORED(seq->offBase), ll0);
|
||||
ZSTD_updateRep(cRepcodes->rep, offCode, ll0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3481,11 +3494,13 @@ static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_
|
||||
*
|
||||
* Returns the total size of that block (including header) or a ZSTD error code.
|
||||
*/
|
||||
static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const seqStore,
|
||||
repcodes_t* const dRep, repcodes_t* const cRep,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
U32 lastBlock, U32 isPartition) {
|
||||
static size_t
|
||||
ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const seqStore,
|
||||
repcodes_t* const dRep, repcodes_t* const cRep,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
U32 lastBlock, U32 isPartition)
|
||||
{
|
||||
const U32 rleMaxLength = 25;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
@@ -3494,6 +3509,7 @@ static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const
|
||||
|
||||
/* In case of an RLE or raw block, the simulated decompression repcode history must be reset */
|
||||
repcodes_t const dRepOriginal = *dRep;
|
||||
DEBUGLOG(5, "ZSTD_compressSeqStore_singleBlock");
|
||||
if (isPartition)
|
||||
ZSTD_seqStore_resolveOffCodes(dRep, cRep, seqStore, (U32)(seqStore->sequences - seqStore->sequencesStart));
|
||||
|
||||
@@ -3566,8 +3582,10 @@ typedef struct {
|
||||
* Furthermore, the number of splits is capped by ZSTD_MAX_NB_BLOCK_SPLITS. At ZSTD_MAX_NB_BLOCK_SPLITS == 196 with the current existing blockSize
|
||||
* maximum of 128 KB, this value is actually impossible to reach.
|
||||
*/
|
||||
static void ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx,
|
||||
ZSTD_CCtx* zc, const seqStore_t* origSeqStore) {
|
||||
static void
|
||||
ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx,
|
||||
ZSTD_CCtx* zc, const seqStore_t* origSeqStore)
|
||||
{
|
||||
seqStore_t* fullSeqStoreChunk = &zc->blockSplitCtx.fullSeqStoreChunk;
|
||||
seqStore_t* firstHalfSeqStore = &zc->blockSplitCtx.firstHalfSeqStore;
|
||||
seqStore_t* secondHalfSeqStore = &zc->blockSplitCtx.secondHalfSeqStore;
|
||||
@@ -3622,8 +3640,10 @@ static size_t ZSTD_deriveBlockSplits(ZSTD_CCtx* zc, U32 partitions[], U32 nbSeq)
|
||||
*
|
||||
* Returns combined size of all blocks (which includes headers), or a ZSTD error code.
|
||||
*/
|
||||
static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity,
|
||||
const void* src, size_t blockSize, U32 lastBlock, U32 nbSeq) {
|
||||
static size_t
|
||||
ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity,
|
||||
const void* src, size_t blockSize, U32 lastBlock, U32 nbSeq)
|
||||
{
|
||||
size_t cSize = 0;
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
@@ -3709,9 +3729,11 @@ static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, s
|
||||
return cSize;
|
||||
}
|
||||
|
||||
static size_t ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize, U32 lastBlock) {
|
||||
static size_t
|
||||
ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize, U32 lastBlock)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
U32 nbSeq;
|
||||
@@ -3737,19 +3759,10 @@ static size_t ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
|
||||
return cSize;
|
||||
}
|
||||
|
||||
/* ZSTD_convertBlockSequencesToSeqStore()
|
||||
* Converts an array of ZSTD_Sequence* with the corresponding original src buffer into
|
||||
* the seqStore of a cctx.
|
||||
*
|
||||
* Returns 0 on success, ZSTD_error on failure.
|
||||
*/
|
||||
static UNUSED_ATTR size_t ZSTD_convertBlockSequencesToSeqStore(ZSTD_CCtx* cctx,
|
||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize, U32 frame)
|
||||
static size_t
|
||||
ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize, U32 frame)
|
||||
{
|
||||
/* This the upper bound for the length of an rle block.
|
||||
* This isn't the actual upper bound. Finding the real threshold
|
||||
@@ -4878,7 +4891,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
||||
&cctxParams, customMem);
|
||||
}
|
||||
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
|
||||
ZSTD_CDict* ZSTD_createCDict_advanced2(
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||
ZSTD_dictContentType_e dictContentType,
|
||||
@@ -5742,39 +5755,39 @@ typedef struct {
|
||||
size_t posInSrc; /* Number of bytes given by sequences provided so far */
|
||||
} ZSTD_sequencePosition;
|
||||
|
||||
/* Returns a ZSTD error code if sequence is not valid */
|
||||
static size_t ZSTD_validateSequence(U32 offCode, U32 matchLength,
|
||||
size_t posInSrc, U32 windowLog, size_t dictSize, U32 minMatch) {
|
||||
size_t offsetBound;
|
||||
U32 windowSize = 1 << windowLog;
|
||||
/* ZSTD_validateSequence() :
|
||||
* @offCode : is presumed to follow format required by ZSTD_storeSeq()
|
||||
* @returns a ZSTD error code if sequence is not valid
|
||||
*/
|
||||
static size_t
|
||||
ZSTD_validateSequence(U32 offCode, U32 matchLength,
|
||||
size_t posInSrc, U32 windowLog, size_t dictSize)
|
||||
{
|
||||
U32 const windowSize = 1 << windowLog;
|
||||
/* posInSrc represents the amount of data the the decoder would decode up to this point.
|
||||
* As long as the amount of data decoded is less than or equal to window size, offsets may be
|
||||
* larger than the total length of output decoded in order to reference the dict, even larger than
|
||||
* window size. After output surpasses windowSize, we're limited to windowSize offsets again.
|
||||
*/
|
||||
offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
|
||||
RETURN_ERROR_IF(offCode > offsetBound + ZSTD_REP_MOVE, corruption_detected, "Offset too large!");
|
||||
RETURN_ERROR_IF(matchLength < minMatch, corruption_detected, "Matchlength too small");
|
||||
size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
|
||||
RETURN_ERROR_IF(offCode > STORE_OFFSET(offsetBound), corruption_detected, "Offset too large!");
|
||||
RETURN_ERROR_IF(matchLength < MINMATCH, corruption_detected, "Matchlength too small");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */
|
||||
static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0) {
|
||||
U32 offCode = rawOffset + ZSTD_REP_MOVE;
|
||||
U32 repCode = 0;
|
||||
static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0)
|
||||
{
|
||||
U32 offCode = STORE_OFFSET(rawOffset);
|
||||
|
||||
if (!ll0 && rawOffset == rep[0]) {
|
||||
repCode = 1;
|
||||
offCode = STORE_REPCODE_1;
|
||||
} else if (rawOffset == rep[1]) {
|
||||
repCode = 2 - ll0;
|
||||
offCode = STORE_REPCODE(2 - ll0);
|
||||
} else if (rawOffset == rep[2]) {
|
||||
repCode = 3 - ll0;
|
||||
offCode = STORE_REPCODE(3 - ll0);
|
||||
} else if (ll0 && rawOffset == rep[0] - 1) {
|
||||
repCode = 3;
|
||||
}
|
||||
if (repCode) {
|
||||
/* ZSTD_storeSeq expects a number in the range [0, 2] to represent a repcode */
|
||||
offCode = repCode - 1;
|
||||
offCode = STORE_REPCODE_3;
|
||||
}
|
||||
return offCode;
|
||||
}
|
||||
@@ -5782,18 +5795,17 @@ static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32
|
||||
/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of
|
||||
* ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter.
|
||||
*/
|
||||
static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize) {
|
||||
static size_t
|
||||
ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
|
||||
ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize)
|
||||
{
|
||||
U32 idx = seqPos->idx;
|
||||
BYTE const* ip = (BYTE const*)(src);
|
||||
const BYTE* const iend = ip + blockSize;
|
||||
repcodes_t updatedRepcodes;
|
||||
U32 dictSize;
|
||||
U32 litLength;
|
||||
U32 matchLength;
|
||||
U32 ll0;
|
||||
U32 offCode;
|
||||
|
||||
if (cctx->cdict) {
|
||||
dictSize = (U32)cctx->cdict->dictContentSize;
|
||||
@@ -5804,23 +5816,22 @@ static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZS
|
||||
}
|
||||
ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
|
||||
for (; (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0) && idx < inSeqsSize; ++idx) {
|
||||
litLength = inSeqs[idx].litLength;
|
||||
matchLength = inSeqs[idx].matchLength;
|
||||
ll0 = litLength == 0;
|
||||
offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
|
||||
updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
|
||||
U32 const litLength = inSeqs[idx].litLength;
|
||||
U32 const ll0 = (litLength == 0);
|
||||
U32 const matchLength = inSeqs[idx].matchLength;
|
||||
U32 const offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
|
||||
ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
|
||||
|
||||
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
|
||||
if (cctx->appliedParams.validateSequences) {
|
||||
seqPos->posInSrc += litLength + matchLength;
|
||||
FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
|
||||
cctx->appliedParams.cParams.windowLog, dictSize,
|
||||
cctx->appliedParams.cParams.minMatch),
|
||||
cctx->appliedParams.cParams.windowLog, dictSize),
|
||||
"Sequence validation failed");
|
||||
}
|
||||
RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
|
||||
"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
|
||||
ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
|
||||
ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength);
|
||||
ip += matchLength + litLength;
|
||||
}
|
||||
ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
|
||||
@@ -5836,13 +5847,6 @@ static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZS
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t ZSTD_convertBlockSequencesToSeqStore(ZSTD_CCtx* cctx,
|
||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t srcSize) {
|
||||
ZSTD_sequencePosition dummySeqPos = {0, 0, 0};
|
||||
return ZSTD_copySequencesToSeqStoreExplicitBlockDelim(cctx, &dummySeqPos, inSeqs, inSeqsSize, src, srcSize);
|
||||
}
|
||||
|
||||
/* Returns the number of bytes to move the current read position back by. Only non-zero
|
||||
* if we ended up splitting a sequence. Otherwise, it may return a ZSTD error if something
|
||||
* went wrong.
|
||||
@@ -5854,9 +5858,11 @@ static size_t ZSTD_convertBlockSequencesToSeqStore(ZSTD_CCtx* cctx,
|
||||
* avoid splitting a match, or to avoid splitting a match such that it would produce a match
|
||||
* smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block.
|
||||
*/
|
||||
static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize) {
|
||||
static size_t
|
||||
ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize)
|
||||
{
|
||||
U32 idx = seqPos->idx;
|
||||
U32 startPosInSequence = seqPos->posInSequence;
|
||||
U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize;
|
||||
@@ -5866,10 +5872,6 @@ static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_seq
|
||||
repcodes_t updatedRepcodes;
|
||||
U32 bytesAdjustment = 0;
|
||||
U32 finalMatchSplit = 0;
|
||||
U32 litLength;
|
||||
U32 matchLength;
|
||||
U32 rawOffset;
|
||||
U32 offCode;
|
||||
|
||||
if (cctx->cdict) {
|
||||
dictSize = cctx->cdict->dictContentSize;
|
||||
@@ -5883,9 +5885,10 @@ static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_seq
|
||||
ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
|
||||
while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) {
|
||||
const ZSTD_Sequence currSeq = inSeqs[idx];
|
||||
litLength = currSeq.litLength;
|
||||
matchLength = currSeq.matchLength;
|
||||
rawOffset = currSeq.offset;
|
||||
U32 litLength = currSeq.litLength;
|
||||
U32 matchLength = currSeq.matchLength;
|
||||
U32 const rawOffset = currSeq.offset;
|
||||
U32 offCode;
|
||||
|
||||
/* Modify the sequence depending on where endPosInSequence lies */
|
||||
if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) {
|
||||
@@ -5938,22 +5941,21 @@ static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_seq
|
||||
}
|
||||
}
|
||||
/* Check if this offset can be represented with a repcode */
|
||||
{ U32 ll0 = (litLength == 0);
|
||||
{ U32 const ll0 = (litLength == 0);
|
||||
offCode = ZSTD_finalizeOffCode(rawOffset, updatedRepcodes.rep, ll0);
|
||||
updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
|
||||
ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
|
||||
}
|
||||
|
||||
if (cctx->appliedParams.validateSequences) {
|
||||
seqPos->posInSrc += litLength + matchLength;
|
||||
FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
|
||||
cctx->appliedParams.cParams.windowLog, dictSize,
|
||||
cctx->appliedParams.cParams.minMatch),
|
||||
cctx->appliedParams.cParams.windowLog, dictSize),
|
||||
"Sequence validation failed");
|
||||
}
|
||||
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
|
||||
RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
|
||||
"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
|
||||
ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
|
||||
ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength);
|
||||
ip += matchLength + litLength;
|
||||
}
|
||||
DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
|
||||
@@ -5978,7 +5980,8 @@ static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_seq
|
||||
typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize);
|
||||
static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) {
|
||||
static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode)
|
||||
{
|
||||
ZSTD_sequenceCopier sequenceCopier = NULL;
|
||||
assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode));
|
||||
if (mode == ZSTD_sf_explicitBlockDelimiters) {
|
||||
@@ -5992,12 +5995,15 @@ static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode)
|
||||
|
||||
/* Compress, block-by-block, all of the sequences given.
|
||||
*
|
||||
* Returns the cumulative size of all compressed blocks (including their headers), otherwise a ZSTD error.
|
||||
* Returns the cumulative size of all compressed blocks (including their headers),
|
||||
* otherwise a ZSTD error.
|
||||
*/
|
||||
static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t srcSize) {
|
||||
static size_t
|
||||
ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
size_t cSize = 0;
|
||||
U32 lastBlock;
|
||||
size_t blockSize;
|
||||
@@ -6007,7 +6013,7 @@ static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
|
||||
|
||||
BYTE const* ip = (BYTE const*)src;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
ZSTD_sequenceCopier sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);
|
||||
ZSTD_sequenceCopier const sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);
|
||||
|
||||
DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize);
|
||||
/* Special case: empty frame */
|
||||
@@ -6107,7 +6113,8 @@ static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
|
||||
|
||||
size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstCapacity,
|
||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t srcSize) {
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
BYTE* op = (BYTE*)dst;
|
||||
size_t cSize = 0;
|
||||
size_t compressedBlocksSize = 0;
|
||||
@@ -6174,119 +6181,12 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
|
||||
|
||||
|
||||
/*-===== Pre-defined compression levels =====-*/
|
||||
#include "clevels.h"
|
||||
|
||||
#define ZSTD_MAX_CLEVEL 22
|
||||
int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
|
||||
int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
|
||||
int ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; }
|
||||
|
||||
static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
|
||||
{ /* "default" - for any srcSize > 256 KB */
|
||||
/* W, C, H, S, L, TL, strat */
|
||||
{ 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
|
||||
{ 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
|
||||
{ 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
|
||||
{ 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */
|
||||
{ 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */
|
||||
{ 21, 18, 19, 4, 5, 2, ZSTD_greedy }, /* level 5 */
|
||||
{ 21, 19, 20, 5, 5, 4, ZSTD_greedy }, /* level 6 */
|
||||
{ 21, 19, 20, 4, 5, 8, ZSTD_lazy }, /* level 7 */
|
||||
{ 21, 19, 20, 5, 5, 16, ZSTD_lazy }, /* level 8 */
|
||||
{ 21, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 22, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 11 */
|
||||
{ 22, 21, 22, 6, 5, 32, ZSTD_lazy2 }, /* level 12 */
|
||||
{ 22, 22, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */
|
||||
{ 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
|
||||
{ 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
|
||||
{ 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */
|
||||
{ 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */
|
||||
{ 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */
|
||||
{ 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */
|
||||
{ 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */
|
||||
{ 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */
|
||||
{ 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */
|
||||
},
|
||||
{ /* for srcSize <= 256 KB */
|
||||
/* W, C, H, S, L, T, strat */
|
||||
{ 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
||||
{ 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
|
||||
{ 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */
|
||||
{ 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */
|
||||
{ 18, 16, 17, 3, 5, 2, ZSTD_greedy }, /* level 4.*/
|
||||
{ 18, 17, 18, 5, 5, 2, ZSTD_greedy }, /* level 5.*/
|
||||
{ 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
|
||||
{ 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */
|
||||
{ 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
|
||||
{ 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/
|
||||
{ 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/
|
||||
{ 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */
|
||||
{ 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
|
||||
{ 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/
|
||||
{ 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/
|
||||
{ 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/
|
||||
{ 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/
|
||||
{ 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
|
||||
{ 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/
|
||||
{ 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/
|
||||
{ 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/
|
||||
},
|
||||
{ /* for srcSize <= 128 KB */
|
||||
/* W, C, H, S, L, T, strat */
|
||||
{ 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
||||
{ 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
|
||||
{ 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
|
||||
{ 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */
|
||||
{ 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */
|
||||
{ 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
|
||||
{ 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
|
||||
{ 17, 16, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
|
||||
{ 17, 16, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
|
||||
{ 17, 16, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 17, 16, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */
|
||||
{ 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */
|
||||
{ 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/
|
||||
{ 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
|
||||
{ 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/
|
||||
{ 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/
|
||||
{ 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/
|
||||
{ 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/
|
||||
{ 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/
|
||||
{ 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/
|
||||
{ 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
|
||||
{ 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/
|
||||
},
|
||||
{ /* for srcSize <= 16 KB */
|
||||
/* W, C, H, S, L, T, strat */
|
||||
{ 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
||||
{ 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
|
||||
{ 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
|
||||
{ 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */
|
||||
{ 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */
|
||||
{ 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
|
||||
{ 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
|
||||
{ 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */
|
||||
{ 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/
|
||||
{ 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/
|
||||
{ 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/
|
||||
{ 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/
|
||||
{ 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/
|
||||
{ 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/
|
||||
{ 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/
|
||||
{ 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/
|
||||
{ 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/
|
||||
{ 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/
|
||||
{ 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/
|
||||
{ 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
|
||||
{ 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/
|
||||
{ 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
|
||||
{ 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/
|
||||
},
|
||||
};
|
||||
|
||||
static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize)
|
||||
{
|
||||
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict);
|
||||
|
||||
@@ -129,7 +129,7 @@ size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
|
||||
*********************************/
|
||||
|
||||
typedef struct {
|
||||
U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */
|
||||
U32 off; /* Offset sumtype code for the match, using ZSTD_storeSeq() format */
|
||||
U32 len; /* Raw length of match */
|
||||
} ZSTD_match_t;
|
||||
|
||||
@@ -392,7 +392,7 @@ struct ZSTD_CCtx_s {
|
||||
ZSTD_blockState_t blockState;
|
||||
U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */
|
||||
|
||||
/* Wether we are streaming or not */
|
||||
/* Whether we are streaming or not */
|
||||
ZSTD_buffered_policy_e bufferedPolicy;
|
||||
|
||||
/* streaming */
|
||||
@@ -497,31 +497,6 @@ MEM_STATIC U32 ZSTD_MLcode(U32 mlBase)
|
||||
return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase];
|
||||
}
|
||||
|
||||
typedef struct repcodes_s {
|
||||
U32 rep[3];
|
||||
} repcodes_t;
|
||||
|
||||
MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
|
||||
{
|
||||
repcodes_t newReps;
|
||||
if (offset >= ZSTD_REP_NUM) { /* full offset */
|
||||
newReps.rep[2] = rep[1];
|
||||
newReps.rep[1] = rep[0];
|
||||
newReps.rep[0] = offset - ZSTD_REP_MOVE;
|
||||
} else { /* repcode */
|
||||
U32 const repCode = offset + ll0;
|
||||
if (repCode > 0) { /* note : if repCode==0, no change */
|
||||
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
|
||||
newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
|
||||
newReps.rep[1] = rep[0];
|
||||
newReps.rep[0] = currentOffset;
|
||||
} else { /* repCode == 0 */
|
||||
ZSTD_memcpy(&newReps, rep, sizeof(newReps));
|
||||
}
|
||||
}
|
||||
return newReps;
|
||||
}
|
||||
|
||||
/* ZSTD_cParam_withinBounds:
|
||||
* @return 1 if value is within cParam bounds,
|
||||
* 0 otherwise */
|
||||
@@ -590,7 +565,9 @@ MEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxPa
|
||||
* Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single
|
||||
* large copies.
|
||||
*/
|
||||
static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w) {
|
||||
static void
|
||||
ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w)
|
||||
{
|
||||
assert(iend > ilimit_w);
|
||||
if (ip <= ilimit_w) {
|
||||
ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap);
|
||||
@@ -600,14 +577,30 @@ static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const ie
|
||||
while (ip < iend) *op++ = *ip++;
|
||||
}
|
||||
|
||||
#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1)
|
||||
#define STORE_REPCODE_1 STORE_REPCODE(1)
|
||||
#define STORE_REPCODE_2 STORE_REPCODE(2)
|
||||
#define STORE_REPCODE_3 STORE_REPCODE(3)
|
||||
#define STORE_REPCODE(r) (assert((r)>=1), assert((r)<=3), (r)-1)
|
||||
#define STORE_OFFSET(o) (assert((o)>0), o + ZSTD_REP_MOVE)
|
||||
#define STORED_IS_OFFSET(o) ((o) > ZSTD_REP_MOVE)
|
||||
#define STORED_IS_REPCODE(o) ((o) <= ZSTD_REP_MOVE)
|
||||
#define STORED_OFFSET(o) (assert(STORED_IS_OFFSET(o)), (o)-ZSTD_REP_MOVE)
|
||||
#define STORED_REPCODE(o) (assert(STORED_IS_REPCODE(o)), (o)+1) /* returns ID 1,2,3 */
|
||||
#define STORED_TO_OFFBASE(o) ((o)+1)
|
||||
#define OFFBASE_TO_STORED(o) ((o)-1)
|
||||
|
||||
/*! ZSTD_storeSeq() :
|
||||
* Store a sequence (litlen, litPtr, offCode and mlBase) into seqStore_t.
|
||||
* `offCode` : distance to match + ZSTD_REP_MOVE (values <= ZSTD_REP_MOVE are repCodes).
|
||||
* `mlBase` : matchLength - MINMATCH
|
||||
* Store a sequence (litlen, litPtr, offCode and matchLength) into seqStore_t.
|
||||
* @offBase_minus1 : Users should use employ macros STORE_REPCODE_X and STORE_OFFSET().
|
||||
* @matchLength : must be >= MINMATCH
|
||||
* Allowed to overread literals up to litLimit.
|
||||
*/
|
||||
HINT_INLINE UNUSED_ATTR
|
||||
void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, const BYTE* litLimit, U32 offCode, size_t mlBase)
|
||||
HINT_INLINE UNUSED_ATTR void
|
||||
ZSTD_storeSeq(seqStore_t* seqStorePtr,
|
||||
size_t litLength, const BYTE* literals, const BYTE* litLimit,
|
||||
U32 offBase_minus1,
|
||||
size_t matchLength)
|
||||
{
|
||||
BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH;
|
||||
BYTE const* const litEnd = literals + litLength;
|
||||
@@ -616,7 +609,7 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
|
||||
if (g_start==NULL) g_start = (const BYTE*)literals; /* note : index only works for compression within a single segment */
|
||||
{ U32 const pos = (U32)((const BYTE*)literals - g_start);
|
||||
DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offCode%7u",
|
||||
pos, (U32)litLength, (U32)mlBase+MINMATCH, (U32)offCode);
|
||||
pos, (U32)litLength, (U32)matchLength, (U32)offBase_minus1);
|
||||
}
|
||||
#endif
|
||||
assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);
|
||||
@@ -647,19 +640,59 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
|
||||
seqStorePtr->sequences[0].litLength = (U16)litLength;
|
||||
|
||||
/* match offset */
|
||||
seqStorePtr->sequences[0].offset = offCode + 1;
|
||||
seqStorePtr->sequences[0].offBase = STORED_TO_OFFBASE(offBase_minus1);
|
||||
|
||||
/* match Length */
|
||||
if (mlBase>0xFFFF) {
|
||||
assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
|
||||
seqStorePtr->longLengthType = ZSTD_llt_matchLength;
|
||||
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
||||
assert(matchLength >= MINMATCH);
|
||||
{ size_t const mlBase = matchLength - MINMATCH;
|
||||
if (mlBase>0xFFFF) {
|
||||
assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
|
||||
seqStorePtr->longLengthType = ZSTD_llt_matchLength;
|
||||
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
||||
}
|
||||
seqStorePtr->sequences[0].mlBase = (U16)mlBase;
|
||||
}
|
||||
seqStorePtr->sequences[0].matchLength = (U16)mlBase;
|
||||
|
||||
seqStorePtr->sequences++;
|
||||
}
|
||||
|
||||
/* ZSTD_updateRep() :
|
||||
* updates in-place @rep (array of repeat offsets)
|
||||
* @offBase_minus1 : sum-type, with same numeric representation as ZSTD_storeSeq()
|
||||
*/
|
||||
MEM_STATIC void
|
||||
ZSTD_updateRep(U32 rep[ZSTD_REP_NUM], U32 const offBase_minus1, U32 const ll0)
|
||||
{
|
||||
if (STORED_IS_OFFSET(offBase_minus1)) { /* full offset */
|
||||
rep[2] = rep[1];
|
||||
rep[1] = rep[0];
|
||||
rep[0] = STORED_OFFSET(offBase_minus1);
|
||||
} else { /* repcode */
|
||||
U32 const repCode = STORED_REPCODE(offBase_minus1) - 1 + ll0;
|
||||
if (repCode > 0) { /* note : if repCode==0, no change */
|
||||
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
|
||||
rep[2] = (repCode >= 2) ? rep[1] : rep[2];
|
||||
rep[1] = rep[0];
|
||||
rep[0] = currentOffset;
|
||||
} else { /* repCode == 0 */
|
||||
/* nothing to do */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct repcodes_s {
|
||||
U32 rep[3];
|
||||
} repcodes_t;
|
||||
|
||||
MEM_STATIC repcodes_t
|
||||
ZSTD_newRep(U32 const rep[ZSTD_REP_NUM], U32 const offBase_minus1, U32 const ll0)
|
||||
{
|
||||
repcodes_t newReps;
|
||||
ZSTD_memcpy(&newReps, rep, sizeof(newReps));
|
||||
ZSTD_updateRep(newReps.rep, offBase_minus1, ll0);
|
||||
return newReps;
|
||||
}
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Match length counter
|
||||
@@ -672,11 +705,17 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
|
||||
# if STATIC_BMI2
|
||||
return _tzcnt_u64(val) >> 3;
|
||||
# else
|
||||
unsigned long r = 0;
|
||||
return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0;
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanForward64(&r, (U64)val);
|
||||
return (unsigned)(r >> 3);
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# endif
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
return (unsigned)(__builtin_ctzll((U64)val) >> 3);
|
||||
return (__builtin_ctzll((U64)val) >> 3);
|
||||
# else
|
||||
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,
|
||||
0, 3, 1, 3, 1, 4, 2, 7,
|
||||
@@ -690,10 +729,16 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
|
||||
# endif
|
||||
} else { /* 32 bits */
|
||||
# if defined(_MSC_VER)
|
||||
unsigned long r=0;
|
||||
return _BitScanForward( &r, (U32)val ) ? (unsigned)(r >> 3) : 0;
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanForward(&r, (U32)val);
|
||||
return (unsigned)(r >> 3);
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (unsigned)(__builtin_ctz((U32)val) >> 3);
|
||||
return (__builtin_ctz((U32)val) >> 3);
|
||||
# else
|
||||
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
|
||||
3, 2, 2, 1, 3, 2, 0, 1,
|
||||
@@ -708,11 +753,17 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
|
||||
# if STATIC_BMI2
|
||||
return _lzcnt_u64(val) >> 3;
|
||||
# else
|
||||
unsigned long r = 0;
|
||||
return _BitScanReverse64(&r, (U64)val) ? (unsigned)(r >> 3) : 0;
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanReverse64(&r, (U64)val);
|
||||
return (unsigned)(r >> 3);
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# endif
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
return (unsigned)(__builtin_clzll(val) >> 3);
|
||||
return (__builtin_clzll(val) >> 3);
|
||||
# else
|
||||
unsigned r;
|
||||
const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
|
||||
@@ -723,10 +774,16 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
|
||||
# endif
|
||||
} else { /* 32 bits */
|
||||
# if defined(_MSC_VER)
|
||||
unsigned long r = 0;
|
||||
return _BitScanReverse( &r, (unsigned long)val ) ? (unsigned)(r >> 3) : 0;
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanReverse(&r, (unsigned long)val);
|
||||
return (unsigned)(r >> 3);
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (unsigned)(__builtin_clz((U32)val) >> 3);
|
||||
return (__builtin_clz((U32)val) >> 3);
|
||||
# else
|
||||
unsigned r;
|
||||
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
|
||||
@@ -958,7 +1015,9 @@ MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,
|
||||
{
|
||||
U32 const cycleSize = 1u << cycleLog;
|
||||
U32 const curr = (U32)((BYTE const*)src - window.base);
|
||||
U32 const minIndexToOverflowCorrect = cycleSize + MAX(maxDist, cycleSize);
|
||||
U32 const minIndexToOverflowCorrect = cycleSize
|
||||
+ MAX(maxDist, cycleSize)
|
||||
+ ZSTD_WINDOW_START_INDEX;
|
||||
|
||||
/* Adjust the min index to backoff the overflow correction frequency,
|
||||
* so we don't waste too much CPU in overflow correction. If this
|
||||
@@ -1033,10 +1092,14 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
||||
U32 const cycleSize = 1u << cycleLog;
|
||||
U32 const cycleMask = cycleSize - 1;
|
||||
U32 const curr = (U32)((BYTE const*)src - window->base);
|
||||
U32 const currentCycle0 = curr & cycleMask;
|
||||
/* Exclude zero so that newCurrent - maxDist >= 1. */
|
||||
U32 const currentCycle1 = currentCycle0 == 0 ? cycleSize : currentCycle0;
|
||||
U32 const newCurrent = currentCycle1 + MAX(maxDist, cycleSize);
|
||||
U32 const currentCycle = curr & cycleMask;
|
||||
/* Ensure newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX. */
|
||||
U32 const currentCycleCorrection = currentCycle < ZSTD_WINDOW_START_INDEX
|
||||
? MAX(cycleSize, ZSTD_WINDOW_START_INDEX)
|
||||
: 0;
|
||||
U32 const newCurrent = currentCycle
|
||||
+ currentCycleCorrection
|
||||
+ MAX(maxDist, cycleSize);
|
||||
U32 const correction = curr - newCurrent;
|
||||
/* maxDist must be a power of two so that:
|
||||
* (newCurrent & cycleMask) == (curr & cycleMask)
|
||||
@@ -1052,14 +1115,20 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
||||
|
||||
window->base += correction;
|
||||
window->dictBase += correction;
|
||||
if (window->lowLimit <= correction) window->lowLimit = 1;
|
||||
else window->lowLimit -= correction;
|
||||
if (window->dictLimit <= correction) window->dictLimit = 1;
|
||||
else window->dictLimit -= correction;
|
||||
if (window->lowLimit < correction + ZSTD_WINDOW_START_INDEX) {
|
||||
window->lowLimit = ZSTD_WINDOW_START_INDEX;
|
||||
} else {
|
||||
window->lowLimit -= correction;
|
||||
}
|
||||
if (window->dictLimit < correction + ZSTD_WINDOW_START_INDEX) {
|
||||
window->dictLimit = ZSTD_WINDOW_START_INDEX;
|
||||
} else {
|
||||
window->dictLimit -= correction;
|
||||
}
|
||||
|
||||
/* Ensure we can still reference the full window. */
|
||||
assert(newCurrent >= maxDist);
|
||||
assert(newCurrent - maxDist >= 1);
|
||||
assert(newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX);
|
||||
/* Ensure that lowLimit and dictLimit didn't underflow. */
|
||||
assert(window->lowLimit <= newCurrent);
|
||||
assert(window->dictLimit <= newCurrent);
|
||||
|
||||
@@ -93,6 +93,7 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
||||
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
|
||||
/* small ? don't even attempt compression (speed opt) */
|
||||
# define COMPRESS_LITERALS_SIZE_MIN 63
|
||||
{ size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
|
||||
if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
@@ -135,7 +136,7 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
||||
switch(lhSize)
|
||||
{
|
||||
case 3: /* 2 - 2 - 10 - 10 */
|
||||
{ U32 const lhc = hType + (((U32)!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);
|
||||
{ U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);
|
||||
MEM_writeLE24(ostart, lhc);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
#include "zstd_compress_internal.h" /* ZSTD_hufCTables_t, ZSTD_minGain() */
|
||||
|
||||
|
||||
/* Below this limit, the heuristic does not even attempt compression of literals,
|
||||
* as the cost of the headers is expected to outweight the benefits.
|
||||
* This limit is not applicable when re-using statistics from dictionary or previous block */
|
||||
#define COMPRESS_LITERALS_SIZE_MIN 63
|
||||
|
||||
size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
|
||||
size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
|
||||
@@ -313,19 +313,19 @@ ZSTD_encodeSequences_body(
|
||||
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].mlBase, ML_bits[mlCodeTable[nbSeq-1]]);
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
||||
if (longOffsets) {
|
||||
U32 const ofBits = ofCodeTable[nbSeq-1];
|
||||
unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
||||
if (extraBits) {
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, extraBits);
|
||||
BIT_flushBits(&blockStream);
|
||||
}
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].offBase >> extraBits,
|
||||
ofBits - extraBits);
|
||||
} else {
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, ofCodeTable[nbSeq-1]);
|
||||
}
|
||||
BIT_flushBits(&blockStream);
|
||||
|
||||
@@ -339,8 +339,8 @@ ZSTD_encodeSequences_body(
|
||||
U32 const mlBits = ML_bits[mlCode];
|
||||
DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
|
||||
(unsigned)sequences[n].litLength,
|
||||
(unsigned)sequences[n].matchLength + MINMATCH,
|
||||
(unsigned)sequences[n].offset);
|
||||
(unsigned)sequences[n].mlBase + MINMATCH,
|
||||
(unsigned)sequences[n].offBase);
|
||||
/* 32b*/ /* 64b*/
|
||||
/* (7)*/ /* (7)*/
|
||||
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
|
||||
@@ -351,18 +351,18 @@ ZSTD_encodeSequences_body(
|
||||
BIT_flushBits(&blockStream); /* (7)*/
|
||||
BIT_addBits(&blockStream, sequences[n].litLength, llBits);
|
||||
if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
|
||||
BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
|
||||
BIT_addBits(&blockStream, sequences[n].mlBase, mlBits);
|
||||
if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
|
||||
if (longOffsets) {
|
||||
unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
||||
if (extraBits) {
|
||||
BIT_addBits(&blockStream, sequences[n].offset, extraBits);
|
||||
BIT_addBits(&blockStream, sequences[n].offBase, extraBits);
|
||||
BIT_flushBits(&blockStream); /* (7)*/
|
||||
}
|
||||
BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
|
||||
BIT_addBits(&blockStream, sequences[n].offBase >> extraBits,
|
||||
ofBits - extraBits); /* 31 */
|
||||
} else {
|
||||
BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
|
||||
BIT_addBits(&blockStream, sequences[n].offBase, ofBits); /* 31 */
|
||||
}
|
||||
BIT_flushBits(&blockStream); /* (7)*/
|
||||
DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr));
|
||||
@@ -399,7 +399,7 @@ ZSTD_encodeSequences_default(
|
||||
|
||||
#if DYNAMIC_BMI2
|
||||
|
||||
static TARGET_ATTRIBUTE("bmi2") size_t
|
||||
static BMI2_TARGET_ATTRIBUTE size_t
|
||||
ZSTD_encodeSequences_bmi2(
|
||||
void* dst, size_t dstCapacity,
|
||||
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
||||
|
||||
@@ -132,6 +132,7 @@ static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, const seqDef*
|
||||
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);
|
||||
litLengthSum += seqLen.litLength;
|
||||
@@ -324,7 +325,7 @@ static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t lit
|
||||
static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
|
||||
const BYTE* codeTable, unsigned maxCode,
|
||||
size_t nbSeq, const FSE_CTable* fseCTable,
|
||||
const U32* additionalBits,
|
||||
const U8* additionalBits,
|
||||
short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
|
||||
void* workspace, size_t wkspSize)
|
||||
{
|
||||
@@ -474,7 +475,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
|
||||
/* 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 everytime.
|
||||
* For example, it would recount literal distribution and symbol codes every time.
|
||||
*/
|
||||
cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount,
|
||||
&nextCBlock->entropy, entropyMetadata,
|
||||
@@ -538,7 +539,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
|
||||
repcodes_t rep;
|
||||
ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
|
||||
for (seq = sstart; seq < sp; ++seq) {
|
||||
rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
|
||||
ZSTD_updateRep(rep.rep, seq->offBase - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
|
||||
}
|
||||
ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
|
||||
}
|
||||
|
||||
+41
-27
@@ -219,7 +219,7 @@ MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) {
|
||||
MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) {
|
||||
/* For alignment, the wksp will always allocate an additional n_1=[1, 64] bytes
|
||||
* to align the beginning of tables section, as well as another n_2=[0, 63] bytes
|
||||
* to align the beginning of the aligned secion.
|
||||
* to align the beginning of the aligned section.
|
||||
*
|
||||
* n_1 + n_2 == 64 bytes if the cwksp is freshly allocated, due to tables and
|
||||
* aligneds being sized in multiples of 64 bytes.
|
||||
@@ -243,12 +243,14 @@ MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignByt
|
||||
|
||||
/**
|
||||
* Internal function. Do not use directly.
|
||||
* Reserves the given number of bytes within the aligned/buffer segment of the wksp, which
|
||||
* counts from the end of the wksp. (as opposed to the object/table segment)
|
||||
* Reserves the given number of bytes within the aligned/buffer segment of the wksp,
|
||||
* which counts from the end of the wksp (as opposed to the object/table segment).
|
||||
*
|
||||
* Returns a pointer to the beginning of that space.
|
||||
*/
|
||||
MEM_STATIC void* ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes) {
|
||||
MEM_STATIC void*
|
||||
ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes)
|
||||
{
|
||||
void* const alloc = (BYTE*)ws->allocStart - bytes;
|
||||
void* const bottom = ws->tableEnd;
|
||||
DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining",
|
||||
@@ -260,6 +262,8 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t
|
||||
ws->allocFailed = 1;
|
||||
return NULL;
|
||||
}
|
||||
/* the area is reserved from the end of wksp.
|
||||
* If it overlaps with tableValidEnd, it voids guarantees on values' range */
|
||||
if (alloc < ws->tableValidEnd) {
|
||||
ws->tableValidEnd = alloc;
|
||||
}
|
||||
@@ -269,10 +273,12 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t
|
||||
|
||||
/**
|
||||
* Moves the cwksp to the next phase, and does any necessary allocations.
|
||||
* cwksp initialization must necessarily go through each phase in order.
|
||||
* Returns a 0 on success, or zstd error
|
||||
*/
|
||||
MEM_STATIC size_t ZSTD_cwksp_internal_advance_phase(
|
||||
ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase) {
|
||||
MEM_STATIC size_t
|
||||
ZSTD_cwksp_internal_advance_phase(ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase)
|
||||
{
|
||||
assert(phase >= ws->phase);
|
||||
if (phase > ws->phase) {
|
||||
/* Going from allocating objects to allocating buffers */
|
||||
@@ -295,15 +301,15 @@ MEM_STATIC size_t ZSTD_cwksp_internal_advance_phase(
|
||||
{ /* Align the start of the tables to 64 bytes. Use [0, 63] bytes */
|
||||
void* const alloc = ws->objectEnd;
|
||||
size_t const bytesToAlign = ZSTD_cwksp_bytes_to_align_ptr(alloc, ZSTD_CWKSP_ALIGNMENT_BYTES);
|
||||
void* const end = (BYTE*)alloc + bytesToAlign;
|
||||
void* const objectEnd = (BYTE*)alloc + bytesToAlign;
|
||||
DEBUGLOG(5, "reserving table alignment addtl space: %zu", bytesToAlign);
|
||||
RETURN_ERROR_IF(end > ws->workspaceEnd, memory_allocation,
|
||||
RETURN_ERROR_IF(objectEnd > ws->workspaceEnd, memory_allocation,
|
||||
"table phase - alignment initial allocation failed!");
|
||||
ws->objectEnd = end;
|
||||
ws->tableEnd = end;
|
||||
ws->tableValidEnd = end;
|
||||
}
|
||||
}
|
||||
ws->objectEnd = objectEnd;
|
||||
ws->tableEnd = objectEnd; /* table area starts being empty */
|
||||
if (ws->tableValidEnd < ws->tableEnd) {
|
||||
ws->tableValidEnd = ws->tableEnd;
|
||||
} } }
|
||||
ws->phase = phase;
|
||||
ZSTD_cwksp_assert_internal_consistency(ws);
|
||||
}
|
||||
@@ -313,15 +319,17 @@ MEM_STATIC size_t ZSTD_cwksp_internal_advance_phase(
|
||||
/**
|
||||
* Returns whether this object/buffer/etc was allocated in this workspace.
|
||||
*/
|
||||
MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr) {
|
||||
MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr)
|
||||
{
|
||||
return (ptr != NULL) && (ws->workspace <= ptr) && (ptr <= ws->workspaceEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function. Do not use directly.
|
||||
*/
|
||||
MEM_STATIC void* ZSTD_cwksp_reserve_internal(
|
||||
ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase) {
|
||||
MEM_STATIC void*
|
||||
ZSTD_cwksp_reserve_internal(ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase)
|
||||
{
|
||||
void* alloc;
|
||||
if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase)) || bytes == 0) {
|
||||
return NULL;
|
||||
@@ -351,14 +359,16 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal(
|
||||
/**
|
||||
* Reserves and returns unaligned memory.
|
||||
*/
|
||||
MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes) {
|
||||
MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes)
|
||||
{
|
||||
return (BYTE*)ZSTD_cwksp_reserve_internal(ws, bytes, ZSTD_cwksp_alloc_buffers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).
|
||||
*/
|
||||
MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) {
|
||||
MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes)
|
||||
{
|
||||
void* ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES),
|
||||
ZSTD_cwksp_alloc_aligned);
|
||||
assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0);
|
||||
@@ -370,7 +380,8 @@ MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) {
|
||||
* their values remain constrained, allowing us to re-use them without
|
||||
* memset()-ing them.
|
||||
*/
|
||||
MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
|
||||
MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes)
|
||||
{
|
||||
const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned;
|
||||
void* alloc;
|
||||
void* end;
|
||||
@@ -408,9 +419,11 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
|
||||
|
||||
/**
|
||||
* Aligned on sizeof(void*).
|
||||
* Note : should happen only once, at workspace first initialization
|
||||
*/
|
||||
MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
|
||||
size_t roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*));
|
||||
MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes)
|
||||
{
|
||||
size_t const roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*));
|
||||
void* alloc = ws->objectEnd;
|
||||
void* end = (BYTE*)alloc + roundedBytes;
|
||||
|
||||
@@ -419,15 +432,15 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
|
||||
end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
||||
#endif
|
||||
|
||||
DEBUGLOG(5,
|
||||
DEBUGLOG(4,
|
||||
"cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining",
|
||||
alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes);
|
||||
assert(((size_t)alloc & (sizeof(void*)-1)) == 0);
|
||||
assert((bytes & (sizeof(void*)-1)) == 0);
|
||||
assert((size_t)alloc % ZSTD_ALIGNOF(void*) == 0);
|
||||
assert(bytes % ZSTD_ALIGNOF(void*) == 0);
|
||||
ZSTD_cwksp_assert_internal_consistency(ws);
|
||||
/* we must be in the first phase, no advance is possible */
|
||||
if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) {
|
||||
DEBUGLOG(4, "cwksp: object alloc failed!");
|
||||
DEBUGLOG(3, "cwksp: object alloc failed!");
|
||||
ws->allocFailed = 1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -438,7 +451,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
|
||||
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
||||
/* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
|
||||
* either size. */
|
||||
alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
||||
alloc = (BYTE*)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
||||
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
|
||||
__asan_unpoison_memory_region(alloc, bytes);
|
||||
}
|
||||
@@ -447,7 +460,8 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
|
||||
return alloc;
|
||||
}
|
||||
|
||||
MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) {
|
||||
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)
|
||||
|
||||
+293
-116
@@ -48,10 +48,216 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
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 */)
|
||||
{
|
||||
ZSTD_compressionParameters const* cParams = &ms->cParams;
|
||||
U32* const hashLong = ms->hashTable;
|
||||
const U32 hBitsL = cParams->hashLog;
|
||||
U32* const hashSmall = ms->chainTable;
|
||||
const U32 hBitsS = cParams->chainLog;
|
||||
const BYTE* const base = ms->window.base;
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
const BYTE* anchor = istart;
|
||||
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
||||
/* presumes that, if there is a dictionary, it must be using Attach mode */
|
||||
const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);
|
||||
const BYTE* const prefixLowest = base + prefixLowestIndex;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* const ilimit = iend - HASH_READ_SIZE;
|
||||
U32 offset_1=rep[0], offset_2=rep[1];
|
||||
U32 offsetSaved = 0;
|
||||
|
||||
size_t mLength;
|
||||
U32 offset;
|
||||
U32 curr;
|
||||
|
||||
/* how many positions to search before increasing step size */
|
||||
const size_t kStepIncr = 1 << kSearchStrength;
|
||||
/* the position at which to increment the step size if no match is found */
|
||||
const BYTE* nextStep;
|
||||
size_t step; /* the current step size */
|
||||
|
||||
size_t hl0; /* the long hash at ip */
|
||||
size_t hl1; /* the long hash at ip1 */
|
||||
|
||||
U32 idxl0; /* the long match index for ip */
|
||||
U32 idxl1; /* the long match index for ip1 */
|
||||
|
||||
const BYTE* matchl0; /* the long match for ip */
|
||||
const BYTE* matchs0; /* the short match for ip */
|
||||
const BYTE* matchl1; /* the long match for ip1 */
|
||||
|
||||
const BYTE* ip = istart; /* the current position */
|
||||
const BYTE* ip1; /* the next position */
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_noDict_generic");
|
||||
|
||||
/* init */
|
||||
ip += ((ip - prefixLowest) == 0);
|
||||
{
|
||||
U32 const current = (U32)(ip - base);
|
||||
U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog);
|
||||
U32 const maxRep = current - windowLow;
|
||||
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
|
||||
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
|
||||
}
|
||||
|
||||
/* Outer Loop: one iteration per match found and stored */
|
||||
while (1) {
|
||||
step = 1;
|
||||
nextStep = ip + kStepIncr;
|
||||
ip1 = ip + step;
|
||||
|
||||
if (ip1 > ilimit) {
|
||||
goto _cleanup;
|
||||
}
|
||||
|
||||
hl0 = ZSTD_hashPtr(ip, hBitsL, 8);
|
||||
idxl0 = hashLong[hl0];
|
||||
matchl0 = base + idxl0;
|
||||
|
||||
/* Inner Loop: one iteration per search / position */
|
||||
do {
|
||||
const size_t hs0 = ZSTD_hashPtr(ip, hBitsS, mls);
|
||||
const U32 idxs0 = hashSmall[hs0];
|
||||
curr = (U32)(ip-base);
|
||||
matchs0 = base + idxs0;
|
||||
|
||||
hashLong[hl0] = hashSmall[hs0] = curr; /* update hash tables */
|
||||
|
||||
/* check noDict repcode */
|
||||
if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
|
||||
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
|
||||
goto _match_stored;
|
||||
}
|
||||
|
||||
hl1 = ZSTD_hashPtr(ip1, hBitsL, 8);
|
||||
|
||||
if (idxl0 > prefixLowestIndex) {
|
||||
/* check prefix long match */
|
||||
if (MEM_read64(matchl0) == MEM_read64(ip)) {
|
||||
mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8;
|
||||
offset = (U32)(ip-matchl0);
|
||||
while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */
|
||||
goto _match_found;
|
||||
}
|
||||
}
|
||||
|
||||
idxl1 = hashLong[hl1];
|
||||
matchl1 = base + idxl1;
|
||||
|
||||
if (idxs0 > prefixLowestIndex) {
|
||||
/* check prefix short match */
|
||||
if (MEM_read32(matchs0) == MEM_read32(ip)) {
|
||||
goto _search_next_long;
|
||||
}
|
||||
}
|
||||
|
||||
if (ip1 >= nextStep) {
|
||||
PREFETCH_L1(ip1 + 64);
|
||||
PREFETCH_L1(ip1 + 128);
|
||||
step++;
|
||||
nextStep += kStepIncr;
|
||||
}
|
||||
ip = ip1;
|
||||
ip1 += step;
|
||||
|
||||
hl0 = hl1;
|
||||
idxl0 = idxl1;
|
||||
matchl0 = matchl1;
|
||||
#if defined(__aarch64__)
|
||||
PREFETCH_L1(ip+256);
|
||||
#endif
|
||||
} while (ip1 <= ilimit);
|
||||
|
||||
_cleanup:
|
||||
/* save reps for next block */
|
||||
rep[0] = offset_1 ? offset_1 : offsetSaved;
|
||||
rep[1] = offset_2 ? offset_2 : offsetSaved;
|
||||
|
||||
/* Return the last literals size */
|
||||
return (size_t)(iend - anchor);
|
||||
|
||||
_search_next_long:
|
||||
|
||||
/* check prefix long +1 match */
|
||||
if (idxl1 > prefixLowestIndex) {
|
||||
if (MEM_read64(matchl1) == MEM_read64(ip1)) {
|
||||
ip = ip1;
|
||||
mLength = ZSTD_count(ip+8, matchl1+8, iend) + 8;
|
||||
offset = (U32)(ip-matchl1);
|
||||
while (((ip>anchor) & (matchl1>prefixLowest)) && (ip[-1] == matchl1[-1])) { ip--; matchl1--; mLength++; } /* catch up */
|
||||
goto _match_found;
|
||||
}
|
||||
}
|
||||
|
||||
/* if no long +1 match, explore the short match we found */
|
||||
mLength = ZSTD_count(ip+4, matchs0+4, iend) + 4;
|
||||
offset = (U32)(ip - matchs0);
|
||||
while (((ip>anchor) & (matchs0>prefixLowest)) && (ip[-1] == matchs0[-1])) { ip--; matchs0--; mLength++; } /* catch up */
|
||||
|
||||
/* fall-through */
|
||||
|
||||
_match_found: /* requires ip, offset, mLength */
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
|
||||
if (step < 4) {
|
||||
/* It is unsafe to write this value back to the hashtable when ip1 is
|
||||
* greater than or equal to the new ip we will have after we're done
|
||||
* processing this match. Rather than perform that test directly
|
||||
* (ip1 >= ip + mLength), which costs speed in practice, we do a simpler
|
||||
* more predictable test. The minmatch even if we take a short match is
|
||||
* 4 bytes, so as long as step, the distance between ip and ip1
|
||||
* (initially) is less than 4, we know ip1 < new ip. */
|
||||
hashLong[hl1] = (U32)(ip1 - base);
|
||||
}
|
||||
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
|
||||
|
||||
_match_stored:
|
||||
/* match found */
|
||||
ip += mLength;
|
||||
anchor = ip;
|
||||
|
||||
if (ip <= ilimit) {
|
||||
/* Complementary insertion */
|
||||
/* done after iLimit test, as candidates could be > iend-8 */
|
||||
{ U32 const indexToInsert = curr+2;
|
||||
hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;
|
||||
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
|
||||
hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;
|
||||
hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);
|
||||
}
|
||||
|
||||
/* check immediate repcode */
|
||||
while ( (ip <= ilimit)
|
||||
&& ( (offset_2>0)
|
||||
& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
|
||||
/* store sequence */
|
||||
size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
||||
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
|
||||
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
|
||||
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, rLength);
|
||||
ip += rLength;
|
||||
anchor = ip;
|
||||
continue; /* faster when present ... (?) */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
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,
|
||||
U32 const mls /* template */, ZSTD_dictMode_e const dictMode)
|
||||
U32 const mls /* template */)
|
||||
{
|
||||
ZSTD_compressionParameters const* cParams = &ms->cParams;
|
||||
U32* const hashLong = ms->hashTable;
|
||||
@@ -72,54 +278,30 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
U32 offsetSaved = 0;
|
||||
|
||||
const ZSTD_matchState_t* const dms = ms->dictMatchState;
|
||||
const ZSTD_compressionParameters* const dictCParams =
|
||||
dictMode == ZSTD_dictMatchState ?
|
||||
&dms->cParams : NULL;
|
||||
const U32* const dictHashLong = dictMode == ZSTD_dictMatchState ?
|
||||
dms->hashTable : NULL;
|
||||
const U32* const dictHashSmall = dictMode == ZSTD_dictMatchState ?
|
||||
dms->chainTable : NULL;
|
||||
const U32 dictStartIndex = dictMode == ZSTD_dictMatchState ?
|
||||
dms->window.dictLimit : 0;
|
||||
const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
|
||||
dms->window.base : NULL;
|
||||
const BYTE* const dictStart = dictMode == ZSTD_dictMatchState ?
|
||||
dictBase + dictStartIndex : NULL;
|
||||
const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
|
||||
dms->window.nextSrc : NULL;
|
||||
const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
|
||||
prefixLowestIndex - (U32)(dictEnd - dictBase) :
|
||||
0;
|
||||
const U32 dictHBitsL = dictMode == ZSTD_dictMatchState ?
|
||||
dictCParams->hashLog : hBitsL;
|
||||
const U32 dictHBitsS = dictMode == ZSTD_dictMatchState ?
|
||||
dictCParams->chainLog : hBitsS;
|
||||
const ZSTD_compressionParameters* const dictCParams = &dms->cParams;
|
||||
const U32* const dictHashLong = dms->hashTable;
|
||||
const U32* const dictHashSmall = dms->chainTable;
|
||||
const U32 dictStartIndex = dms->window.dictLimit;
|
||||
const BYTE* const dictBase = dms->window.base;
|
||||
const BYTE* const dictStart = dictBase + dictStartIndex;
|
||||
const BYTE* const dictEnd = dms->window.nextSrc;
|
||||
const U32 dictIndexDelta = prefixLowestIndex - (U32)(dictEnd - dictBase);
|
||||
const U32 dictHBitsL = dictCParams->hashLog;
|
||||
const U32 dictHBitsS = dictCParams->chainLog;
|
||||
const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictStart));
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_generic");
|
||||
|
||||
assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_dictMatchState_generic");
|
||||
|
||||
/* if a dictionary is attached, it must be within window range */
|
||||
if (dictMode == ZSTD_dictMatchState) {
|
||||
assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex);
|
||||
}
|
||||
assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex);
|
||||
|
||||
/* init */
|
||||
ip += (dictAndPrefixLength == 0);
|
||||
if (dictMode == ZSTD_noDict) {
|
||||
U32 const curr = (U32)(ip - base);
|
||||
U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog);
|
||||
U32 const maxRep = curr - windowLow;
|
||||
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
|
||||
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
|
||||
}
|
||||
if (dictMode == ZSTD_dictMatchState) {
|
||||
/* dictMatchState repCode checks don't currently handle repCode == 0
|
||||
* disabling. */
|
||||
assert(offset_1 <= dictAndPrefixLength);
|
||||
assert(offset_2 <= dictAndPrefixLength);
|
||||
}
|
||||
|
||||
/* dictMatchState repCode checks don't currently handle repCode == 0
|
||||
* disabling. */
|
||||
assert(offset_1 <= dictAndPrefixLength);
|
||||
assert(offset_2 <= dictAndPrefixLength);
|
||||
|
||||
/* Main Search Loop */
|
||||
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
|
||||
@@ -135,29 +317,18 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
const BYTE* matchLong = base + matchIndexL;
|
||||
const BYTE* match = base + matchIndexS;
|
||||
const U32 repIndex = curr + 1 - offset_1;
|
||||
const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
|
||||
&& repIndex < prefixLowestIndex) ?
|
||||
const BYTE* repMatch = (repIndex < prefixLowestIndex) ?
|
||||
dictBase + (repIndex - dictIndexDelta) :
|
||||
base + repIndex;
|
||||
hashLong[h2] = hashSmall[h] = curr; /* update hash tables */
|
||||
|
||||
/* check dictMatchState repcode */
|
||||
if (dictMode == ZSTD_dictMatchState
|
||||
&& ((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
|
||||
/* check repcode */
|
||||
if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
|
||||
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
||||
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
|
||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
|
||||
goto _match_stored;
|
||||
}
|
||||
|
||||
/* check noDict repcode */
|
||||
if ( dictMode == ZSTD_noDict
|
||||
&& ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
|
||||
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
|
||||
goto _match_stored;
|
||||
}
|
||||
|
||||
@@ -169,7 +340,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
|
||||
goto _match_found;
|
||||
}
|
||||
} else if (dictMode == ZSTD_dictMatchState) {
|
||||
} else {
|
||||
/* check dictMatchState long match */
|
||||
U32 const dictMatchIndexL = dictHashLong[dictHL];
|
||||
const BYTE* dictMatchL = dictBase + dictMatchIndexL;
|
||||
@@ -187,7 +358,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
goto _search_next_long;
|
||||
}
|
||||
} else if (dictMode == ZSTD_dictMatchState) {
|
||||
} else {
|
||||
/* check dictMatchState short match */
|
||||
U32 const dictMatchIndexS = dictHashSmall[dictHS];
|
||||
match = dictBase + dictMatchIndexS;
|
||||
@@ -220,7 +391,7 @@ _search_next_long:
|
||||
while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
|
||||
goto _match_found;
|
||||
}
|
||||
} else if (dictMode == ZSTD_dictMatchState) {
|
||||
} else {
|
||||
/* check dict long +1 match */
|
||||
U32 const dictMatchIndexL3 = dictHashLong[dictHLNext];
|
||||
const BYTE* dictMatchL3 = dictBase + dictMatchIndexL3;
|
||||
@@ -234,7 +405,7 @@ _search_next_long:
|
||||
} } }
|
||||
|
||||
/* if no long +1 match, explore the short match we found */
|
||||
if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) {
|
||||
if (matchIndexS < prefixLowestIndex) {
|
||||
mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4;
|
||||
offset = (U32)(curr - matchIndexS);
|
||||
while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
||||
@@ -248,7 +419,7 @@ _match_found:
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
|
||||
|
||||
_match_stored:
|
||||
/* match found */
|
||||
@@ -266,43 +437,27 @@ _match_stored:
|
||||
}
|
||||
|
||||
/* check immediate repcode */
|
||||
if (dictMode == ZSTD_dictMatchState) {
|
||||
while (ip <= ilimit) {
|
||||
U32 const current2 = (U32)(ip-base);
|
||||
U32 const repIndex2 = current2 - offset_2;
|
||||
const BYTE* repMatch2 = dictMode == ZSTD_dictMatchState
|
||||
&& repIndex2 < prefixLowestIndex ?
|
||||
dictBase + repIndex2 - dictIndexDelta :
|
||||
base + repIndex2;
|
||||
if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
|
||||
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
||||
const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;
|
||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;
|
||||
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH);
|
||||
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
|
||||
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
|
||||
ip += repLength2;
|
||||
anchor = ip;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} }
|
||||
|
||||
if (dictMode == ZSTD_noDict) {
|
||||
while ( (ip <= ilimit)
|
||||
&& ( (offset_2>0)
|
||||
& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
|
||||
/* store sequence */
|
||||
size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
||||
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
|
||||
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
|
||||
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, rLength-MINMATCH);
|
||||
ip += rLength;
|
||||
while (ip <= ilimit) {
|
||||
U32 const current2 = (U32)(ip-base);
|
||||
U32 const repIndex2 = current2 - offset_2;
|
||||
const BYTE* repMatch2 = repIndex2 < prefixLowestIndex ?
|
||||
dictBase + repIndex2 - dictIndexDelta :
|
||||
base + repIndex2;
|
||||
if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
|
||||
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
||||
const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;
|
||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;
|
||||
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, repLength2);
|
||||
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
|
||||
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
|
||||
ip += repLength2;
|
||||
anchor = ip;
|
||||
continue; /* faster when present ... (?) */
|
||||
} } }
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* while (ip < ilimit) */
|
||||
|
||||
/* save reps for next block */
|
||||
@@ -313,6 +468,24 @@ _match_stored:
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
#define ZSTD_GEN_DFAST_FN(dictMode, mls) \
|
||||
static size_t ZSTD_compressBlock_doubleFast_##dictMode##_##mls( \
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \
|
||||
void const* src, size_t srcSize) \
|
||||
{ \
|
||||
return ZSTD_compressBlock_doubleFast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls); \
|
||||
}
|
||||
|
||||
ZSTD_GEN_DFAST_FN(noDict, 4)
|
||||
ZSTD_GEN_DFAST_FN(noDict, 5)
|
||||
ZSTD_GEN_DFAST_FN(noDict, 6)
|
||||
ZSTD_GEN_DFAST_FN(noDict, 7)
|
||||
|
||||
ZSTD_GEN_DFAST_FN(dictMatchState, 4)
|
||||
ZSTD_GEN_DFAST_FN(dictMatchState, 5)
|
||||
ZSTD_GEN_DFAST_FN(dictMatchState, 6)
|
||||
ZSTD_GEN_DFAST_FN(dictMatchState, 7)
|
||||
|
||||
|
||||
size_t ZSTD_compressBlock_doubleFast(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
@@ -323,13 +496,13 @@ size_t ZSTD_compressBlock_doubleFast(
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_noDict);
|
||||
return ZSTD_compressBlock_doubleFast_noDict_4(ms, seqStore, rep, src, srcSize);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_noDict);
|
||||
return ZSTD_compressBlock_doubleFast_noDict_5(ms, seqStore, rep, src, srcSize);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_noDict);
|
||||
return ZSTD_compressBlock_doubleFast_noDict_6(ms, seqStore, rep, src, srcSize);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_noDict);
|
||||
return ZSTD_compressBlock_doubleFast_noDict_7(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,13 +516,13 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState(
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_doubleFast_dictMatchState_4(ms, seqStore, rep, src, srcSize);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_doubleFast_dictMatchState_5(ms, seqStore, rep, src, srcSize);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_doubleFast_dictMatchState_6(ms, seqStore, rep, src, srcSize);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_doubleFast_dictMatchState_7(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +558,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
|
||||
/* if extDict is invalidated due to maxDistance, switch to "regular" variant */
|
||||
if (prefixStartIndex == dictStartIndex)
|
||||
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, mls, ZSTD_noDict);
|
||||
return ZSTD_compressBlock_doubleFast(ms, seqStore, rep, src, srcSize);
|
||||
|
||||
/* Search Loop */
|
||||
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
|
||||
@@ -412,7 +585,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
|
||||
} else {
|
||||
if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
|
||||
const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;
|
||||
@@ -423,7 +596,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
|
||||
|
||||
} else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {
|
||||
size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
||||
@@ -448,7 +621,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
}
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
|
||||
|
||||
} else {
|
||||
ip += ((ip-anchor) >> kSearchStrength) + 1;
|
||||
@@ -480,7 +653,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
||||
U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, repLength2);
|
||||
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
|
||||
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
|
||||
ip += repLength2;
|
||||
@@ -498,6 +671,10 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
ZSTD_GEN_DFAST_FN(extDict, 4)
|
||||
ZSTD_GEN_DFAST_FN(extDict, 5)
|
||||
ZSTD_GEN_DFAST_FN(extDict, 6)
|
||||
ZSTD_GEN_DFAST_FN(extDict, 7)
|
||||
|
||||
size_t ZSTD_compressBlock_doubleFast_extDict(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
@@ -508,12 +685,12 @@ size_t ZSTD_compressBlock_doubleFast_extDict(
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 4);
|
||||
return ZSTD_compressBlock_doubleFast_extDict_4(ms, seqStore, rep, src, srcSize);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 5);
|
||||
return ZSTD_compressBlock_doubleFast_extDict_5(ms, seqStore, rep, src, srcSize);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 6);
|
||||
return ZSTD_compressBlock_doubleFast_extDict_6(ms, seqStore, rep, src, srcSize);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 7);
|
||||
return ZSTD_compressBlock_doubleFast_extDict_7(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
}
|
||||
|
||||
+100
-49
@@ -90,16 +90,16 @@ 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_generic(
|
||||
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 mls, U32 const hasStep)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32* const hashTable = ms->hashTable;
|
||||
U32 const hlog = cParams->hashLog;
|
||||
/* support stepSize of 0 */
|
||||
size_t const stepSize = cParams->targetLength + !(cParams->targetLength);
|
||||
size_t const stepSize = hasStep ? (cParams->targetLength + !(cParams->targetLength) + 1) : 2;
|
||||
const BYTE* const base = ms->window.base;
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
||||
@@ -128,6 +128,10 @@ ZSTD_compressBlock_fast_generic(
|
||||
const BYTE* match0;
|
||||
size_t mLength;
|
||||
|
||||
/* ip0 and ip1 are always adjacent. The targetLength skipping and
|
||||
* uncompressibility acceleration is applied to every other position,
|
||||
* matching the behavior of #1562. step therefore represents the gap
|
||||
* between pairs of positions, from ip0 to ip2 or ip1 to ip3. */
|
||||
size_t step;
|
||||
const BYTE* nextStep;
|
||||
const size_t kStepIncr = (1 << (kSearchStrength - 1));
|
||||
@@ -148,9 +152,9 @@ _start: /* Requires: ip0 */
|
||||
nextStep = ip0 + kStepIncr;
|
||||
|
||||
/* calculate positions, ip0 - anchor == 0, so we skip step calc */
|
||||
ip1 = ip0 + stepSize;
|
||||
ip2 = ip1 + stepSize;
|
||||
ip3 = ip2 + stepSize;
|
||||
ip1 = ip0 + 1;
|
||||
ip2 = ip0 + step;
|
||||
ip3 = ip2 + 1;
|
||||
|
||||
if (ip3 >= ilimit) {
|
||||
goto _cleanup;
|
||||
@@ -176,7 +180,7 @@ _start: /* Requires: ip0 */
|
||||
mLength = ip0[-1] == match0[-1];
|
||||
ip0 -= mLength;
|
||||
match0 -= mLength;
|
||||
offcode = 0;
|
||||
offcode = STORE_REPCODE_1;
|
||||
mLength += 4;
|
||||
goto _match;
|
||||
}
|
||||
@@ -230,19 +234,19 @@ _start: /* Requires: ip0 */
|
||||
hash0 = hash1;
|
||||
hash1 = ZSTD_hashPtr(ip2, hlog, mls);
|
||||
|
||||
/* calculate step */
|
||||
if (ip2 >= nextStep) {
|
||||
PREFETCH_L1(ip1 + 64);
|
||||
PREFETCH_L1(ip1 + 128);
|
||||
step++;
|
||||
nextStep += kStepIncr;
|
||||
}
|
||||
|
||||
/* advance to next positions */
|
||||
ip0 = ip1;
|
||||
ip1 = ip2;
|
||||
ip2 = ip2 + step;
|
||||
ip3 = ip2 + step;
|
||||
ip2 = ip0 + step;
|
||||
ip3 = ip1 + step;
|
||||
|
||||
/* calculate step */
|
||||
if (ip2 >= nextStep) {
|
||||
step++;
|
||||
PREFETCH_L1(ip1 + 64);
|
||||
PREFETCH_L1(ip1 + 128);
|
||||
nextStep += kStepIncr;
|
||||
}
|
||||
} while (ip3 < ilimit);
|
||||
|
||||
_cleanup:
|
||||
@@ -263,7 +267,7 @@ _offset: /* Requires: ip0, idx */
|
||||
match0 = base + idx;
|
||||
rep_offset2 = rep_offset1;
|
||||
rep_offset1 = (U32)(ip0-match0);
|
||||
offcode = rep_offset1 + ZSTD_REP_MOVE;
|
||||
offcode = STORE_OFFSET(rep_offset1);
|
||||
mLength = 4;
|
||||
|
||||
/* Count the backwards match length. */
|
||||
@@ -278,7 +282,7 @@ _match: /* Requires: ip0, match0, offcode */
|
||||
/* Count the forward length. */
|
||||
mLength += ZSTD_count(ip0 + mLength, match0 + mLength, iend);
|
||||
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip0 - anchor), anchor, iend, offcode, mLength - MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip0 - anchor), anchor, iend, offcode, mLength);
|
||||
|
||||
ip0 += mLength;
|
||||
anchor = ip0;
|
||||
@@ -302,7 +306,7 @@ _match: /* Requires: ip0, match0, offcode */
|
||||
{ U32 const tmpOff = rep_offset2; rep_offset2 = rep_offset1; rep_offset1 = tmpOff; } /* swap rep_offset2 <=> rep_offset1 */
|
||||
hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);
|
||||
ip0 += rLength;
|
||||
ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, 0 /*offCode*/, rLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, STORE_REPCODE_1, rLength);
|
||||
anchor = ip0;
|
||||
continue; /* faster when present (confirmed on gcc-8) ... (?) */
|
||||
} } }
|
||||
@@ -310,6 +314,23 @@ _match: /* Requires: ip0, match0, offcode */
|
||||
goto _start;
|
||||
}
|
||||
|
||||
#define ZSTD_GEN_FAST_FN(dictMode, mls, step) \
|
||||
static size_t ZSTD_compressBlock_fast_##dictMode##_##mls##_##step( \
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \
|
||||
void const* src, size_t srcSize) \
|
||||
{ \
|
||||
return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls, step); \
|
||||
}
|
||||
|
||||
ZSTD_GEN_FAST_FN(noDict, 4, 1)
|
||||
ZSTD_GEN_FAST_FN(noDict, 5, 1)
|
||||
ZSTD_GEN_FAST_FN(noDict, 6, 1)
|
||||
ZSTD_GEN_FAST_FN(noDict, 7, 1)
|
||||
|
||||
ZSTD_GEN_FAST_FN(noDict, 4, 0)
|
||||
ZSTD_GEN_FAST_FN(noDict, 5, 0)
|
||||
ZSTD_GEN_FAST_FN(noDict, 6, 0)
|
||||
ZSTD_GEN_FAST_FN(noDict, 7, 0)
|
||||
|
||||
size_t ZSTD_compressBlock_fast(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
@@ -317,24 +338,40 @@ size_t ZSTD_compressBlock_fast(
|
||||
{
|
||||
U32 const mls = ms->cParams.minMatch;
|
||||
assert(ms->dictMatchState == NULL);
|
||||
switch(mls)
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7);
|
||||
if (ms->cParams.targetLength > 1) {
|
||||
switch(mls)
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_fast_noDict_4_1(ms, seqStore, rep, src, srcSize);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_fast_noDict_5_1(ms, seqStore, rep, src, srcSize);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_fast_noDict_6_1(ms, seqStore, rep, src, srcSize);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_fast_noDict_7_1(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
} else {
|
||||
switch(mls)
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_fast_noDict_4_0(ms, seqStore, rep, src, srcSize);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_fast_noDict_5_0(ms, seqStore, rep, src, srcSize);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_fast_noDict_6_0(ms, seqStore, rep, src, srcSize);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_fast_noDict_7_0(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize, U32 const mls)
|
||||
void const* src, size_t srcSize, U32 const mls, U32 const hasStep)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32* const hashTable = ms->hashTable;
|
||||
@@ -370,6 +407,8 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||
assert(endIndex - prefixStartIndex <= maxDistance);
|
||||
(void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */
|
||||
|
||||
(void)hasStep; /* not currently specialized on whether it's accelerated */
|
||||
|
||||
/* ensure there will be no underflow
|
||||
* when translating a dict index into a local index */
|
||||
assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
|
||||
@@ -400,7 +439,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
|
||||
} else if ( (matchIndex <= prefixStartIndex) ) {
|
||||
size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls);
|
||||
U32 const dictMatchIndex = dictHashTable[dictHash];
|
||||
@@ -420,7 +459,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||
} /* catch up */
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
|
||||
}
|
||||
} else if (MEM_read32(match) != MEM_read32(ip)) {
|
||||
/* it's not a match, and we're not going to check the dictionary */
|
||||
@@ -435,7 +474,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||
&& (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
||||
offset_2 = offset_1;
|
||||
offset_1 = offset;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
|
||||
}
|
||||
|
||||
/* match found */
|
||||
@@ -460,7 +499,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
||||
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, repLength2);
|
||||
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
|
||||
ip += repLength2;
|
||||
anchor = ip;
|
||||
@@ -479,6 +518,12 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
|
||||
ZSTD_GEN_FAST_FN(dictMatchState, 4, 0)
|
||||
ZSTD_GEN_FAST_FN(dictMatchState, 5, 0)
|
||||
ZSTD_GEN_FAST_FN(dictMatchState, 6, 0)
|
||||
ZSTD_GEN_FAST_FN(dictMatchState, 7, 0)
|
||||
|
||||
size_t ZSTD_compressBlock_fast_dictMatchState(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize)
|
||||
@@ -489,20 +534,20 @@ size_t ZSTD_compressBlock_fast_dictMatchState(
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 4);
|
||||
return ZSTD_compressBlock_fast_dictMatchState_4_0(ms, seqStore, rep, src, srcSize);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 5);
|
||||
return ZSTD_compressBlock_fast_dictMatchState_5_0(ms, seqStore, rep, src, srcSize);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 6);
|
||||
return ZSTD_compressBlock_fast_dictMatchState_6_0(ms, seqStore, rep, src, srcSize);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 7);
|
||||
return ZSTD_compressBlock_fast_dictMatchState_7_0(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static 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)
|
||||
void const* src, size_t srcSize, U32 const mls, U32 const hasStep)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32* const hashTable = ms->hashTable;
|
||||
@@ -526,11 +571,13 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
const BYTE* const ilimit = iend - 8;
|
||||
U32 offset_1=rep[0], offset_2=rep[1];
|
||||
|
||||
(void)hasStep; /* not currently specialized on whether it's accelerated */
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_fast_extDict_generic (offset_1=%u)", offset_1);
|
||||
|
||||
/* switch to "regular" variant if extDict is invalidated due to maxDistance */
|
||||
if (prefixStartIndex == dictStartIndex)
|
||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, mls);
|
||||
return ZSTD_compressBlock_fast(ms, seqStore, rep, src, srcSize);
|
||||
|
||||
/* Search Loop */
|
||||
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
|
||||
@@ -551,7 +598,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
||||
size_t const rLength = ZSTD_count_2segments(ip+1 +4, repMatch +4, iend, repMatchEnd, prefixStart) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, rLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, rLength);
|
||||
ip += rLength;
|
||||
anchor = ip;
|
||||
} else {
|
||||
@@ -567,7 +614,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
size_t mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4;
|
||||
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
||||
offset_2 = offset_1; offset_1 = offset; /* update offset history */
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
|
||||
ip += mLength;
|
||||
anchor = ip;
|
||||
} }
|
||||
@@ -586,7 +633,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
||||
{ U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; } /* swap offset_2 <=> offset_1 */
|
||||
ZSTD_storeSeq(seqStore, 0 /*litlen*/, anchor, iend, 0 /*offcode*/, repLength2-MINMATCH);
|
||||
ZSTD_storeSeq(seqStore, 0 /*litlen*/, anchor, iend, STORE_REPCODE_1, repLength2);
|
||||
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
|
||||
ip += repLength2;
|
||||
anchor = ip;
|
||||
@@ -603,6 +650,10 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
ZSTD_GEN_FAST_FN(extDict, 4, 0)
|
||||
ZSTD_GEN_FAST_FN(extDict, 5, 0)
|
||||
ZSTD_GEN_FAST_FN(extDict, 6, 0)
|
||||
ZSTD_GEN_FAST_FN(extDict, 7, 0)
|
||||
|
||||
size_t ZSTD_compressBlock_fast_extDict(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
@@ -613,12 +664,12 @@ size_t ZSTD_compressBlock_fast_extDict(
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 4);
|
||||
return ZSTD_compressBlock_fast_extDict_4_0(ms, seqStore, rep, src, srcSize);
|
||||
case 5 :
|
||||
return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 5);
|
||||
return ZSTD_compressBlock_fast_extDict_5_0(ms, seqStore, rep, src, srcSize);
|
||||
case 6 :
|
||||
return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 6);
|
||||
return ZSTD_compressBlock_fast_extDict_6_0(ms, seqStore, rep, src, srcSize);
|
||||
case 7 :
|
||||
return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 7);
|
||||
return ZSTD_compressBlock_fast_extDict_7_0(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
}
|
||||
|
||||
+284
-339
@@ -93,7 +93,7 @@ ZSTD_insertDUBT1(const ZSTD_matchState_t* ms,
|
||||
assert(curr >= btLow);
|
||||
assert(ip < iend); /* condition for ZSTD_count */
|
||||
|
||||
while (nbCompares-- && (matchIndex > windowLow)) {
|
||||
for (; nbCompares && (matchIndex > windowLow); --nbCompares) {
|
||||
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
||||
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
||||
assert(matchIndex < curr);
|
||||
@@ -185,7 +185,7 @@ ZSTD_DUBT_findBetterDictMatch (
|
||||
(void)dictMode;
|
||||
assert(dictMode == ZSTD_dictMatchState);
|
||||
|
||||
while (nbCompares-- && (dictMatchIndex > dictLowLimit)) {
|
||||
for (; nbCompares && (dictMatchIndex > dictLowLimit); --nbCompares) {
|
||||
U32* const nextPtr = dictBt + 2*(dictMatchIndex & btMask);
|
||||
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
||||
const BYTE* match = dictBase + dictMatchIndex;
|
||||
@@ -197,8 +197,8 @@ ZSTD_DUBT_findBetterDictMatch (
|
||||
U32 matchIndex = dictMatchIndex + dictIndexDelta;
|
||||
if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) {
|
||||
DEBUGLOG(9, "ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)",
|
||||
curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + curr - matchIndex, dictMatchIndex, matchIndex);
|
||||
bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex;
|
||||
curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, STORE_OFFSET(curr - matchIndex), dictMatchIndex, matchIndex);
|
||||
bestLength = matchLength, *offsetPtr = STORE_OFFSET(curr - matchIndex);
|
||||
}
|
||||
if (ip+matchLength == iend) { /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */
|
||||
break; /* drop, to guarantee consistency (miss a little bit of compression) */
|
||||
@@ -218,7 +218,7 @@ ZSTD_DUBT_findBetterDictMatch (
|
||||
}
|
||||
|
||||
if (bestLength >= MINMATCH) {
|
||||
U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
|
||||
U32 const mIndex = curr - (U32)STORED_OFFSET(*offsetPtr); (void)mIndex;
|
||||
DEBUGLOG(8, "ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
|
||||
curr, (U32)bestLength, (U32)*offsetPtr, mIndex);
|
||||
}
|
||||
@@ -309,7 +309,7 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
|
||||
matchIndex = hashTable[h];
|
||||
hashTable[h] = curr; /* Update Hash Table */
|
||||
|
||||
while (nbCompares-- && (matchIndex > windowLow)) {
|
||||
for (; nbCompares && (matchIndex > windowLow); --nbCompares) {
|
||||
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
||||
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
||||
const BYTE* match;
|
||||
@@ -328,7 +328,7 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
|
||||
if (matchLength > matchEndIdx - matchIndex)
|
||||
matchEndIdx = matchIndex + (U32)matchLength;
|
||||
if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
|
||||
bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex;
|
||||
bestLength = matchLength, *offsetPtr = STORE_OFFSET(curr - matchIndex);
|
||||
if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
|
||||
if (dictMode == ZSTD_dictMatchState) {
|
||||
nbCompares = 0; /* in addition to avoiding checking any
|
||||
@@ -357,6 +357,7 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
|
||||
|
||||
*smallerPtr = *largerPtr = 0;
|
||||
|
||||
assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */
|
||||
if (dictMode == ZSTD_dictMatchState && nbCompares) {
|
||||
bestLength = ZSTD_DUBT_findBetterDictMatch(
|
||||
ms, ip, iend,
|
||||
@@ -367,7 +368,7 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
|
||||
assert(matchEndIdx > curr+8); /* ensure nextToUpdate is increased */
|
||||
ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
|
||||
if (bestLength >= MINMATCH) {
|
||||
U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
|
||||
U32 const mIndex = curr - (U32)STORED_OFFSET(*offsetPtr); (void)mIndex;
|
||||
DEBUGLOG(8, "ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
|
||||
curr, (U32)bestLength, (U32)*offsetPtr, mIndex);
|
||||
}
|
||||
@@ -390,54 +391,6 @@ ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms,
|
||||
return ZSTD_DUBT_findBestMatch(ms, ip, iLimit, offsetPtr, mls, dictMode);
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
ZSTD_BtFindBestMatch_selectMLS ( ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
switch(ms->cParams.minMatch)
|
||||
{
|
||||
default : /* includes case 3 */
|
||||
case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict);
|
||||
case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_BtFindBestMatch_dictMatchState_selectMLS (
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
switch(ms->cParams.minMatch)
|
||||
{
|
||||
default : /* includes case 3 */
|
||||
case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState);
|
||||
case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_BtFindBestMatch_extDict_selectMLS (
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
switch(ms->cParams.minMatch)
|
||||
{
|
||||
default : /* includes case 3 */
|
||||
case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict);
|
||||
case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Dedicated dict search
|
||||
***********************************/
|
||||
@@ -464,7 +417,7 @@ void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const B
|
||||
U32 const hashLog = ms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG;
|
||||
U32* const tmpHashTable = hashTable;
|
||||
U32* const tmpChainTable = hashTable + ((size_t)1 << hashLog);
|
||||
U32 const tmpChainSize = ((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog;
|
||||
U32 const tmpChainSize = (U32)((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog;
|
||||
U32 const tmpMinChain = tmpChainSize < target ? target - tmpChainSize : idx;
|
||||
U32 hashIdx;
|
||||
|
||||
@@ -608,7 +561,7 @@ size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nb
|
||||
/* save best solution */
|
||||
if (currentMl > ml) {
|
||||
ml = currentMl;
|
||||
*offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE;
|
||||
*offsetPtr = STORE_OFFSET(curr - (matchIndex + ddsIndexDelta));
|
||||
if (ip+currentMl == iLimit) {
|
||||
/* best possible, avoids read overflow on next attempt */
|
||||
return ml;
|
||||
@@ -645,7 +598,7 @@ size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nb
|
||||
/* save best solution */
|
||||
if (currentMl > ml) {
|
||||
ml = currentMl;
|
||||
*offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE;
|
||||
*offsetPtr = STORE_OFFSET(curr - (matchIndex + ddsIndexDelta));
|
||||
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
|
||||
}
|
||||
}
|
||||
@@ -692,7 +645,7 @@ U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) {
|
||||
|
||||
/* inlining is important to hardwire a hot branch (template emulation) */
|
||||
FORCE_INLINE_TEMPLATE
|
||||
size_t ZSTD_HcFindBestMatch_generic (
|
||||
size_t ZSTD_HcFindBestMatch(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* const ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr,
|
||||
@@ -750,7 +703,7 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
/* save best solution */
|
||||
if (currentMl > ml) {
|
||||
ml = currentMl;
|
||||
*offsetPtr = curr - matchIndex + ZSTD_REP_MOVE;
|
||||
*offsetPtr = STORE_OFFSET(curr - matchIndex);
|
||||
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
|
||||
}
|
||||
|
||||
@@ -758,6 +711,7 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
|
||||
}
|
||||
|
||||
assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */
|
||||
if (dictMode == ZSTD_dedicatedDictSearch) {
|
||||
ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts, dms,
|
||||
ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);
|
||||
@@ -784,7 +738,8 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
/* save best solution */
|
||||
if (currentMl > ml) {
|
||||
ml = currentMl;
|
||||
*offsetPtr = curr - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE;
|
||||
assert(curr > matchIndex + dmsIndexDelta);
|
||||
*offsetPtr = STORE_OFFSET(curr - (matchIndex + dmsIndexDelta));
|
||||
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
|
||||
}
|
||||
|
||||
@@ -797,70 +752,6 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
return ml;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS (
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
switch(ms->cParams.minMatch)
|
||||
{
|
||||
default : /* includes case 3 */
|
||||
case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict);
|
||||
case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_HcFindBestMatch_dictMatchState_selectMLS (
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
switch(ms->cParams.minMatch)
|
||||
{
|
||||
default : /* includes case 3 */
|
||||
case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState);
|
||||
case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS (
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
switch(ms->cParams.minMatch)
|
||||
{
|
||||
default : /* includes case 3 */
|
||||
case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dedicatedDictSearch);
|
||||
case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dedicatedDictSearch);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dedicatedDictSearch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
switch(ms->cParams.minMatch)
|
||||
{
|
||||
default : /* includes case 3 */
|
||||
case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict);
|
||||
case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict);
|
||||
}
|
||||
}
|
||||
|
||||
/* *********************************
|
||||
* (SIMD) Row-based matchfinder
|
||||
***********************************/
|
||||
@@ -881,8 +772,14 @@ typedef U64 ZSTD_VecMask; /* Clarifies when we are interacting with a U64 repr
|
||||
static U32 ZSTD_VecMask_next(ZSTD_VecMask val) {
|
||||
assert(val != 0);
|
||||
# if defined(_MSC_VER) && defined(_WIN64)
|
||||
unsigned long r=0;
|
||||
return _BitScanForward64(&r, val) ? (U32)r : 0; /* _BitScanForward64 not defined outside of x86/64 */
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanForward64(&r, val);
|
||||
return (U32)(r);
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# elif (defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))
|
||||
if (sizeof(size_t) == 4) {
|
||||
U32 mostSignificantWord = (U32)(val >> 32);
|
||||
@@ -1056,7 +953,7 @@ FORCE_INLINE_TEMPLATE void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const
|
||||
const U32 kMaxMatchEndPositionsToUpdate = 32;
|
||||
|
||||
if (useCache) {
|
||||
/* Only skip positions when using hash cache, i.e.
|
||||
/* Only skip positions when using hash cache, i.e.
|
||||
* if we are loading a dict, don't skip anything.
|
||||
* If we decide to skip, then we only update a set number
|
||||
* of positions at the beginning and end of the match.
|
||||
@@ -1078,7 +975,7 @@ FORCE_INLINE_TEMPLATE void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const
|
||||
* processing.
|
||||
*/
|
||||
void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip) {
|
||||
const U32 rowLog = MAX(MIN(ms->cParams.searchLog, 6), 4);
|
||||
const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6);
|
||||
const U32 rowMask = (1u << rowLog) - 1;
|
||||
const U32 mls = MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */);
|
||||
|
||||
@@ -1086,47 +983,45 @@ void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip) {
|
||||
ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 0 /* dont use cache */);
|
||||
}
|
||||
|
||||
#if defined(ZSTD_ARCH_X86_SSE2)
|
||||
FORCE_INLINE_TEMPLATE ZSTD_VecMask
|
||||
ZSTD_row_getSSEMask(int nbChunks, const BYTE* const src, const BYTE tag, const U32 head)
|
||||
{
|
||||
const __m128i comparisonMask = _mm_set1_epi8((char)tag);
|
||||
int matches[4] = {0};
|
||||
int i;
|
||||
assert(nbChunks == 1 || nbChunks == 2 || nbChunks == 4);
|
||||
for (i=0; i<nbChunks; i++) {
|
||||
const __m128i chunk = _mm_loadu_si128((const __m128i*)(const void*)(src + 16*i));
|
||||
const __m128i equalMask = _mm_cmpeq_epi8(chunk, comparisonMask);
|
||||
matches[i] = _mm_movemask_epi8(equalMask);
|
||||
}
|
||||
if (nbChunks == 1) return ZSTD_rotateRight_U16((U16)matches[0], head);
|
||||
if (nbChunks == 2) return ZSTD_rotateRight_U32((U32)matches[1] << 16 | (U32)matches[0], head);
|
||||
assert(nbChunks == 4);
|
||||
return ZSTD_rotateRight_U64((U64)matches[3] << 48 | (U64)matches[2] << 32 | (U64)matches[1] << 16 | (U64)matches[0], head);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns a ZSTD_VecMask (U32) that has the nth bit set to 1 if the newly-computed "tag" matches
|
||||
* the hash at the nth position in a row of the tagTable.
|
||||
* Each row is a circular buffer beginning at the value of "head". So we must rotate the "matches" bitfield
|
||||
* to match up with the actual layout of the entries within the hashTable */
|
||||
FORCE_INLINE_TEMPLATE
|
||||
ZSTD_VecMask ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 head, const U32 rowEntries) {
|
||||
FORCE_INLINE_TEMPLATE ZSTD_VecMask
|
||||
ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 head, const U32 rowEntries)
|
||||
{
|
||||
const BYTE* const src = tagRow + ZSTD_ROW_HASH_TAG_OFFSET;
|
||||
assert((rowEntries == 16) || (rowEntries == 32) || rowEntries == 64);
|
||||
assert(rowEntries <= ZSTD_ROW_HASH_MAX_ENTRIES);
|
||||
|
||||
#if defined(ZSTD_ARCH_X86_SSE2)
|
||||
if (rowEntries == 16) {
|
||||
const __m128i chunk = _mm_loadu_si128((const __m128i*)(const void*)src);
|
||||
const __m128i equalMask = _mm_cmpeq_epi8(chunk, _mm_set1_epi8(tag));
|
||||
const U16 matches = (U16)_mm_movemask_epi8(equalMask);
|
||||
return ZSTD_rotateRight_U16(matches, head);
|
||||
} else if (rowEntries == 32) {
|
||||
const __m128i chunk0 = _mm_loadu_si128((const __m128i*)(const void*)&src[0]);
|
||||
const __m128i chunk1 = _mm_loadu_si128((const __m128i*)(const void*)&src[16]);
|
||||
const __m128i equalMask0 = _mm_cmpeq_epi8(chunk0, _mm_set1_epi8(tag));
|
||||
const __m128i equalMask1 = _mm_cmpeq_epi8(chunk1, _mm_set1_epi8(tag));
|
||||
const U32 lo = (U32)_mm_movemask_epi8(equalMask0);
|
||||
const U32 hi = (U32)_mm_movemask_epi8(equalMask1);
|
||||
return ZSTD_rotateRight_U32((hi << 16) | lo, head);
|
||||
} else { /* rowEntries == 64 */
|
||||
const __m128i chunk0 = _mm_loadu_si128((const __m128i*)(const void*)&src[0]);
|
||||
const __m128i chunk1 = _mm_loadu_si128((const __m128i*)(const void*)&src[16]);
|
||||
const __m128i chunk2 = _mm_loadu_si128((const __m128i*)(const void*)&src[32]);
|
||||
const __m128i chunk3 = _mm_loadu_si128((const __m128i*)(const void*)&src[48]);
|
||||
const __m128i comparisonMask = _mm_set1_epi8(tag);
|
||||
const __m128i equalMask0 = _mm_cmpeq_epi8(chunk0, comparisonMask);
|
||||
const __m128i equalMask1 = _mm_cmpeq_epi8(chunk1, comparisonMask);
|
||||
const __m128i equalMask2 = _mm_cmpeq_epi8(chunk2, comparisonMask);
|
||||
const __m128i equalMask3 = _mm_cmpeq_epi8(chunk3, comparisonMask);
|
||||
const U64 mask0 = (U64)_mm_movemask_epi8(equalMask0);
|
||||
const U64 mask1 = (U64)_mm_movemask_epi8(equalMask1);
|
||||
const U64 mask2 = (U64)_mm_movemask_epi8(equalMask2);
|
||||
const U64 mask3 = (U64)_mm_movemask_epi8(equalMask3);
|
||||
return ZSTD_rotateRight_U64((mask3 << 48) | (mask2 << 32) | (mask1 << 16) | mask0, head);
|
||||
}
|
||||
#else
|
||||
# if defined(ZSTD_ARCH_ARM_NEON)
|
||||
|
||||
return ZSTD_row_getSSEMask(rowEntries / 16, src, tag, head);
|
||||
|
||||
#else /* SW or NEON-LE */
|
||||
|
||||
# if defined(ZSTD_ARCH_ARM_NEON)
|
||||
/* This NEON path only works for little endian - otherwise use SWAR below */
|
||||
if (MEM_isLittleEndian()) {
|
||||
if (rowEntries == 16) {
|
||||
const uint8x16_t chunk = vld1q_u8(src);
|
||||
@@ -1170,9 +1065,9 @@ ZSTD_VecMask ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, con
|
||||
return ZSTD_rotateRight_U64(matches, head);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
{ /* SWAR */
|
||||
const size_t chunkSize = sizeof(size_t);
|
||||
# endif /* ZSTD_ARCH_ARM_NEON */
|
||||
/* SWAR */
|
||||
{ const size_t chunkSize = sizeof(size_t);
|
||||
const size_t shiftAmount = ((chunkSize * 8) - chunkSize);
|
||||
const size_t xFF = ~((size_t)0);
|
||||
const size_t x01 = xFF / 0xFF;
|
||||
@@ -1231,7 +1126,7 @@ ZSTD_VecMask ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, con
|
||||
* - Pick the longest match.
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE
|
||||
size_t ZSTD_RowFindBestMatch_generic (
|
||||
size_t ZSTD_RowFindBestMatch(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* const ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr,
|
||||
@@ -1350,12 +1245,13 @@ size_t ZSTD_RowFindBestMatch_generic (
|
||||
/* Save best solution */
|
||||
if (currentMl > ml) {
|
||||
ml = currentMl;
|
||||
*offsetPtr = curr - matchIndex + ZSTD_REP_MOVE;
|
||||
*offsetPtr = STORE_OFFSET(curr - matchIndex);
|
||||
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */
|
||||
if (dictMode == ZSTD_dedicatedDictSearch) {
|
||||
ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts + ddsExtraAttempts, dms,
|
||||
ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);
|
||||
@@ -1397,7 +1293,8 @@ size_t ZSTD_RowFindBestMatch_generic (
|
||||
|
||||
if (currentMl > ml) {
|
||||
ml = currentMl;
|
||||
*offsetPtr = curr - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE;
|
||||
assert(curr > matchIndex + dmsIndexDelta);
|
||||
*offsetPtr = STORE_OFFSET(curr - (matchIndex + dmsIndexDelta));
|
||||
if (ip+currentMl == iLimit) break;
|
||||
}
|
||||
}
|
||||
@@ -1406,88 +1303,175 @@ size_t ZSTD_RowFindBestMatch_generic (
|
||||
return ml;
|
||||
}
|
||||
|
||||
/* Inlining is important to hardwire a hot branch (template emulation) */
|
||||
FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_selectMLS (
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
const ZSTD_dictMode_e dictMode, size_t* offsetPtr, const U32 rowLog)
|
||||
{
|
||||
switch(ms->cParams.minMatch)
|
||||
{
|
||||
default : /* includes case 3 */
|
||||
case 4 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, dictMode, rowLog);
|
||||
case 5 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, dictMode, rowLog);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, dictMode, rowLog);
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_selectRowLog (
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 6);
|
||||
switch(cappedSearchLog)
|
||||
{
|
||||
default :
|
||||
case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_noDict, offsetPtr, 4);
|
||||
case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_noDict, offsetPtr, 5);
|
||||
case 6 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_noDict, offsetPtr, 6);
|
||||
}
|
||||
}
|
||||
typedef size_t (*searchMax_f)(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_dictMatchState_selectRowLog(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 6);
|
||||
switch(cappedSearchLog)
|
||||
{
|
||||
default :
|
||||
case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dictMatchState, offsetPtr, 4);
|
||||
case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dictMatchState, offsetPtr, 5);
|
||||
case 6 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dictMatchState, offsetPtr, 6);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This struct contains the functions necessary for lazy to search.
|
||||
* Currently, that is only searchMax. However, it is still valuable to have the
|
||||
* VTable because this makes it easier to add more functions to the VTable later.
|
||||
*
|
||||
* TODO: The start of the search function involves loading and calculating a
|
||||
* bunch of constants from the ZSTD_matchState_t. These computations could be
|
||||
* done in an initialization function, and saved somewhere in the match state.
|
||||
* Then we could pass a pointer to the saved state instead of the match state,
|
||||
* and avoid duplicate computations.
|
||||
*
|
||||
* TODO: Move the match re-winding into searchMax. This improves compression
|
||||
* ratio, and unlocks further simplifications with the next TODO.
|
||||
*
|
||||
* TODO: Try moving the repcode search into searchMax. After the re-winding
|
||||
* and repcode search are in searchMax, there is no more logic in the match
|
||||
* finder loop that requires knowledge about the dictMode. So we should be
|
||||
* able to avoid force inlining it, and we can join the extDict loop with
|
||||
* the single segment loop. It should go in searchMax instead of its own
|
||||
* function to avoid having multiple virtual function calls per search.
|
||||
*/
|
||||
typedef struct {
|
||||
searchMax_f searchMax;
|
||||
} ZSTD_LazyVTable;
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_dedicatedDictSearch_selectRowLog(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 6);
|
||||
switch(cappedSearchLog)
|
||||
{
|
||||
default :
|
||||
case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dedicatedDictSearch, offsetPtr, 4);
|
||||
case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dedicatedDictSearch, offsetPtr, 5);
|
||||
case 6 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dedicatedDictSearch, offsetPtr, 6);
|
||||
}
|
||||
}
|
||||
#define GEN_ZSTD_BT_VTABLE(dictMode, mls) \
|
||||
static size_t ZSTD_BtFindBestMatch_##dictMode##_##mls( \
|
||||
ZSTD_matchState_t* ms, \
|
||||
const BYTE* ip, const BYTE* const iLimit, \
|
||||
size_t* offsetPtr) \
|
||||
{ \
|
||||
assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \
|
||||
return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode); \
|
||||
} \
|
||||
static const ZSTD_LazyVTable ZSTD_BtVTable_##dictMode##_##mls = { \
|
||||
ZSTD_BtFindBestMatch_##dictMode##_##mls \
|
||||
};
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_extDict_selectRowLog (
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
size_t* offsetPtr)
|
||||
{
|
||||
const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 6);
|
||||
switch(cappedSearchLog)
|
||||
{
|
||||
default :
|
||||
case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_extDict, offsetPtr, 4);
|
||||
case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_extDict, offsetPtr, 5);
|
||||
case 6 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_extDict, offsetPtr, 6);
|
||||
}
|
||||
}
|
||||
#define GEN_ZSTD_HC_VTABLE(dictMode, mls) \
|
||||
static size_t ZSTD_HcFindBestMatch_##dictMode##_##mls( \
|
||||
ZSTD_matchState_t* ms, \
|
||||
const BYTE* ip, const BYTE* const iLimit, \
|
||||
size_t* offsetPtr) \
|
||||
{ \
|
||||
assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \
|
||||
return ZSTD_HcFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode); \
|
||||
} \
|
||||
static const ZSTD_LazyVTable ZSTD_HcVTable_##dictMode##_##mls = { \
|
||||
ZSTD_HcFindBestMatch_##dictMode##_##mls \
|
||||
};
|
||||
|
||||
#define GEN_ZSTD_ROW_VTABLE(dictMode, mls, rowLog) \
|
||||
static size_t ZSTD_RowFindBestMatch_##dictMode##_##mls##_##rowLog( \
|
||||
ZSTD_matchState_t* ms, \
|
||||
const BYTE* ip, const BYTE* const iLimit, \
|
||||
size_t* offsetPtr) \
|
||||
{ \
|
||||
assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \
|
||||
assert(MAX(4, MIN(6, ms->cParams.searchLog)) == rowLog); \
|
||||
return ZSTD_RowFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode, rowLog); \
|
||||
} \
|
||||
static const ZSTD_LazyVTable ZSTD_RowVTable_##dictMode##_##mls##_##rowLog = { \
|
||||
ZSTD_RowFindBestMatch_##dictMode##_##mls##_##rowLog \
|
||||
};
|
||||
|
||||
#define ZSTD_FOR_EACH_ROWLOG(X, dictMode, mls) \
|
||||
X(dictMode, mls, 4) \
|
||||
X(dictMode, mls, 5) \
|
||||
X(dictMode, mls, 6)
|
||||
|
||||
#define ZSTD_FOR_EACH_MLS_ROWLOG(X, dictMode) \
|
||||
ZSTD_FOR_EACH_ROWLOG(X, dictMode, 4) \
|
||||
ZSTD_FOR_EACH_ROWLOG(X, dictMode, 5) \
|
||||
ZSTD_FOR_EACH_ROWLOG(X, dictMode, 6)
|
||||
|
||||
#define ZSTD_FOR_EACH_MLS(X, dictMode) \
|
||||
X(dictMode, 4) \
|
||||
X(dictMode, 5) \
|
||||
X(dictMode, 6)
|
||||
|
||||
#define ZSTD_FOR_EACH_DICT_MODE(X, ...) \
|
||||
X(__VA_ARGS__, noDict) \
|
||||
X(__VA_ARGS__, extDict) \
|
||||
X(__VA_ARGS__, dictMatchState) \
|
||||
X(__VA_ARGS__, dedicatedDictSearch)
|
||||
|
||||
/* Generate Row VTables for each combination of (dictMode, mls, rowLog) */
|
||||
ZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS_ROWLOG, GEN_ZSTD_ROW_VTABLE)
|
||||
/* Generate Binary Tree VTables for each combination of (dictMode, mls) */
|
||||
ZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_BT_VTABLE)
|
||||
/* Generate Hash Chain VTables for each combination of (dictMode, mls) */
|
||||
ZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_HC_VTABLE)
|
||||
|
||||
#define GEN_ZSTD_BT_VTABLE_ARRAY(dictMode) \
|
||||
{ \
|
||||
&ZSTD_BtVTable_##dictMode##_4, \
|
||||
&ZSTD_BtVTable_##dictMode##_5, \
|
||||
&ZSTD_BtVTable_##dictMode##_6 \
|
||||
}
|
||||
|
||||
#define GEN_ZSTD_HC_VTABLE_ARRAY(dictMode) \
|
||||
{ \
|
||||
&ZSTD_HcVTable_##dictMode##_4, \
|
||||
&ZSTD_HcVTable_##dictMode##_5, \
|
||||
&ZSTD_HcVTable_##dictMode##_6 \
|
||||
}
|
||||
|
||||
#define GEN_ZSTD_ROW_VTABLE_ARRAY_(dictMode, mls) \
|
||||
{ \
|
||||
&ZSTD_RowVTable_##dictMode##_##mls##_4, \
|
||||
&ZSTD_RowVTable_##dictMode##_##mls##_5, \
|
||||
&ZSTD_RowVTable_##dictMode##_##mls##_6 \
|
||||
}
|
||||
|
||||
#define GEN_ZSTD_ROW_VTABLE_ARRAY(dictMode) \
|
||||
{ \
|
||||
GEN_ZSTD_ROW_VTABLE_ARRAY_(dictMode, 4), \
|
||||
GEN_ZSTD_ROW_VTABLE_ARRAY_(dictMode, 5), \
|
||||
GEN_ZSTD_ROW_VTABLE_ARRAY_(dictMode, 6) \
|
||||
}
|
||||
|
||||
#define GEN_ZSTD_VTABLE_ARRAY(X) \
|
||||
{ \
|
||||
X(noDict), \
|
||||
X(extDict), \
|
||||
X(dictMatchState), \
|
||||
X(dedicatedDictSearch) \
|
||||
}
|
||||
|
||||
/* *******************************
|
||||
* Common parser - lazy strategy
|
||||
*********************************/
|
||||
typedef enum { search_hashChain=0, search_binaryTree=1, search_rowHash=2 } searchMethod_e;
|
||||
|
||||
/**
|
||||
* This table is indexed first by the four ZSTD_dictMode_e values, and then
|
||||
* by the two searchMethod_e values. NULLs are placed for configurations
|
||||
* that should never occur (extDict modes go to the other implementation
|
||||
* below and there is no DDSS for binary tree search yet).
|
||||
*/
|
||||
|
||||
static ZSTD_LazyVTable const*
|
||||
ZSTD_selectLazyVTable(ZSTD_matchState_t const* ms, searchMethod_e searchMethod, ZSTD_dictMode_e dictMode)
|
||||
{
|
||||
/* Fill the Hc/Bt VTable arrays with the right functions for the (dictMode, mls) combination. */
|
||||
ZSTD_LazyVTable const* const hcVTables[4][3] = GEN_ZSTD_VTABLE_ARRAY(GEN_ZSTD_HC_VTABLE_ARRAY);
|
||||
ZSTD_LazyVTable const* const btVTables[4][3] = GEN_ZSTD_VTABLE_ARRAY(GEN_ZSTD_BT_VTABLE_ARRAY);
|
||||
/* Fill the Row VTable array with the right functions for the (dictMode, mls, rowLog) combination. */
|
||||
ZSTD_LazyVTable const* const rowVTables[4][3][3] = GEN_ZSTD_VTABLE_ARRAY(GEN_ZSTD_ROW_VTABLE_ARRAY);
|
||||
|
||||
U32 const mls = MAX(4, MIN(6, ms->cParams.minMatch));
|
||||
U32 const rowLog = MAX(4, MIN(6, ms->cParams.searchLog));
|
||||
switch (searchMethod) {
|
||||
case search_hashChain:
|
||||
return hcVTables[dictMode][mls - 4];
|
||||
case search_binaryTree:
|
||||
return btVTables[dictMode][mls - 4];
|
||||
case search_rowHash:
|
||||
return rowVTables[dictMode][mls - 4][rowLog - 4];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
ZSTD_compressBlock_lazy_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore,
|
||||
@@ -1500,46 +1484,12 @@ ZSTD_compressBlock_lazy_generic(
|
||||
const BYTE* ip = istart;
|
||||
const BYTE* anchor = istart;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* const ilimit = searchMethod == search_rowHash ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;
|
||||
const BYTE* const ilimit = (searchMethod == search_rowHash) ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;
|
||||
const BYTE* const base = ms->window.base;
|
||||
const U32 prefixLowestIndex = ms->window.dictLimit;
|
||||
const BYTE* const prefixLowest = base + prefixLowestIndex;
|
||||
const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5;
|
||||
|
||||
typedef size_t (*searchMax_f)(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
|
||||
|
||||
/**
|
||||
* This table is indexed first by the four ZSTD_dictMode_e values, and then
|
||||
* by the two searchMethod_e values. NULLs are placed for configurations
|
||||
* that should never occur (extDict modes go to the other implementation
|
||||
* below and there is no DDSS for binary tree search yet).
|
||||
*/
|
||||
const searchMax_f searchFuncs[4][3] = {
|
||||
{
|
||||
ZSTD_HcFindBestMatch_selectMLS,
|
||||
ZSTD_BtFindBestMatch_selectMLS,
|
||||
ZSTD_RowFindBestMatch_selectRowLog
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
ZSTD_HcFindBestMatch_dictMatchState_selectMLS,
|
||||
ZSTD_BtFindBestMatch_dictMatchState_selectMLS,
|
||||
ZSTD_RowFindBestMatch_dictMatchState_selectRowLog
|
||||
},
|
||||
{
|
||||
ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS,
|
||||
NULL,
|
||||
ZSTD_RowFindBestMatch_dedicatedDictSearch_selectRowLog
|
||||
}
|
||||
};
|
||||
|
||||
searchMax_f const searchMax = searchFuncs[dictMode][(int)searchMethod];
|
||||
searchMax_f const searchMax = ZSTD_selectLazyVTable(ms, searchMethod, dictMode)->searchMax;
|
||||
U32 offset_1 = rep[0], offset_2 = rep[1], savedOffset=0;
|
||||
|
||||
const int isDMS = dictMode == ZSTD_dictMatchState;
|
||||
@@ -1574,6 +1524,7 @@ ZSTD_compressBlock_lazy_generic(
|
||||
}
|
||||
|
||||
if (searchMethod == search_rowHash) {
|
||||
const U32 rowLog = MAX(4, MIN(6, ms->cParams.searchLog));
|
||||
ZSTD_row_fillHashCache(ms, base, rowLog,
|
||||
MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */),
|
||||
ms->nextToUpdate, ilimit);
|
||||
@@ -1588,8 +1539,9 @@ ZSTD_compressBlock_lazy_generic(
|
||||
#endif
|
||||
while (ip < ilimit) {
|
||||
size_t matchLength=0;
|
||||
size_t offset=0;
|
||||
size_t offcode=STORE_REPCODE_1;
|
||||
const BYTE* start=ip+1;
|
||||
DEBUGLOG(7, "search baseline (depth 0)");
|
||||
|
||||
/* check repCode */
|
||||
if (isDxS) {
|
||||
@@ -1615,7 +1567,7 @@ ZSTD_compressBlock_lazy_generic(
|
||||
{ size_t offsetFound = 999999999;
|
||||
size_t const ml2 = searchMax(ms, ip, iend, &offsetFound);
|
||||
if (ml2 > matchLength)
|
||||
matchLength = ml2, start = ip, offset=offsetFound;
|
||||
matchLength = ml2, start = ip, offcode=offsetFound;
|
||||
}
|
||||
|
||||
if (matchLength < 4) {
|
||||
@@ -1626,14 +1578,15 @@ ZSTD_compressBlock_lazy_generic(
|
||||
/* let's try to find a better solution */
|
||||
if (depth>=1)
|
||||
while (ip<ilimit) {
|
||||
DEBUGLOG(7, "search depth 1");
|
||||
ip ++;
|
||||
if ( (dictMode == ZSTD_noDict)
|
||||
&& (offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
|
||||
&& (offcode) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
|
||||
size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
|
||||
int const gain2 = (int)(mlRep * 3);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
|
||||
if ((mlRep >= 4) && (gain2 > gain1))
|
||||
matchLength = mlRep, offset = 0, start = ip;
|
||||
matchLength = mlRep, offcode = STORE_REPCODE_1, start = ip;
|
||||
}
|
||||
if (isDxS) {
|
||||
const U32 repIndex = (U32)(ip - base) - offset_1;
|
||||
@@ -1645,30 +1598,31 @@ ZSTD_compressBlock_lazy_generic(
|
||||
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
|
||||
size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
|
||||
int const gain2 = (int)(mlRep * 3);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
|
||||
if ((mlRep >= 4) && (gain2 > gain1))
|
||||
matchLength = mlRep, offset = 0, start = ip;
|
||||
matchLength = mlRep, offcode = STORE_REPCODE_1, start = ip;
|
||||
}
|
||||
}
|
||||
{ size_t offset2=999999999;
|
||||
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offset2))); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 4);
|
||||
if ((ml2 >= 4) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2, start = ip;
|
||||
matchLength = ml2, offcode = offset2, start = ip;
|
||||
continue; /* search a better one */
|
||||
} }
|
||||
|
||||
/* let's find an even better one */
|
||||
if ((depth==2) && (ip<ilimit)) {
|
||||
DEBUGLOG(7, "search depth 2");
|
||||
ip ++;
|
||||
if ( (dictMode == ZSTD_noDict)
|
||||
&& (offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
|
||||
&& (offcode) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
|
||||
size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
|
||||
int const gain2 = (int)(mlRep * 4);
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
|
||||
if ((mlRep >= 4) && (gain2 > gain1))
|
||||
matchLength = mlRep, offset = 0, start = ip;
|
||||
matchLength = mlRep, offcode = STORE_REPCODE_1, start = ip;
|
||||
}
|
||||
if (isDxS) {
|
||||
const U32 repIndex = (U32)(ip - base) - offset_1;
|
||||
@@ -1680,46 +1634,45 @@ ZSTD_compressBlock_lazy_generic(
|
||||
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
|
||||
size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
|
||||
int const gain2 = (int)(mlRep * 4);
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
|
||||
if ((mlRep >= 4) && (gain2 > gain1))
|
||||
matchLength = mlRep, offset = 0, start = ip;
|
||||
matchLength = mlRep, offcode = STORE_REPCODE_1, start = ip;
|
||||
}
|
||||
}
|
||||
{ size_t offset2=999999999;
|
||||
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offset2))); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 7);
|
||||
if ((ml2 >= 4) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2, start = ip;
|
||||
matchLength = ml2, offcode = offset2, start = ip;
|
||||
continue;
|
||||
} } }
|
||||
break; /* nothing found : store previous solution */
|
||||
}
|
||||
|
||||
/* NOTE:
|
||||
* start[-offset+ZSTD_REP_MOVE-1] is undefined behavior.
|
||||
* (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which
|
||||
* overflows the pointer, which is undefined behavior.
|
||||
* Pay attention that `start[-value]` can lead to strange undefined behavior
|
||||
* notably if `value` is unsigned, resulting in a large positive `-value`.
|
||||
*/
|
||||
/* catch up */
|
||||
if (offset) {
|
||||
if (STORED_IS_OFFSET(offcode)) {
|
||||
if (dictMode == ZSTD_noDict) {
|
||||
while ( ((start > anchor) & (start - (offset-ZSTD_REP_MOVE) > prefixLowest))
|
||||
&& (start[-1] == (start-(offset-ZSTD_REP_MOVE))[-1]) ) /* only search for offset within prefix */
|
||||
while ( ((start > anchor) & (start - STORED_OFFSET(offcode) > prefixLowest))
|
||||
&& (start[-1] == (start-STORED_OFFSET(offcode))[-1]) ) /* only search for offset within prefix */
|
||||
{ start--; matchLength++; }
|
||||
}
|
||||
if (isDxS) {
|
||||
U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
|
||||
U32 const matchIndex = (U32)((size_t)(start-base) - STORED_OFFSET(offcode));
|
||||
const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex;
|
||||
const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest;
|
||||
while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
|
||||
}
|
||||
offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
|
||||
offset_2 = offset_1; offset_1 = (U32)STORED_OFFSET(offcode);
|
||||
}
|
||||
/* store sequence */
|
||||
_storeSequence:
|
||||
{ size_t const litLength = start - anchor;
|
||||
ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offset, matchLength-MINMATCH);
|
||||
{ size_t const litLength = (size_t)(start - anchor);
|
||||
ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offcode, matchLength);
|
||||
anchor = ip = start + matchLength;
|
||||
}
|
||||
|
||||
@@ -1735,8 +1688,8 @@ _storeSequence:
|
||||
&& (MEM_read32(repMatch) == MEM_read32(ip)) ) {
|
||||
const BYTE* const repEnd2 = repIndex < prefixLowestIndex ? dictEnd : iend;
|
||||
matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd2, prefixLowest) + 4;
|
||||
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset_2 <=> offset_1 */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, matchLength-MINMATCH);
|
||||
offcode = offset_2; offset_2 = offset_1; offset_1 = (U32)offcode; /* swap offset_2 <=> offset_1 */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, matchLength);
|
||||
ip += matchLength;
|
||||
anchor = ip;
|
||||
continue;
|
||||
@@ -1750,8 +1703,8 @@ _storeSequence:
|
||||
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
|
||||
/* store sequence */
|
||||
matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
||||
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, matchLength-MINMATCH);
|
||||
offcode = offset_2; offset_2 = offset_1; offset_1 = (U32)offcode; /* swap repcodes */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, matchLength);
|
||||
ip += matchLength;
|
||||
anchor = ip;
|
||||
continue; /* faster when present ... (?) */
|
||||
@@ -1930,15 +1883,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
|
||||
const U32 windowLog = ms->cParams.windowLog;
|
||||
const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5;
|
||||
|
||||
typedef size_t (*searchMax_f)(
|
||||
ZSTD_matchState_t* ms,
|
||||
const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
|
||||
const searchMax_f searchFuncs[3] = {
|
||||
ZSTD_HcFindBestMatch_extDict_selectMLS,
|
||||
ZSTD_BtFindBestMatch_extDict_selectMLS,
|
||||
ZSTD_RowFindBestMatch_extDict_selectRowLog
|
||||
};
|
||||
searchMax_f searchMax = searchFuncs[(int)searchMethod];
|
||||
searchMax_f const searchMax = ZSTD_selectLazyVTable(ms, searchMethod, ZSTD_extDict)->searchMax;
|
||||
U32 offset_1 = rep[0], offset_2 = rep[1];
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_lazy_extDict_generic (searchFunc=%u)", (U32)searchMethod);
|
||||
@@ -1960,7 +1905,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
|
||||
#endif
|
||||
while (ip < ilimit) {
|
||||
size_t matchLength=0;
|
||||
size_t offset=0;
|
||||
size_t offcode=STORE_REPCODE_1;
|
||||
const BYTE* start=ip+1;
|
||||
U32 curr = (U32)(ip-base);
|
||||
|
||||
@@ -1982,10 +1927,10 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
|
||||
{ size_t offsetFound = 999999999;
|
||||
size_t const ml2 = searchMax(ms, ip, iend, &offsetFound);
|
||||
if (ml2 > matchLength)
|
||||
matchLength = ml2, start = ip, offset=offsetFound;
|
||||
matchLength = ml2, start = ip, offcode=offsetFound;
|
||||
}
|
||||
|
||||
if (matchLength < 4) {
|
||||
if (matchLength < 4) {
|
||||
ip += ((ip-anchor) >> kSearchStrength) + 1; /* jump faster over incompressible sections */
|
||||
continue;
|
||||
}
|
||||
@@ -1996,7 +1941,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
|
||||
ip ++;
|
||||
curr++;
|
||||
/* check repCode */
|
||||
if (offset) {
|
||||
if (offcode) {
|
||||
const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);
|
||||
const U32 repIndex = (U32)(curr - offset_1);
|
||||
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
|
||||
@@ -2008,18 +1953,18 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
|
||||
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
||||
size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
||||
int const gain2 = (int)(repLength * 3);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
|
||||
if ((repLength >= 4) && (gain2 > gain1))
|
||||
matchLength = repLength, offset = 0, start = ip;
|
||||
matchLength = repLength, offcode = STORE_REPCODE_1, start = ip;
|
||||
} }
|
||||
|
||||
/* search match, depth 1 */
|
||||
{ size_t offset2=999999999;
|
||||
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offset2))); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 4);
|
||||
if ((ml2 >= 4) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2, start = ip;
|
||||
matchLength = ml2, offcode = offset2, start = ip;
|
||||
continue; /* search a better one */
|
||||
} }
|
||||
|
||||
@@ -2028,7 +1973,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
|
||||
ip ++;
|
||||
curr++;
|
||||
/* check repCode */
|
||||
if (offset) {
|
||||
if (offcode) {
|
||||
const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);
|
||||
const U32 repIndex = (U32)(curr - offset_1);
|
||||
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
|
||||
@@ -2040,36 +1985,36 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
|
||||
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
||||
size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
||||
int const gain2 = (int)(repLength * 4);
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
|
||||
if ((repLength >= 4) && (gain2 > gain1))
|
||||
matchLength = repLength, offset = 0, start = ip;
|
||||
matchLength = repLength, offcode = STORE_REPCODE_1, start = ip;
|
||||
} }
|
||||
|
||||
/* search match, depth 2 */
|
||||
{ size_t offset2=999999999;
|
||||
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offset2))); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 7);
|
||||
if ((ml2 >= 4) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2, start = ip;
|
||||
matchLength = ml2, offcode = offset2, start = ip;
|
||||
continue;
|
||||
} } }
|
||||
break; /* nothing found : store previous solution */
|
||||
}
|
||||
|
||||
/* catch up */
|
||||
if (offset) {
|
||||
U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
|
||||
if (STORED_IS_OFFSET(offcode)) {
|
||||
U32 const matchIndex = (U32)((size_t)(start-base) - STORED_OFFSET(offcode));
|
||||
const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
|
||||
const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
|
||||
while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
|
||||
offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
|
||||
offset_2 = offset_1; offset_1 = (U32)STORED_OFFSET(offcode);
|
||||
}
|
||||
|
||||
/* store sequence */
|
||||
_storeSequence:
|
||||
{ size_t const litLength = start - anchor;
|
||||
ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offset, matchLength-MINMATCH);
|
||||
{ size_t const litLength = (size_t)(start - anchor);
|
||||
ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offcode, matchLength);
|
||||
anchor = ip = start + matchLength;
|
||||
}
|
||||
|
||||
@@ -2086,8 +2031,8 @@ _storeSequence:
|
||||
/* repcode detected we should take it */
|
||||
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
||||
matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
||||
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, matchLength-MINMATCH);
|
||||
offcode = offset_2; offset_2 = offset_1; offset_1 = (U32)offcode; /* swap offset history */
|
||||
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, matchLength);
|
||||
ip += matchLength;
|
||||
anchor = ip;
|
||||
continue; /* faster when present ... (?) */
|
||||
|
||||
@@ -478,7 +478,7 @@ static size_t ZSTD_ldm_generateSequences_internal(
|
||||
*/
|
||||
if (anchor > ip + hashed) {
|
||||
ZSTD_ldm_gear_reset(&hashState, anchor - minMatchLength, minMatchLength);
|
||||
/* Continue the outter loop at anchor (ip + hashed == anchor). */
|
||||
/* Continue the outer loop at anchor (ip + hashed == anchor). */
|
||||
ip = anchor - hashed;
|
||||
break;
|
||||
}
|
||||
@@ -579,7 +579,9 @@ size_t ZSTD_ldm_generateSequences(
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
|
||||
void
|
||||
ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch)
|
||||
{
|
||||
while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
|
||||
rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;
|
||||
if (srcSize <= seq->litLength) {
|
||||
@@ -709,8 +711,8 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
|
||||
rep[0] = sequence.offset;
|
||||
/* Store the sequence */
|
||||
ZSTD_storeSeq(seqStore, newLitLength, ip - newLitLength, iend,
|
||||
sequence.offset + ZSTD_REP_MOVE,
|
||||
sequence.matchLength - MINMATCH);
|
||||
STORE_OFFSET(sequence.offset),
|
||||
sequence.matchLength);
|
||||
ip += sequence.matchLength;
|
||||
}
|
||||
}
|
||||
|
||||
+229
-253
@@ -113,21 +113,6 @@ static U32 ZSTD_scaleStats(unsigned* table, U32 lastEltIndex, U32 logTarget)
|
||||
return ZSTD_downscaleStats(table, lastEltIndex, ZSTD_highbit32(factor));
|
||||
}
|
||||
|
||||
static unsigned const k_baseLLfreqs[MaxLL+1] = {
|
||||
4, 2, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1
|
||||
};
|
||||
|
||||
static unsigned const k_baseOFCfreqs[MaxOff+1] = {
|
||||
6, 2, 1, 1, 2, 3, 4, 4,
|
||||
4, 3, 2, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1
|
||||
};
|
||||
|
||||
/* ZSTD_rescaleFreqs() :
|
||||
* if first block (detected by optPtr->litLengthSum == 0) : init statistics
|
||||
* take hints from dictionary if there is one
|
||||
@@ -207,13 +192,21 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
||||
|
||||
assert(optPtr->litFreq != NULL);
|
||||
if (compressedLiterals) {
|
||||
unsigned maxlit = MaxLit;
|
||||
HIST_count_simple(optPtr->litFreq, &maxlit, src, srcSize); /* use raw first block to init statistics */
|
||||
unsigned lit = MaxLit;
|
||||
HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
|
||||
optPtr->litSum = ZSTD_downscaleStats(optPtr->litFreq, MaxLit, 8);
|
||||
}
|
||||
|
||||
ZSTD_memcpy(optPtr->litLengthFreq, k_baseLLfreqs, sizeof(k_baseLLfreqs));
|
||||
optPtr->litLengthSum = sum_u32(k_baseLLfreqs, MaxLL+1);
|
||||
{ unsigned const baseLLfreqs[MaxLL+1] = {
|
||||
4, 2, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1
|
||||
};
|
||||
ZSTD_memcpy(optPtr->litLengthFreq, baseLLfreqs, sizeof(baseLLfreqs));
|
||||
optPtr->litLengthSum = sum_u32(baseLLfreqs, MaxLL+1);
|
||||
}
|
||||
|
||||
{ unsigned ml;
|
||||
for (ml=0; ml<=MaxML; ml++)
|
||||
@@ -221,8 +214,16 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
||||
}
|
||||
optPtr->matchLengthSum = MaxML+1;
|
||||
|
||||
ZSTD_memcpy(optPtr->offCodeFreq, k_baseOFCfreqs, sizeof(k_baseOFCfreqs));
|
||||
optPtr->offCodeSum = sum_u32(k_baseOFCfreqs, MaxOff+1);
|
||||
{ unsigned const baseOFCfreqs[MaxOff+1] = {
|
||||
6, 2, 1, 1, 2, 3, 4, 4,
|
||||
4, 3, 2, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1
|
||||
};
|
||||
ZSTD_memcpy(optPtr->offCodeFreq, baseOFCfreqs, sizeof(baseOFCfreqs));
|
||||
optPtr->offCodeSum = sum_u32(baseOFCfreqs, MaxOff+1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -268,7 +269,16 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
|
||||
* cost of literalLength symbol */
|
||||
static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optPtr, int optLevel)
|
||||
{
|
||||
if (optPtr->priceType == zop_predef) return WEIGHT(litLength, optLevel);
|
||||
assert(litLength <= ZSTD_BLOCKSIZE_MAX);
|
||||
if (optPtr->priceType == zop_predef)
|
||||
return WEIGHT(litLength, optLevel);
|
||||
/* We can't compute the litLength price for sizes >= ZSTD_BLOCKSIZE_MAX
|
||||
* because it isn't representable in the zstd format. So instead just
|
||||
* call it 1 bit more than ZSTD_BLOCKSIZE_MAX - 1. In this case the block
|
||||
* would be all literals.
|
||||
*/
|
||||
if (litLength == ZSTD_BLOCKSIZE_MAX)
|
||||
return BITCOST_MULTIPLIER + ZSTD_litLengthPrice(ZSTD_BLOCKSIZE_MAX - 1, optPtr, optLevel);
|
||||
|
||||
/* dynamic statistics */
|
||||
{ U32 const llCode = ZSTD_LLcode(litLength);
|
||||
@@ -281,15 +291,17 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
|
||||
/* ZSTD_getMatchPrice() :
|
||||
* Provides the cost of the match part (offset + matchLength) of a sequence
|
||||
* Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
|
||||
* optLevel: when <2, favors small offset for decompression speed (improved cache efficiency) */
|
||||
* @offcode : expects a scale where 0,1,2 are repcodes 1-3, and 3+ are real_offsets+2
|
||||
* @optLevel: when <2, favors small offset for decompression speed (improved cache efficiency)
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE U32
|
||||
ZSTD_getMatchPrice(U32 const offset,
|
||||
ZSTD_getMatchPrice(U32 const offcode,
|
||||
U32 const matchLength,
|
||||
const optState_t* const optPtr,
|
||||
int const optLevel)
|
||||
{
|
||||
U32 price;
|
||||
U32 const offCode = ZSTD_highbit32(offset+1);
|
||||
U32 const offCode = ZSTD_highbit32(STORED_TO_OFFBASE(offcode));
|
||||
U32 const mlBase = matchLength - MINMATCH;
|
||||
assert(matchLength >= MINMATCH);
|
||||
|
||||
@@ -312,19 +324,28 @@ ZSTD_getMatchPrice(U32 const offset,
|
||||
return price;
|
||||
}
|
||||
|
||||
/* ZSTD_updateStats() :
|
||||
* assumption : literals + litLengtn <= iend */
|
||||
static void ZSTD_updateStats(optState_t* const optPtr,
|
||||
U32 litLength, const BYTE* literals,
|
||||
U32 offsetCode, U32 matchLength)
|
||||
|
||||
static void
|
||||
ZSTD_updateLiterals(optState_t* const optPtr, const BYTE* literals, U32 litLength)
|
||||
{
|
||||
/* literals */
|
||||
if (ZSTD_compressedLiterals(optPtr)) {
|
||||
U32 u;
|
||||
for (u=0; u < litLength; u++)
|
||||
optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
|
||||
optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
/* ZSTD_updateStats() :
|
||||
* assumption : literals + litLengtn <= iend */
|
||||
static void ZSTD_updateStats(optState_t* const optPtr,
|
||||
U32 litLength, const BYTE* literals,
|
||||
U32 offsetCode, U32 matchLength)
|
||||
{
|
||||
DEBUGLOG(6, "ZSTD_updateStats (ll=%u, ml=%u)", litLength, matchLength);
|
||||
|
||||
/* literals */
|
||||
ZSTD_updateLiterals(optPtr, literals, litLength);
|
||||
|
||||
/* literal Length */
|
||||
{ U32 const llCode = ZSTD_LLcode(litLength);
|
||||
@@ -332,8 +353,8 @@ static void ZSTD_updateStats(optState_t* const optPtr,
|
||||
optPtr->litLengthSum++;
|
||||
}
|
||||
|
||||
/* match offset code (0-2=>repCode; 3+=>offset+2) */
|
||||
{ U32 const offCode = ZSTD_highbit32(offsetCode+1);
|
||||
/* offset code : expected to follow storeSeq() numeric representation */
|
||||
{ U32 const offCode = ZSTD_highbit32(STORED_TO_OFFBASE(offsetCode));
|
||||
assert(offCode <= MaxOff);
|
||||
optPtr->offCodeFreq[offCode]++;
|
||||
optPtr->offCodeSum++;
|
||||
@@ -443,7 +464,7 @@ static U32 ZSTD_insertBt1(
|
||||
hashTable[h] = curr; /* Update Hash Table */
|
||||
|
||||
assert(windowLow > 0);
|
||||
while (nbCompares-- && (matchIndex >= windowLow)) {
|
||||
for (; nbCompares && (matchIndex >= windowLow); --nbCompares) {
|
||||
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
||||
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
||||
assert(matchIndex < curr);
|
||||
@@ -632,7 +653,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
DEBUGLOG(8, "found repCode %u (ll0:%u, offset:%u) of length %u",
|
||||
repCode, ll0, repOffset, repLen);
|
||||
bestLength = repLen;
|
||||
matches[mnum].off = repCode - ll0;
|
||||
matches[mnum].off = STORE_REPCODE(repCode - ll0 + 1); /* expect value between 1 and 3 */
|
||||
matches[mnum].len = (U32)repLen;
|
||||
mnum++;
|
||||
if ( (repLen > sufficient_len)
|
||||
@@ -661,7 +682,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
bestLength = mlen;
|
||||
assert(curr > matchIndex3);
|
||||
assert(mnum==0); /* no prior solution */
|
||||
matches[0].off = (curr - matchIndex3) + ZSTD_REP_MOVE;
|
||||
matches[0].off = STORE_OFFSET(curr - matchIndex3);
|
||||
matches[0].len = (U32)mlen;
|
||||
mnum = 1;
|
||||
if ( (mlen > sufficient_len) |
|
||||
@@ -674,7 +695,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
|
||||
hashTable[h] = curr; /* Update Hash Table */
|
||||
|
||||
while (nbCompares-- && (matchIndex >= matchLow)) {
|
||||
for (; nbCompares && (matchIndex >= matchLow); --nbCompares) {
|
||||
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
||||
const BYTE* match;
|
||||
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
||||
@@ -695,12 +716,12 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
|
||||
if (matchLength > bestLength) {
|
||||
DEBUGLOG(8, "found match of length %u at distance %u (offCode=%u)",
|
||||
(U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
|
||||
(U32)matchLength, curr - matchIndex, STORE_OFFSET(curr - matchIndex));
|
||||
assert(matchEndIdx > matchIndex);
|
||||
if (matchLength > matchEndIdx - matchIndex)
|
||||
matchEndIdx = matchIndex + (U32)matchLength;
|
||||
bestLength = matchLength;
|
||||
matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
|
||||
matches[mnum].off = STORE_OFFSET(curr - matchIndex);
|
||||
matches[mnum].len = (U32)matchLength;
|
||||
mnum++;
|
||||
if ( (matchLength > ZSTD_OPT_NUM)
|
||||
@@ -726,12 +747,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
|
||||
*smallerPtr = *largerPtr = 0;
|
||||
|
||||
assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */
|
||||
if (dictMode == ZSTD_dictMatchState && nbCompares) {
|
||||
size_t const dmsH = ZSTD_hashPtr(ip, dmsHashLog, mls);
|
||||
U32 dictMatchIndex = dms->hashTable[dmsH];
|
||||
const U32* const dmsBt = dms->chainTable;
|
||||
commonLengthSmaller = commonLengthLarger = 0;
|
||||
while (nbCompares-- && (dictMatchIndex > dmsLowLimit)) {
|
||||
for (; nbCompares && (dictMatchIndex > dmsLowLimit); --nbCompares) {
|
||||
const U32* const nextPtr = dmsBt + 2*(dictMatchIndex & dmsBtMask);
|
||||
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
||||
const BYTE* match = dmsBase + dictMatchIndex;
|
||||
@@ -742,11 +764,11 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
if (matchLength > bestLength) {
|
||||
matchIndex = dictMatchIndex + dmsIndexDelta;
|
||||
DEBUGLOG(8, "found dms match of length %u at distance %u (offCode=%u)",
|
||||
(U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
|
||||
(U32)matchLength, curr - matchIndex, STORE_OFFSET(curr - matchIndex));
|
||||
if (matchLength > matchEndIdx - matchIndex)
|
||||
matchEndIdx = matchIndex + (U32)matchLength;
|
||||
bestLength = matchLength;
|
||||
matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
|
||||
matches[mnum].off = STORE_OFFSET(curr - matchIndex);
|
||||
matches[mnum].len = (U32)matchLength;
|
||||
mnum++;
|
||||
if ( (matchLength > ZSTD_OPT_NUM)
|
||||
@@ -769,30 +791,84 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
||||
return mnum;
|
||||
}
|
||||
|
||||
typedef U32 (*ZSTD_getAllMatchesFn)(
|
||||
ZSTD_match_t*,
|
||||
ZSTD_matchState_t*,
|
||||
U32*,
|
||||
const BYTE*,
|
||||
const BYTE*,
|
||||
const U32 rep[ZSTD_REP_NUM],
|
||||
U32 const ll0,
|
||||
U32 const lengthToBeat);
|
||||
|
||||
FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
||||
ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
|
||||
ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
|
||||
const U32 rep[ZSTD_REP_NUM],
|
||||
U32 const ll0,
|
||||
U32 const lengthToBeat)
|
||||
FORCE_INLINE_TEMPLATE U32 ZSTD_btGetAllMatches_internal(
|
||||
ZSTD_match_t* matches,
|
||||
ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iHighLimit,
|
||||
const U32 rep[ZSTD_REP_NUM],
|
||||
U32 const ll0,
|
||||
U32 const lengthToBeat,
|
||||
const ZSTD_dictMode_e dictMode,
|
||||
const U32 mls)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32 const matchLengthSearch = cParams->minMatch;
|
||||
DEBUGLOG(8, "ZSTD_BtGetAllMatches");
|
||||
if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
|
||||
ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
|
||||
switch(matchLengthSearch)
|
||||
{
|
||||
case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3);
|
||||
default :
|
||||
case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4);
|
||||
case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6);
|
||||
assert(BOUNDED(3, ms->cParams.minMatch, 6) == mls);
|
||||
DEBUGLOG(8, "ZSTD_BtGetAllMatches(dictMode=%d, mls=%u)", (int)dictMode, mls);
|
||||
if (ip < ms->window.base + ms->nextToUpdate)
|
||||
return 0; /* skipped area */
|
||||
ZSTD_updateTree_internal(ms, ip, iHighLimit, mls, dictMode);
|
||||
return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, mls);
|
||||
}
|
||||
|
||||
#define ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls) ZSTD_btGetAllMatches_##dictMode##_##mls
|
||||
|
||||
#define GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, mls) \
|
||||
static U32 ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls)( \
|
||||
ZSTD_match_t* matches, \
|
||||
ZSTD_matchState_t* ms, \
|
||||
U32* nextToUpdate3, \
|
||||
const BYTE* ip, \
|
||||
const BYTE* const iHighLimit, \
|
||||
const U32 rep[ZSTD_REP_NUM], \
|
||||
U32 const ll0, \
|
||||
U32 const lengthToBeat) \
|
||||
{ \
|
||||
return ZSTD_btGetAllMatches_internal( \
|
||||
matches, ms, nextToUpdate3, ip, iHighLimit, \
|
||||
rep, ll0, lengthToBeat, ZSTD_##dictMode, mls); \
|
||||
}
|
||||
|
||||
#define GEN_ZSTD_BT_GET_ALL_MATCHES(dictMode) \
|
||||
GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 3) \
|
||||
GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 4) \
|
||||
GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 5) \
|
||||
GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 6)
|
||||
|
||||
GEN_ZSTD_BT_GET_ALL_MATCHES(noDict)
|
||||
GEN_ZSTD_BT_GET_ALL_MATCHES(extDict)
|
||||
GEN_ZSTD_BT_GET_ALL_MATCHES(dictMatchState)
|
||||
|
||||
#define ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMode) \
|
||||
{ \
|
||||
ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 3), \
|
||||
ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 4), \
|
||||
ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 5), \
|
||||
ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 6) \
|
||||
}
|
||||
|
||||
static ZSTD_getAllMatchesFn
|
||||
ZSTD_selectBtGetAllMatches(ZSTD_matchState_t const* ms, ZSTD_dictMode_e const dictMode)
|
||||
{
|
||||
ZSTD_getAllMatchesFn const getAllMatchesFns[3][4] = {
|
||||
ZSTD_BT_GET_ALL_MATCHES_ARRAY(noDict),
|
||||
ZSTD_BT_GET_ALL_MATCHES_ARRAY(extDict),
|
||||
ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMatchState)
|
||||
};
|
||||
U32 const mls = BOUNDED(3, ms->cParams.minMatch, 6);
|
||||
assert((U32)dictMode < 3);
|
||||
assert(mls - 3 < 4);
|
||||
return getAllMatchesFns[(int)dictMode][mls - 3];
|
||||
}
|
||||
|
||||
/*************************
|
||||
@@ -801,16 +877,18 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
||||
|
||||
/* Struct containing info needed to make decision about ldm inclusion */
|
||||
typedef struct {
|
||||
rawSeqStore_t seqStore; /* External match candidates store for this block */
|
||||
U32 startPosInBlock; /* Start position of the current match candidate */
|
||||
U32 endPosInBlock; /* End position of the current match candidate */
|
||||
U32 offset; /* Offset of the match candidate */
|
||||
rawSeqStore_t seqStore; /* External match candidates store for this block */
|
||||
U32 startPosInBlock; /* Start position of the current match candidate */
|
||||
U32 endPosInBlock; /* End position of the current match candidate */
|
||||
U32 offset; /* Offset of the match candidate */
|
||||
} ZSTD_optLdm_t;
|
||||
|
||||
/* ZSTD_optLdm_skipRawSeqStoreBytes():
|
||||
* Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
|
||||
* Moves forward in @rawSeqStore by @nbBytes,
|
||||
* which will update the fields 'pos' and 'posInSequence'.
|
||||
*/
|
||||
static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
|
||||
static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes)
|
||||
{
|
||||
U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);
|
||||
while (currPos && rawSeqStore->pos < rawSeqStore->size) {
|
||||
rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
|
||||
@@ -831,8 +909,10 @@ static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t
|
||||
* Calculates the beginning and end of the next match in the current block.
|
||||
* Updates 'pos' and 'posInSequence' of the ldmSeqStore.
|
||||
*/
|
||||
static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,
|
||||
U32 blockBytesRemaining) {
|
||||
static void
|
||||
ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,
|
||||
U32 blockBytesRemaining)
|
||||
{
|
||||
rawSeq currSeq;
|
||||
U32 currBlockEndPos;
|
||||
U32 literalsBytesRemaining;
|
||||
@@ -844,8 +924,8 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
|
||||
optLdm->endPosInBlock = UINT_MAX;
|
||||
return;
|
||||
}
|
||||
/* Calculate appropriate bytes left in matchLength and litLength after adjusting
|
||||
based on ldmSeqStore->posInSequence */
|
||||
/* Calculate appropriate bytes left in matchLength and litLength
|
||||
* after adjusting based on ldmSeqStore->posInSequence */
|
||||
currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos];
|
||||
assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength);
|
||||
currBlockEndPos = currPosInBlock + blockBytesRemaining;
|
||||
@@ -881,15 +961,16 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
|
||||
}
|
||||
|
||||
/* ZSTD_optLdm_maybeAddMatch():
|
||||
* Adds a match if it's long enough, based on it's 'matchStartPosInBlock'
|
||||
* and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
|
||||
* Adds a match if it's long enough,
|
||||
* based on it's 'matchStartPosInBlock' and 'matchEndPosInBlock',
|
||||
* into 'matches'. Maintains the correct ordering of 'matches'.
|
||||
*/
|
||||
static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
|
||||
ZSTD_optLdm_t* optLdm, U32 currPosInBlock) {
|
||||
U32 posDiff = currPosInBlock - optLdm->startPosInBlock;
|
||||
const ZSTD_optLdm_t* optLdm, U32 currPosInBlock)
|
||||
{
|
||||
U32 const posDiff = currPosInBlock - optLdm->startPosInBlock;
|
||||
/* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
|
||||
U32 candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
|
||||
U32 candidateOffCode = optLdm->offset + ZSTD_REP_MOVE;
|
||||
U32 const candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
|
||||
|
||||
/* Ensure that current block position is not outside of the match */
|
||||
if (currPosInBlock < optLdm->startPosInBlock
|
||||
@@ -899,6 +980,7 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
|
||||
}
|
||||
|
||||
if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) {
|
||||
U32 const candidateOffCode = STORE_OFFSET(optLdm->offset);
|
||||
DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
|
||||
candidateOffCode, candidateMatchLength, currPosInBlock);
|
||||
matches[*nbMatches].len = candidateMatchLength;
|
||||
@@ -910,8 +992,11 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
|
||||
/* ZSTD_optLdm_processMatchCandidate():
|
||||
* Wrapper function to update ldm seq store and call ldm functions as necessary.
|
||||
*/
|
||||
static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
|
||||
U32 currPosInBlock, U32 remainingBytes) {
|
||||
static void
|
||||
ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm,
|
||||
ZSTD_match_t* matches, U32* nbMatches,
|
||||
U32 currPosInBlock, U32 remainingBytes)
|
||||
{
|
||||
if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {
|
||||
return;
|
||||
}
|
||||
@@ -922,7 +1007,7 @@ static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_
|
||||
* at the end of a match from the ldm seq store, and will often be some bytes
|
||||
* over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots"
|
||||
*/
|
||||
U32 posOvershoot = currPosInBlock - optLdm->endPosInBlock;
|
||||
U32 const posOvershoot = currPosInBlock - optLdm->endPosInBlock;
|
||||
ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot);
|
||||
}
|
||||
ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes);
|
||||
@@ -975,6 +1060,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
const BYTE* const prefixStart = base + ms->window.dictLimit;
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
|
||||
ZSTD_getAllMatchesFn getAllMatches = ZSTD_selectBtGetAllMatches(ms, dictMode);
|
||||
|
||||
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
|
||||
U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
|
||||
U32 nextToUpdate3 = ms->nextToUpdate;
|
||||
@@ -983,6 +1070,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
ZSTD_match_t* const matches = optStatePtr->matchTable;
|
||||
ZSTD_optimal_t lastSequence;
|
||||
ZSTD_optLdm_t optLdm;
|
||||
size_t literalsAlreadyCounted = 0;
|
||||
|
||||
optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore;
|
||||
optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0;
|
||||
@@ -1002,11 +1090,19 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
/* find first match */
|
||||
{ U32 const litlen = (U32)(ip - anchor);
|
||||
U32 const ll0 = !litlen;
|
||||
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
|
||||
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; }
|
||||
|
||||
if (ip-anchor > 0) {
|
||||
/* if (literalsAlreadyCounted > 0) : avoid double counting */
|
||||
size_t const newlits = (size_t)(ip-anchor) - literalsAlreadyCounted;
|
||||
assert(literalsAlreadyCounted <= (size_t)(ip-anchor));
|
||||
ZSTD_updateLiterals(optStatePtr, anchor + literalsAlreadyCounted, newlits);
|
||||
literalsAlreadyCounted += newlits;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
@@ -1020,14 +1116,14 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
|
||||
/* large match -> immediate encoding */
|
||||
{ U32 const maxML = matches[nbMatches-1].len;
|
||||
U32 const maxOffset = matches[nbMatches-1].off;
|
||||
U32 const maxOffcode = matches[nbMatches-1].off;
|
||||
DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
|
||||
nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
|
||||
nbMatches, maxML, maxOffcode, (U32)(ip-prefixStart));
|
||||
|
||||
if (maxML > sufficient_len) {
|
||||
lastSequence.litlen = litlen;
|
||||
lastSequence.mlen = maxML;
|
||||
lastSequence.off = maxOffset;
|
||||
lastSequence.off = maxOffcode;
|
||||
DEBUGLOG(6, "large match (%u>%u), immediate encoding",
|
||||
maxML, sufficient_len);
|
||||
cur = 0;
|
||||
@@ -1044,20 +1140,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
opt[pos].price = ZSTD_MAX_PRICE; /* mlen, litlen and price will be fixed during forward scanning */
|
||||
}
|
||||
for (matchNb = 0; matchNb < nbMatches; matchNb++) {
|
||||
U32 const offset = matches[matchNb].off;
|
||||
U32 const offcode = matches[matchNb].off;
|
||||
U32 const end = matches[matchNb].len;
|
||||
for ( ; pos <= end ; pos++ ) {
|
||||
U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
|
||||
U32 const matchPrice = ZSTD_getMatchPrice(offcode, pos, optStatePtr, optLevel);
|
||||
U32 const sequencePrice = literalsPrice + matchPrice;
|
||||
DEBUGLOG(7, "rPos:%u => set initial price : %.2f",
|
||||
pos, ZSTD_fCost(sequencePrice));
|
||||
opt[pos].mlen = pos;
|
||||
opt[pos].off = offset;
|
||||
opt[pos].off = offcode;
|
||||
opt[pos].litlen = litlen;
|
||||
opt[pos].price = (int)sequencePrice;
|
||||
} }
|
||||
last_pos = pos-1;
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
/* check further positions */
|
||||
for (cur = 1; cur <= last_pos; cur++) {
|
||||
@@ -1084,7 +1181,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
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]);
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
@@ -1095,7 +1193,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
assert(cur >= opt[cur].mlen);
|
||||
if (opt[cur].mlen != 0) {
|
||||
U32 const prev = cur - opt[cur].mlen;
|
||||
repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
|
||||
repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
|
||||
ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
|
||||
} else {
|
||||
ZSTD_memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
|
||||
@@ -1117,7 +1215,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
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 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
|
||||
U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, inr, iend, opt[cur].rep, ll0, minMatch);
|
||||
U32 matchNb;
|
||||
|
||||
ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
|
||||
@@ -1185,7 +1283,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
||||
* update them while traversing the sequences.
|
||||
*/
|
||||
if (lastSequence.mlen != 0) {
|
||||
repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
|
||||
repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
|
||||
ZSTD_memcpy(rep, &reps, sizeof(reps));
|
||||
} else {
|
||||
ZSTD_memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
|
||||
@@ -1221,15 +1319,17 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
||||
DEBUGLOG(6, "considering seq starting at %zi, llen=%u, mlen=%u",
|
||||
anchor - istart, (unsigned)llen, (unsigned)mlen);
|
||||
|
||||
if (mlen==0) { /* only literals => must be last "sequence", actually starting a new stream of sequences */
|
||||
if (mlen==0) { /* only literals */
|
||||
assert(storePos == storeEnd); /* must be last sequence */
|
||||
ip = anchor + llen; /* last "sequence" is a bunch of literals => don't progress anchor */
|
||||
continue; /* will finish */
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(anchor + llen <= iend);
|
||||
ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
|
||||
ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
|
||||
assert(llen >= literalsAlreadyCounted);
|
||||
ZSTD_updateStats(optStatePtr, llen - literalsAlreadyCounted, anchor + literalsAlreadyCounted, offCode, mlen);
|
||||
literalsAlreadyCounted = 0;
|
||||
ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen);
|
||||
anchor += advance;
|
||||
ip = anchor;
|
||||
} }
|
||||
@@ -1237,151 +1337,36 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
||||
}
|
||||
} /* while (ip < ilimit) */
|
||||
|
||||
/* update literals statistics, for next block */
|
||||
assert((size_t)(iend - anchor) >= literalsAlreadyCounted);
|
||||
ZSTD_updateLiterals(optStatePtr, anchor + literalsAlreadyCounted, (size_t)(iend - anchor) - literalsAlreadyCounted);
|
||||
/* Return the last literals size */
|
||||
return (size_t)(iend - anchor);
|
||||
}
|
||||
|
||||
static size_t ZSTD_compressBlock_opt0(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode)
|
||||
{
|
||||
return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /* optLevel */, dictMode);
|
||||
}
|
||||
|
||||
static size_t ZSTD_compressBlock_opt2(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode)
|
||||
{
|
||||
return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /* optLevel */, dictMode);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock_btopt(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_btopt");
|
||||
return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_noDict);
|
||||
return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_noDict);
|
||||
}
|
||||
|
||||
|
||||
#include "zstd_compress_literals.h" /* COMPRESS_LITERALS_SIZE_MIN */
|
||||
|
||||
static void transfer_literalStats(optState_t* opt, const seqStore_t* seqStore)
|
||||
{
|
||||
size_t const nbLiterals = (size_t)(seqStore->lit - seqStore->litStart);
|
||||
assert(seqStore->lit >= seqStore->litStart);
|
||||
|
||||
if (nbLiterals < COMPRESS_LITERALS_SIZE_MIN) {
|
||||
/* literals won't be compressed, so give them an all-flat cost */
|
||||
/* note : it would be better if it was also possible to extend this category
|
||||
* to non-compressible literals, even when they are more numerous than threshold.
|
||||
* However, this requires additional cpu and memory workspace */
|
||||
unsigned u;
|
||||
for (u=0; u<=MaxLit; u++) opt->litFreq[u]=2;
|
||||
} else {
|
||||
unsigned maxlit = MaxLit;
|
||||
HIST_count_simple(opt->litFreq, &maxlit, seqStore->litStart, nbLiterals);
|
||||
}
|
||||
opt->litSum = ZSTD_downscaleStats(opt->litFreq, MaxLit, 0); /* flatten stats, by providing at least 1 to every symbol */
|
||||
}
|
||||
|
||||
|
||||
typedef enum { fix_greedy_bias, from_btultra } biasfix_e;
|
||||
|
||||
static void transfer_seqStats(optState_t* opt, const seqStore_t* seqStore, biasfix_e biasfix)
|
||||
{
|
||||
U32 const nbSeq = (U32)(seqStore->sequences - seqStore->sequencesStart);
|
||||
assert(seqStore->sequences >= seqStore->sequencesStart);
|
||||
ZSTD_seqToCodes(seqStore);
|
||||
|
||||
{ const BYTE* codePtr = seqStore->ofCode;
|
||||
U32 u;
|
||||
memset(opt->offCodeFreq, 0, sizeof(U32) * (MaxOff+1));
|
||||
ZSTD_STATIC_ASSERT(MaxOff >= 17);
|
||||
for (u=0; u<17; u++) opt->offCodeFreq[u]=1; /* flatten stats; some offcode may not be produced by greedy but still be present */
|
||||
for (u=0; u<nbSeq; u++) opt->offCodeFreq[codePtr[u]]++;
|
||||
if (biasfix == fix_greedy_bias) {
|
||||
assert(opt->offCodeFreq[1] == 1); /* greedy can't find rep1/rep2 */
|
||||
opt->offCodeFreq[1] = (opt->offCodeFreq[0] / 3) + 1; /* bias correction */
|
||||
}
|
||||
opt->offCodeSum = sum_u32(opt->offCodeFreq, 18);
|
||||
}
|
||||
|
||||
{ const BYTE* codePtr = seqStore->mlCode;
|
||||
U32 u;
|
||||
for (u=0; u<MaxML+1; u++) opt->matchLengthFreq[u]=1; /* flatten stats; some match length not produced by greedy might end up present */
|
||||
for (u=0; u<nbSeq; u++) opt->matchLengthFreq[codePtr[u]]++;
|
||||
if (biasfix == fix_greedy_bias) {
|
||||
assert(opt->matchLengthFreq[0] == 1); /* greedy can't find mml=3 */
|
||||
opt->matchLengthFreq[0] = opt->matchLengthFreq[1] + 1; /* bias correction */
|
||||
}
|
||||
opt->matchLengthSum = sum_u32(opt->matchLengthFreq, MaxML+1);
|
||||
}
|
||||
|
||||
{ const BYTE* codePtr = seqStore->llCode;
|
||||
U32 u;
|
||||
ZSTD_memcpy(opt->litLengthFreq, k_baseLLfreqs, sizeof(k_baseLLfreqs));
|
||||
for (u=0; u<nbSeq; u++) opt->litLengthFreq[codePtr[u]]++;
|
||||
opt->litLengthSum = sum_u32(opt->litLengthFreq, MaxLL+1);
|
||||
}
|
||||
}
|
||||
|
||||
#include "zstd_lazy.h"
|
||||
/* ZSTD_initStats_greedy():
|
||||
* make a first compression pass, just to seed stats with more accurate starting values.
|
||||
* only works on first block, with no dictionary and no ldm.
|
||||
* this function cannot error, hence its contract must be respected.
|
||||
*/
|
||||
static void
|
||||
ZSTD_initStats_greedy(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));
|
||||
|
||||
DEBUGLOG(4, "ZSTD_initStats_greedy (srcSize=%zu)", srcSize);
|
||||
assert(ms->opt.litLengthSum == 0); /* first block */
|
||||
assert(seqStore->sequences == seqStore->sequencesStart); /* no ldm */
|
||||
assert(ms->window.dictLimit == ms->window.lowLimit); /* no dictionary */
|
||||
assert(ms->window.dictLimit - ms->nextToUpdate <= 1); /* no prefix (note: intentional overflow, defined as 2-complement) */
|
||||
|
||||
{ size_t const lastLits = ZSTD_compressBlock_greedy(ms, seqStore, tmpRep, src, srcSize); /* generate stats into seqstore */
|
||||
/* add last lits into literals buffers for proper accounting */
|
||||
assert(lastLits <= srcSize);
|
||||
ZSTD_memcpy(seqStore->lit , (const char*)src + srcSize - lastLits, lastLits);
|
||||
seqStore->lit += lastLits;
|
||||
}
|
||||
|
||||
/* transfer stats from seqStore into ms-opt */
|
||||
transfer_literalStats(&ms->opt, seqStore);
|
||||
transfer_seqStats(&ms->opt, seqStore, fix_greedy_bias);
|
||||
|
||||
/* invalidate first scan from history */
|
||||
ZSTD_resetSeqStore(seqStore);
|
||||
ms->window.base -= srcSize;
|
||||
ms->window.dictLimit += (U32)srcSize;
|
||||
ms->window.lowLimit = ms->window.dictLimit;
|
||||
ms->nextToUpdate = ms->window.dictLimit;
|
||||
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock_btultra(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
U32 const curr = (U32)((const BYTE*)src - ms->window.base);
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_btultra (srcSize=%zu)", srcSize);
|
||||
|
||||
/* 2-pass strategy (when possible):
|
||||
* this strategy makes a first pass over first block to collect statistics
|
||||
* and seed next round's statistics with it.
|
||||
* After 1st pass, function forgets everything, and starts a new block.
|
||||
* 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.4% on first block),
|
||||
* the cost is +5% cpu time on first block. */
|
||||
assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
|
||||
if ( (ms->opt.litLengthSum==0) /* first block */
|
||||
&& (seqStore->sequences == seqStore->sequencesStart) /* no ldm */
|
||||
&& (ms->window.dictLimit == ms->window.lowLimit) /* no dictionary */
|
||||
&& (curr == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */
|
||||
&& (srcSize > ZSTD_PREDEF_THRESHOLD)
|
||||
) {
|
||||
ZSTD_initStats_greedy(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
|
||||
return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ZSTD_initStats_ultra():
|
||||
@@ -1395,7 +1380,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||
U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
size_t lastLits;
|
||||
U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */
|
||||
ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep));
|
||||
|
||||
@@ -1405,23 +1389,7 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||
assert(ms->window.dictLimit == ms->window.lowLimit); /* no dictionary */
|
||||
assert(ms->window.dictLimit - ms->nextToUpdate <= 1); /* no prefix (note: intentional overflow, defined as 2-complement) */
|
||||
|
||||
if (srcSize < 8 KB) {
|
||||
/* use raw btultra, initialized by default starting stats
|
||||
* generally preferable for small blocks
|
||||
*/
|
||||
lastLits = ZSTD_compressBlock_opt_generic(ms, seqStore, tmpRep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict); /* generate stats into ms->opt*/
|
||||
} else {
|
||||
/* in this mode, btultra is initialized with greedy strategy;
|
||||
* it's generally better for larger block sizes */
|
||||
lastLits = ZSTD_compressBlock_btultra(ms, seqStore, tmpRep, src, srcSize); /* generate stats into ms->opt*/
|
||||
}
|
||||
|
||||
/* transfer stats from seqStore into ms-opt */
|
||||
assert(lastLits <= srcSize);
|
||||
ZSTD_memcpy(seqStore->lit , (const char*)src + srcSize - lastLits, lastLits);
|
||||
seqStore->lit += lastLits;
|
||||
transfer_literalStats(&ms->opt, seqStore);
|
||||
transfer_seqStats(&ms->opt, seqStore, from_btultra);
|
||||
ZSTD_compressBlock_opt2(ms, seqStore, tmpRep, src, srcSize, ZSTD_noDict); /* generate stats into ms->opt*/
|
||||
|
||||
/* invalidate first scan from history */
|
||||
ZSTD_resetSeqStore(seqStore);
|
||||
@@ -1432,6 +1400,14 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock_btultra(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_btultra (srcSize=%zu)", srcSize);
|
||||
return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock_btultra2(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
@@ -1457,35 +1433,35 @@ size_t ZSTD_compressBlock_btultra2(
|
||||
ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
|
||||
return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict);
|
||||
return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock_btopt_dictMatchState(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock_btultra_dictMatchState(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_dictMatchState);
|
||||
return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock_btopt_extDict(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_extDict);
|
||||
return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_extDict);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock_btultra_extDict(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_extDict);
|
||||
return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_extDict);
|
||||
}
|
||||
|
||||
/* note : no btultra2 variant for extDict nor dictMatchState,
|
||||
|
||||
@@ -20,8 +20,6 @@ extern "C" {
|
||||
/* used in ZSTD_loadDictionaryContent() */
|
||||
void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend);
|
||||
|
||||
/* All parsers @return the size of "last literals" segment */
|
||||
|
||||
size_t ZSTD_compressBlock_btopt(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize);
|
||||
|
||||
@@ -1550,17 +1550,21 @@ static range_t ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)
|
||||
static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range)
|
||||
{
|
||||
BYTE const* const bufferStart = (BYTE const*)buffer.start;
|
||||
BYTE const* const bufferEnd = bufferStart + buffer.capacity;
|
||||
BYTE const* const rangeStart = (BYTE const*)range.start;
|
||||
BYTE const* const rangeEnd = range.size != 0 ? rangeStart + range.size : rangeStart;
|
||||
|
||||
if (rangeStart == NULL || bufferStart == NULL)
|
||||
return 0;
|
||||
/* Empty ranges cannot overlap */
|
||||
if (bufferStart == bufferEnd || rangeStart == rangeEnd)
|
||||
return 0;
|
||||
|
||||
return bufferStart < rangeEnd && rangeStart < bufferEnd;
|
||||
{
|
||||
BYTE const* const bufferEnd = bufferStart + buffer.capacity;
|
||||
BYTE const* const rangeEnd = rangeStart + range.size;
|
||||
|
||||
/* Empty ranges cannot overlap */
|
||||
if (bufferStart == bufferEnd || rangeStart == rangeEnd)
|
||||
return 0;
|
||||
|
||||
return bufferStart < rangeEnd && rangeStart < bufferEnd;
|
||||
}
|
||||
}
|
||||
|
||||
static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
|
||||
|
||||
@@ -43,32 +43,8 @@
|
||||
#error "Cannot force the use of the X1 and X2 decoders at the same time!"
|
||||
#endif
|
||||
|
||||
/* Only use assembly on Linux / MacOS.
|
||||
* Disable when MSAN is enabled.
|
||||
*/
|
||||
#if defined(__linux__) || defined(__linux) || defined(__APPLE__)
|
||||
# if ZSTD_MEMORY_SANITIZER
|
||||
# define HUF_ASM_SUPPORTED 0
|
||||
# elif ZSTD_DATAFLOW_SANITIZER
|
||||
# define HUF_ASM_SUPPORTED 0
|
||||
# else
|
||||
# define HUF_ASM_SUPPORTED 1
|
||||
# endif
|
||||
#else
|
||||
# define HUF_ASM_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
/* HUF_DISABLE_ASM: Disables all ASM implementations. */
|
||||
#if !defined(HUF_DISABLE_ASM) && \
|
||||
HUF_ASM_SUPPORTED && \
|
||||
defined(__x86_64__) && (DYNAMIC_BMI2 || defined(__BMI2__))
|
||||
# define HUF_ENABLE_ASM_X86_64_BMI2 1
|
||||
#else
|
||||
# define HUF_ENABLE_ASM_X86_64_BMI2 0
|
||||
#endif
|
||||
|
||||
#if HUF_ENABLE_ASM_X86_64_BMI2 && DYNAMIC_BMI2
|
||||
# define HUF_ASM_X86_64_BMI2_ATTRS TARGET_ATTRIBUTE("bmi2")
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2 && DYNAMIC_BMI2
|
||||
# define HUF_ASM_X86_64_BMI2_ATTRS BMI2_TARGET_ATTRIBUTE
|
||||
#else
|
||||
# define HUF_ASM_X86_64_BMI2_ATTRS
|
||||
#endif
|
||||
@@ -80,13 +56,13 @@
|
||||
#endif
|
||||
#define HUF_ASM_DECL HUF_EXTERN_C
|
||||
|
||||
#if DYNAMIC_BMI2 || (HUF_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
|
||||
#if DYNAMIC_BMI2 || (ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
|
||||
# define HUF_NEED_BMI2_FUNCTION 1
|
||||
#else
|
||||
# define HUF_NEED_BMI2_FUNCTION 0
|
||||
#endif
|
||||
|
||||
#if !(HUF_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
|
||||
#if !(ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
|
||||
# define HUF_NEED_DEFAULT_FUNCTION 1
|
||||
#else
|
||||
# define HUF_NEED_DEFAULT_FUNCTION 0
|
||||
@@ -120,7 +96,7 @@
|
||||
return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
|
||||
} \
|
||||
\
|
||||
static TARGET_ATTRIBUTE("bmi2") size_t fn##_bmi2( \
|
||||
static BMI2_TARGET_ATTRIBUTE size_t fn##_bmi2( \
|
||||
void* dst, size_t dstSize, \
|
||||
const void* cSrc, size_t cSrcSize, \
|
||||
const HUF_DTable* DTable) \
|
||||
@@ -162,7 +138,7 @@ static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
|
||||
return dtd;
|
||||
}
|
||||
|
||||
#if HUF_ENABLE_ASM_X86_64_BMI2
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
|
||||
static size_t HUF_initDStream(BYTE const* ip) {
|
||||
BYTE const lastByte = ip[7];
|
||||
@@ -196,8 +172,9 @@ static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst,
|
||||
|
||||
BYTE* const oend = (BYTE*)dst + dstSize;
|
||||
|
||||
/* We're assuming x86-64 BMI2 - assure that this is the case. */
|
||||
assert(MEM_isLittleEndian() && !MEM_32bits());
|
||||
/* The following condition is false on x32 platform,
|
||||
* but HUF_asm is not compatible with this ABI */
|
||||
if (!(MEM_isLittleEndian() && !MEM_32bits())) return 1;
|
||||
|
||||
/* strict minimum : jump table + 1 byte per stream */
|
||||
if (srcSize < 10)
|
||||
@@ -429,7 +406,7 @@ size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t sr
|
||||
|
||||
/* fill DTable
|
||||
* We fill all entries of each weight in order.
|
||||
* That way length is a constant for each iteration of the outter loop.
|
||||
* That way length is a constant for each iteration of the outer loop.
|
||||
* We can switch based on the length to a different inner loop which is
|
||||
* optimized for that particular case.
|
||||
*/
|
||||
@@ -670,7 +647,7 @@ HUF_decompress4X1_usingDTable_internal_body(
|
||||
}
|
||||
|
||||
#if HUF_NEED_BMI2_FUNCTION
|
||||
static TARGET_ATTRIBUTE("bmi2")
|
||||
static BMI2_TARGET_ATTRIBUTE
|
||||
size_t HUF_decompress4X1_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,
|
||||
size_t cSrcSize, HUF_DTable const* DTable) {
|
||||
return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
@@ -685,7 +662,7 @@ size_t HUF_decompress4X1_usingDTable_internal_default(void* dst, size_t dstSize,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HUF_ENABLE_ASM_X86_64_BMI2
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
|
||||
HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args);
|
||||
|
||||
@@ -741,7 +718,7 @@ HUF_decompress4X1_usingDTable_internal_bmi2_asm(
|
||||
/* decoded size */
|
||||
return dstSize;
|
||||
}
|
||||
#endif /* HUF_ENABLE_ASM_X86_64_BMI2 */
|
||||
#endif /* ZSTD_ENABLE_ASM_X86_64_BMI2 */
|
||||
|
||||
typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,
|
||||
const void *cSrc,
|
||||
@@ -755,7 +732,7 @@ static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize,
|
||||
{
|
||||
#if DYNAMIC_BMI2
|
||||
if (bmi2) {
|
||||
# if HUF_ENABLE_ASM_X86_64_BMI2
|
||||
# if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
return HUF_decompress4X1_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
# else
|
||||
return HUF_decompress4X1_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
@@ -765,7 +742,7 @@ static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize,
|
||||
(void)bmi2;
|
||||
#endif
|
||||
|
||||
#if HUF_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
|
||||
return HUF_decompress4X1_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
#else
|
||||
return HUF_decompress4X1_usingDTable_internal_default(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
@@ -1355,7 +1332,7 @@ HUF_decompress4X2_usingDTable_internal_body(
|
||||
HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
|
||||
HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
|
||||
HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
|
||||
endSignal = (U32)LIKELY(
|
||||
endSignal = (U32)LIKELY((U32)
|
||||
(BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)
|
||||
& (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)
|
||||
& (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)
|
||||
@@ -1386,7 +1363,7 @@ HUF_decompress4X2_usingDTable_internal_body(
|
||||
}
|
||||
|
||||
#if HUF_NEED_BMI2_FUNCTION
|
||||
static TARGET_ATTRIBUTE("bmi2")
|
||||
static BMI2_TARGET_ATTRIBUTE
|
||||
size_t HUF_decompress4X2_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,
|
||||
size_t cSrcSize, HUF_DTable const* DTable) {
|
||||
return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
@@ -1401,7 +1378,7 @@ size_t HUF_decompress4X2_usingDTable_internal_default(void* dst, size_t dstSize,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HUF_ENABLE_ASM_X86_64_BMI2
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
|
||||
HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args);
|
||||
|
||||
@@ -1453,14 +1430,14 @@ HUF_decompress4X2_usingDTable_internal_bmi2_asm(
|
||||
/* decoded size */
|
||||
return dstSize;
|
||||
}
|
||||
#endif /* HUF_ENABLE_ASM_X86_64_BMI2 */
|
||||
#endif /* ZSTD_ENABLE_ASM_X86_64_BMI2 */
|
||||
|
||||
static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
|
||||
size_t cSrcSize, HUF_DTable const* DTable, int bmi2)
|
||||
{
|
||||
#if DYNAMIC_BMI2
|
||||
if (bmi2) {
|
||||
# if HUF_ENABLE_ASM_X86_64_BMI2
|
||||
# if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
return HUF_decompress4X2_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
# else
|
||||
return HUF_decompress4X2_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
@@ -1470,7 +1447,7 @@ static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize,
|
||||
(void)bmi2;
|
||||
#endif
|
||||
|
||||
#if HUF_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
|
||||
return HUF_decompress4X2_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
#else
|
||||
return HUF_decompress4X2_usingDTable_internal_default(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,6 @@
|
||||
* Dependencies
|
||||
*********************************************************/
|
||||
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
|
||||
#include "../common/cpu.h" /* bmi2 */
|
||||
#include "../common/mem.h" /* low level memory routines */
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "../common/fse.h"
|
||||
@@ -177,12 +176,15 @@ static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet,
|
||||
static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
|
||||
ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
|
||||
DEBUGLOG(4, "Allocating new hash set");
|
||||
if (!ret)
|
||||
return NULL;
|
||||
ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
|
||||
ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
|
||||
ret->ddictPtrCount = 0;
|
||||
if (!ret || !ret->ddictPtrTable) {
|
||||
if (!ret->ddictPtrTable) {
|
||||
ZSTD_customFree(ret, customMem);
|
||||
return NULL;
|
||||
}
|
||||
ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
|
||||
ret->ddictPtrCount = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -262,7 +264,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
||||
dctx->noForwardProgress = 0;
|
||||
dctx->oversizedDuration = 0;
|
||||
#if DYNAMIC_BMI2
|
||||
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
||||
dctx->bmi2 = ZSTD_cpuSupportsBmi2();
|
||||
#endif
|
||||
dctx->ddictSet = NULL;
|
||||
ZSTD_DCtx_resetParameters(dctx);
|
||||
@@ -913,7 +915,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
switch(blockProperties.blockType)
|
||||
{
|
||||
case bt_compressed:
|
||||
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1);
|
||||
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
|
||||
break;
|
||||
case bt_raw :
|
||||
decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
|
||||
@@ -1120,7 +1122,7 @@ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t
|
||||
return dctx->expected;
|
||||
if (dctx->bType != bt_raw)
|
||||
return dctx->expected;
|
||||
return MIN(MAX(inputSize, 1), dctx->expected);
|
||||
return BOUNDED(1, inputSize, dctx->expected);
|
||||
}
|
||||
|
||||
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
||||
@@ -1226,7 +1228,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||
{
|
||||
case bt_compressed:
|
||||
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
||||
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
|
||||
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
|
||||
dctx->expected = 0; /* Streaming not supported */
|
||||
break;
|
||||
case bt_raw :
|
||||
@@ -1821,7 +1823,8 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
|
||||
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
|
||||
{
|
||||
size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
||||
unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
|
||||
/* space is needed to store the litbuffer after the output of a given block without stomping the extDict of a previous run, as well as to cover both windows against wildcopy*/
|
||||
unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
|
||||
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
||||
size_t const minRBSize = (size_t) neededSize;
|
||||
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,12 @@
|
||||
*/
|
||||
|
||||
|
||||
/* Streaming state is used to inform allocation of the literal buffer */
|
||||
typedef enum {
|
||||
not_streaming = 0,
|
||||
is_streaming = 1
|
||||
} streaming_operation;
|
||||
|
||||
/* ZSTD_decompressBlock_internal() :
|
||||
* decompress block, starting at `src`,
|
||||
* into destination buffer `dst`.
|
||||
@@ -41,7 +47,7 @@
|
||||
*/
|
||||
size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize, const int frame);
|
||||
const void* src, size_t srcSize, const int frame, const streaming_operation streaming);
|
||||
|
||||
/* ZSTD_buildFSETable() :
|
||||
* generate FSE decoding table for one symbol (ll, ml or off)
|
||||
@@ -54,7 +60,7 @@ size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
*/
|
||||
void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
|
||||
const short* normalizedCounter, unsigned maxSymbolValue,
|
||||
const U32* baseValue, const U32* nbAdditionalBits,
|
||||
const U32* baseValue, const U8* nbAdditionalBits,
|
||||
unsigned tableLog, void* wksp, size_t wkspSize,
|
||||
int bmi2);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ static UNUSED_ATTR const U32 OF_base[MaxOff+1] = {
|
||||
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
|
||||
0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
|
||||
|
||||
static UNUSED_ATTR const U32 OF_bits[MaxOff+1] = {
|
||||
static UNUSED_ATTR const U8 OF_bits[MaxOff+1] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
@@ -106,6 +106,22 @@ typedef struct {
|
||||
size_t ddictPtrCount;
|
||||
} ZSTD_DDictHashSet;
|
||||
|
||||
#ifndef ZSTD_DECODER_INTERNAL_BUFFER
|
||||
# define ZSTD_DECODER_INTERNAL_BUFFER (1 << 16)
|
||||
#endif
|
||||
|
||||
#define ZSTD_LBMIN 64
|
||||
#define ZSTD_LBMAX (128 << 10)
|
||||
|
||||
/* extra buffer, compensates when dst is not large enough to store litBuffer */
|
||||
#define ZSTD_LITBUFFEREXTRASIZE BOUNDED(ZSTD_LBMIN, ZSTD_DECODER_INTERNAL_BUFFER, ZSTD_LBMAX)
|
||||
|
||||
typedef enum {
|
||||
ZSTD_not_in_dst = 0, /* Stored entirely within litExtraBuffer */
|
||||
ZSTD_in_dst = 1, /* Stored entirely within dst (in memory after current output write) */
|
||||
ZSTD_split = 2 /* Split between litExtraBuffer and dst */
|
||||
} ZSTD_litLocation_e;
|
||||
|
||||
struct ZSTD_DCtx_s
|
||||
{
|
||||
const ZSTD_seqSymbol* LLTptr;
|
||||
@@ -171,7 +187,10 @@ struct ZSTD_DCtx_s
|
||||
ZSTD_outBuffer expectedOutBuffer;
|
||||
|
||||
/* workspace */
|
||||
BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
|
||||
BYTE* litBuffer;
|
||||
const BYTE* litBufferEnd;
|
||||
ZSTD_litLocation_e litBufferLocation;
|
||||
BYTE litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE + WILDCOPY_OVERLENGTH]; /* literal buffer can be split between storage within dst and within this scratch buffer */
|
||||
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
|
||||
|
||||
size_t oversizedDuration;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
***************************************/
|
||||
#define ZBUFF_STATIC_LINKING_ONLY
|
||||
#include "zbuff.h"
|
||||
#include "../common/error_private.h"
|
||||
|
||||
|
||||
/*-***********************************************************
|
||||
@@ -73,13 +74,32 @@ size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* preserve "0 == unknown" behavior */
|
||||
return ZSTD_initCStream_advanced(zbc, dict, dictSize, params, pledgedSrcSize);
|
||||
}
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_reset(zbc, ZSTD_reset_session_only), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setPledgedSrcSize(zbc, pledgedSrcSize), "");
|
||||
|
||||
FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_windowLog, params.cParams.windowLog), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_hashLog, params.cParams.hashLog), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_chainLog, params.cParams.chainLog), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_searchLog, params.cParams.searchLog), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_minMatch, params.cParams.minMatch), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_targetLength, params.cParams.targetLength), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_strategy, params.cParams.strategy), "");
|
||||
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_contentSizeFlag, params.fParams.contentSizeFlag), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_checksumFlag, params.fParams.checksumFlag), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_dictIDFlag, params.fParams.noDictIDFlag), "");
|
||||
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_loadDictionary(zbc, dict, dictSize), "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZBUFF_compressInitDictionary(ZBUFF_CCtx* zbc, const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
return ZSTD_initCStream_usingDict(zbc, dict, dictSize, compressionLevel);
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_reset(zbc, ZSTD_reset_session_only), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_compressionLevel, compressionLevel), "");
|
||||
FORWARD_IF_ERROR(ZSTD_CCtx_loadDictionary(zbc, dict, dictSize), "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZBUFF_compressInit(ZBUFF_CCtx* zbc, int compressionLevel)
|
||||
|
||||
@@ -40,6 +40,13 @@
|
||||
/*-*************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
/**
|
||||
* There are 32bit indexes used to ref samples, so limit samples size to 4GB
|
||||
* on 64bit builds.
|
||||
* For 32bit builds we choose 1 GB.
|
||||
* Most 32bit platforms have 2GB user-mode addressable space and we allocate a large
|
||||
* contiguous buffer, so 1GB is already a high limit.
|
||||
*/
|
||||
#define COVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB))
|
||||
#define COVER_DEFAULT_SPLITPOINT 1.0
|
||||
|
||||
|
||||
@@ -32,6 +32,13 @@
|
||||
/*-*************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
/**
|
||||
* There are 32bit indexes used to ref samples, so limit samples size to 4GB
|
||||
* on 64bit builds.
|
||||
* For 32bit builds we choose 1 GB.
|
||||
* Most 32bit platforms have 2GB user-mode addressable space and we allocate a large
|
||||
* contiguous buffer, so 1GB is already a high limit.
|
||||
*/
|
||||
#define FASTCOVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB))
|
||||
#define FASTCOVER_MAX_F 31
|
||||
#define FASTCOVER_MAX_ACCEL 10
|
||||
|
||||
+87
-22
@@ -135,9 +135,14 @@ static unsigned ZDICT_NbCommonBytes (size_t val)
|
||||
if (MEM_isLittleEndian()) {
|
||||
if (MEM_64bits()) {
|
||||
# if defined(_MSC_VER) && defined(_WIN64)
|
||||
unsigned long r = 0;
|
||||
_BitScanForward64( &r, (U64)val );
|
||||
return (unsigned)(r>>3);
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanForward64(&r, (U64)val);
|
||||
return (unsigned)(r >> 3);
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (unsigned)(__builtin_ctzll((U64)val) >> 3);
|
||||
# else
|
||||
@@ -146,9 +151,14 @@ static unsigned ZDICT_NbCommonBytes (size_t val)
|
||||
# endif
|
||||
} else { /* 32 bits */
|
||||
# if defined(_MSC_VER)
|
||||
unsigned long r=0;
|
||||
_BitScanForward( &r, (U32)val );
|
||||
return (unsigned)(r>>3);
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanForward(&r, (U32)val);
|
||||
return (unsigned)(r >> 3);
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (unsigned)(__builtin_ctz((U32)val) >> 3);
|
||||
# else
|
||||
@@ -159,9 +169,14 @@ static unsigned ZDICT_NbCommonBytes (size_t val)
|
||||
} else { /* Big Endian CPU */
|
||||
if (MEM_64bits()) {
|
||||
# if defined(_MSC_VER) && defined(_WIN64)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse64( &r, val );
|
||||
return (unsigned)(r>>3);
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanReverse64(&r, val);
|
||||
return (unsigned)(r >> 3);
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (unsigned)(__builtin_clzll(val) >> 3);
|
||||
# else
|
||||
@@ -174,9 +189,14 @@ static unsigned ZDICT_NbCommonBytes (size_t val)
|
||||
# endif
|
||||
} else { /* 32 bits */
|
||||
# if defined(_MSC_VER)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse( &r, (unsigned long)val );
|
||||
return (unsigned)(r>>3);
|
||||
if (val != 0) {
|
||||
unsigned long r;
|
||||
_BitScanReverse(&r, (unsigned long)val);
|
||||
return (unsigned)(r >> 3);
|
||||
} else {
|
||||
/* Should not reach this code path */
|
||||
__assume(0);
|
||||
}
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (unsigned)(__builtin_clz((U32)val) >> 3);
|
||||
# else
|
||||
@@ -627,6 +647,7 @@ static void ZDICT_countEStats(EStats_ress_t esr, const ZSTD_parameters* params,
|
||||
if (srcSize > blockSizeMax) srcSize = blockSizeMax; /* protection vs large samples */
|
||||
{ size_t const errorCode = ZSTD_compressBegin_usingCDict(esr.zc, esr.dict);
|
||||
if (ZSTD_isError(errorCode)) { DISPLAYLEVEL(1, "warning : ZSTD_compressBegin_usingCDict failed \n"); return; }
|
||||
|
||||
}
|
||||
cSize = ZSTD_compressBlock(esr.zc, esr.workPlace, ZSTD_BLOCKSIZE_MAX, src, srcSize);
|
||||
if (ZSTD_isError(cSize)) { DISPLAYLEVEL(3, "warning : could not compress sample size %u \n", (unsigned)srcSize); return; }
|
||||
@@ -636,7 +657,7 @@ static void ZDICT_countEStats(EStats_ress_t esr, const ZSTD_parameters* params,
|
||||
|
||||
/* literals stats */
|
||||
{ const BYTE* bytePtr;
|
||||
for (bytePtr = seqStorePtr->litStart; bytePtr < seqStorePtr->lit; bytePtr++)
|
||||
for(bytePtr = seqStorePtr->litStart; bytePtr < seqStorePtr->lit; bytePtr++)
|
||||
countLit[*bytePtr]++;
|
||||
}
|
||||
|
||||
@@ -661,8 +682,8 @@ static void ZDICT_countEStats(EStats_ress_t esr, const ZSTD_parameters* params,
|
||||
|
||||
if (nbSeq >= 2) { /* rep offsets */
|
||||
const seqDef* const seq = seqStorePtr->sequencesStart;
|
||||
U32 offset1 = seq[0].offset - 3;
|
||||
U32 offset2 = seq[1].offset - 3;
|
||||
U32 offset1 = seq[0].offBase - ZSTD_REP_NUM;
|
||||
U32 offset2 = seq[1].offBase - ZSTD_REP_NUM;
|
||||
if (offset1 >= MAXREPOFFSET) offset1 = 0;
|
||||
if (offset2 >= MAXREPOFFSET) offset2 = 0;
|
||||
repOffsets[offset1] += 3;
|
||||
@@ -894,6 +915,17 @@ _cleanup:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @returns the maximum repcode value
|
||||
*/
|
||||
static U32 ZDICT_maxRep(U32 const reps[ZSTD_REP_NUM])
|
||||
{
|
||||
U32 maxRep = reps[0];
|
||||
int r;
|
||||
for (r = 1; r < ZSTD_REP_NUM; ++r)
|
||||
maxRep = MAX(maxRep, reps[r]);
|
||||
return maxRep;
|
||||
}
|
||||
|
||||
size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
|
||||
const void* customDictContent, size_t dictContentSize,
|
||||
@@ -905,11 +937,13 @@ size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
|
||||
BYTE header[HBUFFSIZE];
|
||||
int const compressionLevel = (params.compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : params.compressionLevel;
|
||||
U32 const notificationLevel = params.notificationLevel;
|
||||
/* The final dictionary content must be at least as large as the largest repcode */
|
||||
size_t const minContentSize = (size_t)ZDICT_maxRep(repStartValue);
|
||||
size_t paddingSize;
|
||||
|
||||
/* check conditions */
|
||||
DEBUGLOG(4, "ZDICT_finalizeDictionary");
|
||||
if (dictBufferCapacity < dictContentSize) return ERROR(dstSize_tooSmall);
|
||||
if (dictContentSize < ZDICT_CONTENTSIZE_MIN) return ERROR(srcSize_wrong);
|
||||
if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) return ERROR(dstSize_tooSmall);
|
||||
|
||||
/* dictionary header */
|
||||
@@ -933,12 +967,43 @@ size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
|
||||
hSize += eSize;
|
||||
}
|
||||
|
||||
/* copy elements in final buffer ; note : src and dst buffer can overlap */
|
||||
if (hSize + dictContentSize > dictBufferCapacity) dictContentSize = dictBufferCapacity - hSize;
|
||||
{ size_t const dictSize = hSize + dictContentSize;
|
||||
char* dictEnd = (char*)dictBuffer + dictSize;
|
||||
memmove(dictEnd - dictContentSize, customDictContent, dictContentSize);
|
||||
memcpy(dictBuffer, header, hSize);
|
||||
/* Shrink the content size if it doesn't fit in the buffer */
|
||||
if (hSize + dictContentSize > dictBufferCapacity) {
|
||||
dictContentSize = dictBufferCapacity - hSize;
|
||||
}
|
||||
|
||||
/* Pad the dictionary content with zeros if it is too small */
|
||||
if (dictContentSize < minContentSize) {
|
||||
RETURN_ERROR_IF(hSize + minContentSize > dictBufferCapacity, dstSize_tooSmall,
|
||||
"dictBufferCapacity too small to fit max repcode");
|
||||
paddingSize = minContentSize - dictContentSize;
|
||||
} else {
|
||||
paddingSize = 0;
|
||||
}
|
||||
|
||||
{
|
||||
size_t const dictSize = hSize + paddingSize + dictContentSize;
|
||||
|
||||
/* The dictionary consists of the header, optional padding, and the content.
|
||||
* The padding comes before the content because the "best" position in the
|
||||
* dictionary is the last byte.
|
||||
*/
|
||||
BYTE* const outDictHeader = (BYTE*)dictBuffer;
|
||||
BYTE* const outDictPadding = outDictHeader + hSize;
|
||||
BYTE* const outDictContent = outDictPadding + paddingSize;
|
||||
|
||||
assert(dictSize <= dictBufferCapacity);
|
||||
assert(outDictContent + dictContentSize == (BYTE*)dictBuffer + dictSize);
|
||||
|
||||
/* First copy the customDictContent into its final location.
|
||||
* `customDictContent` and `dictBuffer` may overlap, so we must
|
||||
* do this before any other writes into the output buffer.
|
||||
* Then copy the header & padding into the output buffer.
|
||||
*/
|
||||
memmove(outDictContent, customDictContent, dictContentSize);
|
||||
memcpy(outDictHeader, header, hSize);
|
||||
memset(outDictPadding, 0, paddingSize);
|
||||
|
||||
return dictSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,10 +204,7 @@ typedef signed long long S64;
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef FSE_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
|
||||
# define FSE_FORCE_MEMORY_ACCESS 2
|
||||
# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define FSE_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
@@ -343,8 +340,7 @@ FORCE_INLINE unsigned FSE_highbit32 (U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
unsigned long r;
|
||||
_BitScanReverse ( &r, val );
|
||||
return (unsigned) r;
|
||||
return _BitScanReverse(&r, val) ? (unsigned)r : 0;
|
||||
# elif defined(__GNUC__) && (GCC_VERSION >= 304) /* GCC Intrinsic */
|
||||
return __builtin_clz (val) ^ 31;
|
||||
# else /* Software version */
|
||||
|
||||
@@ -129,10 +129,7 @@ extern "C" {
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
|
||||
# define MEM_FORCE_MEMORY_ACCESS 2
|
||||
# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
@@ -353,9 +350,8 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
|
||||
MEM_STATIC unsigned BIT_highbit32 (U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
unsigned long r=0;
|
||||
_BitScanReverse ( &r, val );
|
||||
return (unsigned) r;
|
||||
unsigned long r;
|
||||
return _BitScanReverse(&r, val) ? (unsigned)r : 0;
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
||||
return __builtin_clz (val) ^ 31;
|
||||
# else /* Software version */
|
||||
|
||||
@@ -130,10 +130,7 @@ extern "C" {
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
|
||||
# define MEM_FORCE_MEMORY_ACCESS 2
|
||||
# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
@@ -356,9 +353,8 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
|
||||
MEM_STATIC unsigned BIT_highbit32 (U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
unsigned long r=0;
|
||||
_BitScanReverse ( &r, val );
|
||||
return (unsigned) r;
|
||||
unsigned long r;
|
||||
return _BitScanReverse(&r, val) ? (unsigned)r : 0;
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
||||
return __builtin_clz (val) ^ 31;
|
||||
# else /* Software version */
|
||||
|
||||
@@ -101,10 +101,7 @@ extern "C" {
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
|
||||
# define MEM_FORCE_MEMORY_ACCESS 2
|
||||
# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
@@ -627,9 +624,8 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
|
||||
MEM_STATIC unsigned BIT_highbit32 (U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
unsigned long r=0;
|
||||
_BitScanReverse ( &r, val );
|
||||
return (unsigned) r;
|
||||
unsigned long r;
|
||||
return _BitScanReverse(&r, val) ? (unsigned)r : 0;
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
||||
return __builtin_clz (val) ^ 31;
|
||||
# else /* Software version */
|
||||
|
||||
@@ -120,10 +120,7 @@ extern "C" {
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
|
||||
# define MEM_FORCE_MEMORY_ACCESS 2
|
||||
# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
@@ -756,9 +753,8 @@ MEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, unsigned nbBits);
|
||||
MEM_STATIC unsigned BITv05_highbit32 (U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
unsigned long r=0;
|
||||
_BitScanReverse ( &r, val );
|
||||
return (unsigned) r;
|
||||
unsigned long r;
|
||||
return _BitScanReverse(&r, val) ? (unsigned)r : 0;
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
||||
return __builtin_clz (val) ^ 31;
|
||||
# else /* Software version */
|
||||
|
||||
@@ -122,10 +122,7 @@ extern "C" {
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
|
||||
# define MEM_FORCE_MEMORY_ACCESS 2
|
||||
# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
@@ -860,9 +857,8 @@ MEM_STATIC size_t BITv06_readBitsFast(BITv06_DStream_t* bitD, unsigned nbBits);
|
||||
MEM_STATIC unsigned BITv06_highbit32 ( U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
unsigned long r=0;
|
||||
_BitScanReverse ( &r, val );
|
||||
return (unsigned) r;
|
||||
unsigned long r;
|
||||
return _BitScanReverse(&r, val) ? (unsigned)r : 0;
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
||||
return __builtin_clz (val) ^ 31;
|
||||
# else /* Software version */
|
||||
|
||||
@@ -282,10 +282,7 @@ extern "C" {
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
|
||||
# define MEM_FORCE_MEMORY_ACCESS 2
|
||||
# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
@@ -530,9 +527,8 @@ MEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, unsigned nbBits);
|
||||
MEM_STATIC unsigned BITv07_highbit32 (U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
unsigned long r=0;
|
||||
_BitScanReverse ( &r, val );
|
||||
return (unsigned) r;
|
||||
unsigned long r;
|
||||
return _BitScanReverse(&r, val) ? (unsigned)r : 0;
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
||||
return __builtin_clz (val) ^ 31;
|
||||
# else /* Software version */
|
||||
|
||||
+17
-2
@@ -34,6 +34,8 @@ ZSTD_NO_ASM ?= 0
|
||||
# libzstd helpers
|
||||
##################################################################
|
||||
|
||||
VOID ?= /dev/null
|
||||
|
||||
# Make 4.3 doesn't support '\#' anymore (https://lwn.net/Articles/810071/)
|
||||
NUM_SYMBOL := \#
|
||||
|
||||
@@ -79,7 +81,7 @@ endif
|
||||
CFLAGS += -fno-stack-protector -fomit-frame-pointer -fno-ident \
|
||||
-DDYNAMIC_BMI2=0 -DNDEBUG
|
||||
else
|
||||
CFLAGS += -O3
|
||||
CFLAGS ?= -O3
|
||||
endif
|
||||
|
||||
DEBUGLEVEL ?= 0
|
||||
@@ -96,6 +98,19 @@ CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||
LDFLAGS += $(MOREFLAGS)
|
||||
FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
ifndef ALREADY_APPENDED_NOEXECSTACK
|
||||
export ALREADY_APPENDED_NOEXECSTACK := 1
|
||||
ifeq ($(shell echo "int main(int argc, char* argv[]) { (void)argc; (void)argv; return 0; }" | $(CC) $(FLAGS) -z noexecstack -x c -Werror - -o $(VOID) 2>$(VOID) && echo 1 || echo 0),1)
|
||||
LDFLAGS += -z noexecstack
|
||||
endif
|
||||
ifeq ($(shell echo | $(CC) $(FLAGS) -Wa,--noexecstack -x assembler -Werror -c - -o $(VOID) 2>$(VOID) && echo 1 || echo 0),1)
|
||||
CFLAGS += -Wa,--noexecstack
|
||||
else ifeq ($(shell echo | $(CC) $(FLAGS) -Qunused-arguments -Wa,--noexecstack -x assembler -Werror -c - -o $(VOID) 2>$(VOID) && echo 1 || echo 0),1)
|
||||
# See e.g.: https://github.com/android/ndk/issues/171
|
||||
CFLAGS += -Qunused-arguments -Wa,--noexecstack
|
||||
endif
|
||||
endif
|
||||
|
||||
HAVE_COLORNEVER = $(shell echo a | grep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0)
|
||||
GREP_OPTIONS ?=
|
||||
ifeq ($HAVE_COLORNEVER, 1)
|
||||
@@ -114,7 +129,7 @@ ZSTD_LEGACY_FILES :=
|
||||
ZSTD_DECOMPRESS_AMD64_ASM_FILES := $(sort $(wildcard $(LIBZSTD)/decompress/*_amd64.S))
|
||||
|
||||
ifneq ($(ZSTD_NO_ASM), 0)
|
||||
CPPFLAGS += -DHUF_DISABLE_ASM
|
||||
CPPFLAGS += -DZSTD_DISABLE_ASM
|
||||
else
|
||||
# Unconditionally add the ASM files they are disabled by
|
||||
# macros in the .S file.
|
||||
|
||||
@@ -12,4 +12,5 @@ Description: fast lossless compression algorithm library
|
||||
URL: http://www.zstd.net/
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lzstd
|
||||
Libs.private: @LIBS_PRIVATE@
|
||||
Cflags: -I${includedir}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
module libzstd [extern_c] {
|
||||
header "zstd.h"
|
||||
export *
|
||||
config_macros [exhaustive] /* zstd.h */ \
|
||||
ZSTD_STATIC_LINKING_ONLY, \
|
||||
ZSTDLIB_VISIBLE, \
|
||||
ZSTD_DLL_EXPORT, \
|
||||
ZSTDLIB_STATIC_API, \
|
||||
ZSTD_DISABLE_DEPRECATE_WARNINGS, \
|
||||
ZSTD_CLEVEL_DEFAULT, \
|
||||
/* zdict.h */ ZDICT_STATIC_LINKING_ONLY, \
|
||||
ZDICTLIB_VISIBILITY, \
|
||||
ZDICT_DISABLE_DEPRECATE_WARNINGS, \
|
||||
/* zstd_errors.h */ ZSTDERRORLIB_VISIBILITY
|
||||
|
||||
module dictbuilder [extern_c] {
|
||||
header "zdict.h"
|
||||
export *
|
||||
}
|
||||
|
||||
module errors [extern_c] {
|
||||
header "zstd_errors.h"
|
||||
export *
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -46,7 +46,7 @@ extern "C" {
|
||||
*
|
||||
* Zstd can use dictionaries to improve compression ratio of small data.
|
||||
* Traditionally small files don't compress well because there is very little
|
||||
* repetion in a single sample, since it is small. But, if you are compressing
|
||||
* repetition in a single sample, since it is small. But, if you are compressing
|
||||
* many similar files, like a bunch of JSON records that share the same
|
||||
* structure, you can train a dictionary on ahead of time on some samples of
|
||||
* these files. Then, zstd can use the dictionary to find repetitions that are
|
||||
@@ -132,7 +132,7 @@ extern "C" {
|
||||
*
|
||||
* # Benchmark levels 1-3 without a dictionary
|
||||
* zstd -b1e3 -r /path/to/my/files
|
||||
* # Benchmark levels 1-3 with a dictioanry
|
||||
* # Benchmark levels 1-3 with a dictionary
|
||||
* zstd -b1e3 -r /path/to/my/files -D /path/to/my/dictionary
|
||||
*
|
||||
* When should I retrain a dictionary?
|
||||
@@ -237,7 +237,6 @@ typedef struct {
|
||||
* is presumed that the most profitable content is at the end of the dictionary,
|
||||
* since that is the cheapest to reference.
|
||||
*
|
||||
* `dictContentSize` must be >= ZDICT_CONTENTSIZE_MIN bytes.
|
||||
* `maxDictSize` must be >= max(dictContentSize, ZSTD_DICTSIZE_MIN).
|
||||
*
|
||||
* @return: size of dictionary stored into `dstDictBuffer` (<= `maxDictSize`),
|
||||
@@ -272,8 +271,9 @@ ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode);
|
||||
* Use them only in association with static linking.
|
||||
* ==================================================================================== */
|
||||
|
||||
#define ZDICT_CONTENTSIZE_MIN 128
|
||||
#define ZDICT_DICTSIZE_MIN 256
|
||||
/* Deprecated: Remove in v1.6.0 */
|
||||
#define ZDICT_CONTENTSIZE_MIN 128
|
||||
|
||||
/*! ZDICT_cover_params_t:
|
||||
* k and d are the only required parameters.
|
||||
|
||||
+123
-110
@@ -20,19 +20,21 @@ extern "C" {
|
||||
|
||||
|
||||
/* ===== ZSTDLIB_API : control library symbols visibility ===== */
|
||||
#ifndef ZSTDLIB_VISIBILITY
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
# define ZSTDLIB_VISIBILITY __attribute__ ((visibility ("default")))
|
||||
#ifndef ZSTDLIB_VISIBLE
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
# define ZSTDLIB_VISIBLE __attribute__ ((visibility ("default")))
|
||||
# define ZSTDLIB_HIDDEN __attribute__ ((visibility ("hidden")))
|
||||
# else
|
||||
# define ZSTDLIB_VISIBILITY
|
||||
# define ZSTDLIB_VISIBLE
|
||||
# define ZSTDLIB_HIDDEN
|
||||
# endif
|
||||
#endif
|
||||
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||
# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBILITY
|
||||
# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBLE
|
||||
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||
# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#else
|
||||
# define ZSTDLIB_API ZSTDLIB_VISIBILITY
|
||||
# define ZSTDLIB_API ZSTDLIB_VISIBLE
|
||||
#endif
|
||||
|
||||
|
||||
@@ -247,7 +249,7 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
|
||||
*
|
||||
* It's possible to reset all parameters to "default" using ZSTD_CCtx_reset().
|
||||
*
|
||||
* This API supercedes all other "advanced" API entry points in the experimental section.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -1073,25 +1075,36 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
|
||||
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
|
||||
|
||||
/* This can be overridden externally to hide static symbols. */
|
||||
#ifndef ZSTDLIB_STATIC_API
|
||||
# if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||
# define ZSTDLIB_STATIC_API __declspec(dllexport) ZSTDLIB_VISIBLE
|
||||
# elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||
# define ZSTDLIB_STATIC_API __declspec(dllimport) ZSTDLIB_VISIBLE
|
||||
# else
|
||||
# define ZSTDLIB_STATIC_API ZSTDLIB_VISIBLE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Deprecation warnings :
|
||||
* Should these warnings be a problem, it is generally possible to disable them,
|
||||
* typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual.
|
||||
* Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS.
|
||||
*/
|
||||
#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_API /* disable deprecation warnings */
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API /* disable deprecation warnings */
|
||||
#else
|
||||
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
||||
# define ZSTD_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_API
|
||||
# define ZSTD_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_STATIC_API
|
||||
# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__)
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated(message)))
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API __attribute__((deprecated(message)))
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated))
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API __attribute__((deprecated))
|
||||
# elif defined(_MSC_VER)
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_API __declspec(deprecated(message))
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API __declspec(deprecated(message))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement ZSTD_DEPRECATED for this compiler")
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_API
|
||||
# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API
|
||||
# endif
|
||||
#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */
|
||||
|
||||
@@ -1333,7 +1346,7 @@ typedef enum {
|
||||
* note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to
|
||||
* read each contained frame header. This is fast as most of the data is skipped,
|
||||
* however it does mean that all frame data must be present and valid. */
|
||||
ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_decompressBound() :
|
||||
* `src` should point to the start of a series of ZSTD encoded and/or skippable frames
|
||||
@@ -1348,13 +1361,13 @@ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t
|
||||
* note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:
|
||||
* upper-bound = # blocks * min(128 KB, Window_Size)
|
||||
*/
|
||||
ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_frameHeaderSize() :
|
||||
* srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
|
||||
* @return : size of the Frame Header,
|
||||
* or an error code (if srcSize is too small) */
|
||||
ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
|
||||
|
||||
typedef enum {
|
||||
ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */
|
||||
@@ -1377,7 +1390,7 @@ typedef enum {
|
||||
* @return : number of sequences generated
|
||||
*/
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
||||
size_t outSeqsSize, const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_mergeBlockDelimiters() :
|
||||
@@ -1391,7 +1404,7 @@ ZSTDLIB_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
||||
* setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters
|
||||
* @return : number of sequences left after merging
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);
|
||||
|
||||
/*! ZSTD_compressSequences() :
|
||||
* Compress an array of ZSTD_Sequence, generated from the original source buffer, into dst.
|
||||
@@ -1421,7 +1434,7 @@ ZSTDLIB_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t se
|
||||
* and cannot emit an RLE block that disagrees with the repcode history
|
||||
* @return : final compressed size or a ZSTD error.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize,
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize,
|
||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
@@ -1439,7 +1452,7 @@ ZSTDLIB_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size
|
||||
*
|
||||
* @return : number of bytes written or a ZSTD error.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize, unsigned magicVariant);
|
||||
|
||||
/*! ZSTD_readSkippableFrame() :
|
||||
@@ -1490,10 +1503,10 @@ ZSTDLIB_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);
|
||||
* Note 2 : only single-threaded compression is supported.
|
||||
* ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
|
||||
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);
|
||||
|
||||
/*! ZSTD_estimateCStreamSize() :
|
||||
* ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one.
|
||||
@@ -1508,20 +1521,20 @@ ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
|
||||
* 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 */
|
||||
ZSTDLIB_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDStreamSize(size_t windowSize);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
|
||||
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_fromFrame(const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_estimate?DictSize() :
|
||||
* ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict().
|
||||
* ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced().
|
||||
* Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
|
||||
|
||||
/*! ZSTD_initStatic*() :
|
||||
* Initialize an object using a pre-allocated fixed-size buffer.
|
||||
@@ -1544,20 +1557,20 @@ ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e
|
||||
* Limitation 2 : static cctx currently not compatible with multi-threading.
|
||||
* Limitation 3 : static dctx is incompatible with legacy support.
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
|
||||
ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */
|
||||
ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
|
||||
ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */
|
||||
|
||||
ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);
|
||||
ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */
|
||||
ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);
|
||||
ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */
|
||||
|
||||
ZSTDLIB_API const ZSTD_CDict* ZSTD_initStaticCDict(
|
||||
ZSTDLIB_STATIC_API const ZSTD_CDict* ZSTD_initStaticCDict(
|
||||
void* workspace, size_t workspaceSize,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||
ZSTD_dictContentType_e dictContentType,
|
||||
ZSTD_compressionParameters cParams);
|
||||
|
||||
ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict(
|
||||
ZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict(
|
||||
void* workspace, size_t workspaceSize,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||
@@ -1578,44 +1591,44 @@ __attribute__((__unused__))
|
||||
#endif
|
||||
ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */
|
||||
|
||||
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
|
||||
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
|
||||
ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
|
||||
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
|
||||
ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
|
||||
ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
|
||||
ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
|
||||
ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
|
||||
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
|
||||
ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
|
||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||
ZSTD_dictContentType_e dictContentType,
|
||||
ZSTD_compressionParameters cParams,
|
||||
ZSTD_customMem customMem);
|
||||
|
||||
/* ! Thread pool :
|
||||
* These prototypes make it possible to share a thread pool among multiple compression contexts.
|
||||
* This can limit resources for applications with multiple threads where each one uses
|
||||
* a threaded compression mode (via ZSTD_c_nbWorkers parameter).
|
||||
* ZSTD_createThreadPool creates a new thread pool with a given number of threads.
|
||||
* Note that the lifetime of such pool must exist while being used.
|
||||
* ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
|
||||
* to use an internal thread pool).
|
||||
* ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.
|
||||
/*! Thread pool :
|
||||
* These prototypes make it possible to share a thread pool among multiple compression contexts.
|
||||
* This can limit resources for applications with multiple threads where each one uses
|
||||
* a threaded compression mode (via ZSTD_c_nbWorkers parameter).
|
||||
* ZSTD_createThreadPool creates a new thread pool with a given number of threads.
|
||||
* Note that the lifetime of such pool must exist while being used.
|
||||
* ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
|
||||
* to use an internal thread pool).
|
||||
* ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.
|
||||
*/
|
||||
typedef struct POOL_ctx_s ZSTD_threadPool;
|
||||
ZSTDLIB_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
|
||||
ZSTDLIB_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
|
||||
ZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
|
||||
ZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
|
||||
|
||||
|
||||
/*
|
||||
* This API is temporary and is expected to change or disappear in the future!
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
|
||||
ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced2(
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||
ZSTD_dictContentType_e dictContentType,
|
||||
const ZSTD_CCtx_params* cctxParams,
|
||||
ZSTD_customMem customMem);
|
||||
|
||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(
|
||||
ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_advanced(
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||
ZSTD_dictContentType_e dictContentType,
|
||||
@@ -1632,22 +1645,22 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(
|
||||
* As a consequence, `dictBuffer` **must** outlive CDict,
|
||||
* and its content must remain unmodified throughout the lifetime of CDict.
|
||||
* note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||
ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||
|
||||
/*! ZSTD_getCParams() :
|
||||
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
||||
* `estimatedSrcSize` value is optional, select 0 if not known */
|
||||
ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_getParams() :
|
||||
* same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
|
||||
* All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */
|
||||
ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
ZSTDLIB_STATIC_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_checkCParams() :
|
||||
* Ensure param values remain within authorized range.
|
||||
* @return 0 on success, or an error code (can be checked with ZSTD_isError()) */
|
||||
ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
|
||||
/*! ZSTD_adjustCParams() :
|
||||
* optimize params for a given `srcSize` and `dictSize`.
|
||||
@@ -1655,7 +1668,7 @@ ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
* `dictSize` must be `0` when there is no dictionary.
|
||||
* cPar can be invalid : all parameters will be clamped within valid range in the @return struct.
|
||||
* This function never fails (wide contract) */
|
||||
ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
|
||||
ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_compress_advanced() :
|
||||
* Note : this function is now DEPRECATED.
|
||||
@@ -1683,18 +1696,18 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
|
||||
/*! ZSTD_CCtx_loadDictionary_byReference() :
|
||||
* Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx.
|
||||
* It saves some memory, but also requires that `dict` outlives its usage within `cctx` */
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
||||
|
||||
/*! ZSTD_CCtx_loadDictionary_advanced() :
|
||||
* Same as ZSTD_CCtx_loadDictionary(), but gives finer control over
|
||||
* how to load the dictionary (by copy ? by reference ?)
|
||||
* and how to interpret it (automatic ? force raw mode ? full mode only ?) */
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
|
||||
|
||||
/*! ZSTD_CCtx_refPrefix_advanced() :
|
||||
* Same as ZSTD_CCtx_refPrefix(), but gives finer control over
|
||||
* how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
|
||||
|
||||
/* === experimental parameters === */
|
||||
/* these parameters can be used with ZSTD_setParameter()
|
||||
@@ -1804,7 +1817,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
|
||||
*
|
||||
* Note that this means that the CDict tables can no longer be copied into the
|
||||
* CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be
|
||||
* useable. The dictionary can only be attached or reloaded.
|
||||
* usable. The dictionary can only be attached or reloaded.
|
||||
*
|
||||
* In general, you should expect compression to be faster--sometimes very much
|
||||
* so--and CDict creation to be slightly slower. Eventually, we will probably
|
||||
@@ -1941,7 +1954,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
|
||||
* and store it into int* value.
|
||||
* @return : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
|
||||
|
||||
|
||||
/*! ZSTD_CCtx_params :
|
||||
@@ -1961,25 +1974,25 @@ ZSTDLIB_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter
|
||||
* This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
|
||||
* for static allocation of CCtx for single-threaded compression.
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
|
||||
ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */
|
||||
ZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */
|
||||
|
||||
/*! ZSTD_CCtxParams_reset() :
|
||||
* Reset params to default values.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
|
||||
|
||||
/*! ZSTD_CCtxParams_init() :
|
||||
* Initializes the compression parameters of cctxParams according to
|
||||
* compression level. All other parameters are reset to their default values.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
|
||||
|
||||
/*! ZSTD_CCtxParams_init_advanced() :
|
||||
* Initializes the compression and frame parameters of cctxParams according to
|
||||
* params. All other parameters are reset to their default values.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
|
||||
|
||||
/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+
|
||||
* Similar to ZSTD_CCtx_setParameter.
|
||||
@@ -1989,14 +2002,14 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, Z
|
||||
* @result : a code representing success or failure (which can be tested with
|
||||
* ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
|
||||
|
||||
/*! ZSTD_CCtxParams_getParameter() :
|
||||
* Similar to ZSTD_CCtx_getParameter.
|
||||
* Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
||||
|
||||
/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
|
||||
* Apply a set of ZSTD_CCtx_params to the compression context.
|
||||
@@ -2005,7 +2018,7 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params,
|
||||
* if nbWorkers>=1, new parameters will be picked up at next job,
|
||||
* with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
||||
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);
|
||||
|
||||
/*! ZSTD_compressStream2_simpleArgs() :
|
||||
@@ -2014,7 +2027,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
||||
* This variant might be helpful for binders from dynamic languages
|
||||
* which have troubles handling structures containing memory pointers.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_compressStream2_simpleArgs (
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs (
|
||||
ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity, size_t* dstPos,
|
||||
const void* src, size_t srcSize, size_t* srcPos,
|
||||
@@ -2030,33 +2043,33 @@ ZSTDLIB_API size_t ZSTD_compressStream2_simpleArgs (
|
||||
* Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
|
||||
* Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
|
||||
* Note 3 : Skippable Frame Identifiers are considered valid. */
|
||||
ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
|
||||
ZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
|
||||
|
||||
/*! ZSTD_createDDict_byReference() :
|
||||
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||
* Dictionary content is referenced, and therefore stays in dictBuffer.
|
||||
* It is important that dictBuffer outlives DDict,
|
||||
* it must remain read accessible throughout the lifetime of DDict */
|
||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
|
||||
ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
|
||||
|
||||
/*! ZSTD_DCtx_loadDictionary_byReference() :
|
||||
* Same as ZSTD_DCtx_loadDictionary(),
|
||||
* but references `dict` content instead of copying it into `dctx`.
|
||||
* This saves memory if `dict` remains around.,
|
||||
* However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
||||
|
||||
/*! ZSTD_DCtx_loadDictionary_advanced() :
|
||||
* Same as ZSTD_DCtx_loadDictionary(),
|
||||
* but gives direct control over
|
||||
* how to load the dictionary (by copy ? by reference ?)
|
||||
* and how to interpret it (automatic ? force raw mode ? full mode only ?). */
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
|
||||
|
||||
/*! ZSTD_DCtx_refPrefix_advanced() :
|
||||
* Same as ZSTD_DCtx_refPrefix(), but gives finer control over
|
||||
* how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
|
||||
|
||||
/*! ZSTD_DCtx_setMaxWindowSize() :
|
||||
* Refuses allocating internal buffers for frames requiring a window size larger than provided limit.
|
||||
@@ -2065,14 +2078,14 @@ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* pre
|
||||
* By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT)
|
||||
* @return : 0, or an error code (which can be tested using ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
|
||||
|
||||
/*! ZSTD_DCtx_getParameter() :
|
||||
* Get the requested decompression parameter value, selected by enum ZSTD_dParameter,
|
||||
* and store it into int* value.
|
||||
* @return : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);
|
||||
|
||||
/* ZSTD_d_format
|
||||
* experimental parameter,
|
||||
@@ -2161,7 +2174,7 @@ size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
|
||||
* This can be helpful for binders from dynamic languages
|
||||
* which have troubles handling structures containing memory pointers.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs (
|
||||
ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity, size_t* dstPos,
|
||||
const void* src, size_t srcSize, size_t* srcPos);
|
||||
@@ -2300,7 +2313,7 @@ typedef struct {
|
||||
* Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed.
|
||||
* Aggregates progression inside active worker threads.
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_STATIC_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);
|
||||
|
||||
/*! ZSTD_toFlushNow() :
|
||||
* Tell how many bytes are ready to be flushed immediately.
|
||||
@@ -2315,7 +2328,7 @@ ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx
|
||||
* therefore flush speed is limited by production speed of oldest job
|
||||
* irrespective of the speed of concurrent (and newer) jobs.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
|
||||
|
||||
|
||||
/*===== Advanced Streaming decompression functions =====*/
|
||||
@@ -2329,7 +2342,7 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
|
||||
* note: no dictionary will be used if dict == NULL or dictSize < 8
|
||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
|
||||
|
||||
/*!
|
||||
* This function is deprecated, and is equivalent to:
|
||||
@@ -2340,7 +2353,7 @@ ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dic
|
||||
* note : ddict is referenced, it must outlive decompression session
|
||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
|
||||
|
||||
/*!
|
||||
* This function is deprecated, and is equivalent to:
|
||||
@@ -2350,7 +2363,7 @@ ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDi
|
||||
* re-use decompression parameters from previous init; saves dictionary loading
|
||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
@@ -2392,13 +2405,13 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
*/
|
||||
|
||||
/*===== Buffer-less streaming compression functions =====*/
|
||||
ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
|
||||
ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
|
||||
/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */
|
||||
ZSTD_DEPRECATED("use advanced API to access custom parameters")
|
||||
@@ -2495,24 +2508,24 @@ typedef struct {
|
||||
* @return : 0, `zfhPtr` is correctly filled,
|
||||
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
|
||||
* or an error code, which can be tested using ZSTD_isError() */
|
||||
ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */
|
||||
/*! ZSTD_getFrameHeader_advanced() :
|
||||
* same as ZSTD_getFrameHeader(),
|
||||
* with added capability to select a format (like ZSTD_f_zstd1_magicless) */
|
||||
ZSTDLIB_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
|
||||
ZSTDLIB_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);
|
||||
ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
||||
ZSTDLIB_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);
|
||||
ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
|
||||
/* misc */
|
||||
ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);
|
||||
ZSTDLIB_STATIC_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);
|
||||
typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
|
||||
ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
|
||||
ZSTDLIB_STATIC_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
|
||||
|
||||
|
||||
|
||||
@@ -2549,10 +2562,10 @@ ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
|
||||
*/
|
||||
|
||||
/*===== Raw zstd block functions =====*/
|
||||
ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
|
||||
|
||||
|
||||
#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */
|
||||
|
||||
+5
-7
@@ -41,7 +41,7 @@ ZSTDLIB_LOCAL_SRC = $(notdir $(ZSTDLIB_FULL_SRC))
|
||||
ZSTDLIB_LOCAL_OBJ0 := $(ZSTDLIB_LOCAL_SRC:.c=.o)
|
||||
ZSTDLIB_LOCAL_OBJ := $(ZSTDLIB_LOCAL_OBJ0:.S=.o)
|
||||
|
||||
ZSTD_CLI_SRC := $(wildcard *.c)
|
||||
ZSTD_CLI_SRC := $(sort $(wildcard *.c))
|
||||
ZSTD_CLI_OBJ := $(ZSTD_CLI_SRC:.c=.o)
|
||||
|
||||
ZSTD_ALL_SRC = $(ZSTDLIB_LOCAL_SRC) $(ZSTD_CLI_SRC)
|
||||
@@ -62,8 +62,6 @@ else
|
||||
EXT =
|
||||
endif
|
||||
|
||||
VOID = /dev/null
|
||||
|
||||
# thread detection
|
||||
NO_THREAD_MSG := ==> no threads, building without multithreading support
|
||||
HAVE_PTHREAD := $(shell printf '$(NUM_SYMBOL)include <pthread.h>\nint main(void) { return 0; }' > have_pthread.c && $(CC) $(FLAGS) -o have_pthread$(EXT) have_pthread.c -pthread 2> $(VOID) && rm have_pthread$(EXT) && echo 1 || echo 0; rm have_pthread.c)
|
||||
@@ -164,8 +162,8 @@ $(BUILD_DIR)/zstd : $(ZSTD_OBJ)
|
||||
$(CC) $(FLAGS) $^ $(LDLIBS) -o $@$(EXT)
|
||||
|
||||
ifeq ($(HAVE_HASH),1)
|
||||
SRCBIN_HASH = $(shell cat $(BUILD_DIR)/zstd 2> $(VOID) | $(HASH) | cut -f 1 -d " ")
|
||||
DSTBIN_HASH = $(shell cat zstd 2> $(VOID) | $(HASH) | cut -f 1 -d " ")
|
||||
SRCBIN_HASH = $(shell cat $(BUILD_DIR)/zstd$(EXT) 2> $(VOID) | $(HASH) | cut -f 1 -d " ")
|
||||
DSTBIN_HASH = $(shell cat zstd$(EXT) 2> $(VOID) | $(HASH) | cut -f 1 -d " ")
|
||||
BIN_ISDIFFERENT = $(if $(filter $(SRCBIN_HASH),$(DSTBIN_HASH)),0,1)
|
||||
else
|
||||
BIN_ISDIFFERENT = 1
|
||||
@@ -173,7 +171,7 @@ endif
|
||||
|
||||
zstd : $(BUILD_DIR)/zstd
|
||||
if [ $(BIN_ISDIFFERENT) -eq 1 ]; then \
|
||||
cp -f $< $@; \
|
||||
cp -f $<$(EXT) $@$(EXT); \
|
||||
echo zstd build completed; \
|
||||
else \
|
||||
echo zstd already built; \
|
||||
@@ -337,7 +335,7 @@ include $(wildcard $(DEPFILES))
|
||||
#-----------------------------------------------------------------------------
|
||||
# make install is validated only for Linux, macOS, BSD, Hurd and Solaris targets
|
||||
#-----------------------------------------------------------------------------
|
||||
ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku))
|
||||
ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX))
|
||||
|
||||
HAVE_COLORNEVER = $(shell echo a | egrep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0)
|
||||
EGREP_OPTIONS ?=
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ Arguments :
|
||||
|
||||
Advanced arguments :
|
||||
-V : display Version number and exit
|
||||
-c : force write to standard output, even if it is the console
|
||||
-c : write to standard output (even if it is the console)
|
||||
-v : verbose mode; specify multiple times to increase verbosity
|
||||
-q : suppress warnings; specify twice to suppress errors too
|
||||
--no-progress : do not display the progress counter
|
||||
|
||||
@@ -31,9 +31,14 @@
|
||||
#include "timefn.h" /* UTIL_time_t */
|
||||
#include "benchfn.h"
|
||||
#include "../lib/common/mem.h"
|
||||
#ifndef ZSTD_STATIC_LINKING_ONLY
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
#endif
|
||||
#include "../lib/zstd.h"
|
||||
#include "datagen.h" /* RDG_genBuffer */
|
||||
#ifndef XXH_INLINE_ALL
|
||||
#define XXH_INLINE_ALL
|
||||
#endif
|
||||
#include "../lib/common/xxhash.h"
|
||||
#include "benchzstd.h"
|
||||
#include "../lib/zstd_errors.h"
|
||||
@@ -452,11 +457,11 @@ BMK_benchMemAdvancedNoAlloc(
|
||||
|
||||
{ int const ratioAccuracy = (ratio < 10.) ? 3 : 2;
|
||||
assert(cSize < UINT_MAX);
|
||||
OUTPUTLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.*f), %6.*f MB/s\r",
|
||||
OUTPUTLEVEL(2, "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s \r",
|
||||
marks[markNb], displayName,
|
||||
(unsigned)srcSize, (unsigned)cSize,
|
||||
ratioAccuracy, ratio,
|
||||
benchResult.cSpeed < (10 MB) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT);
|
||||
benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT);
|
||||
}
|
||||
compressionCompleted = BMK_isCompleted_TimedFn(timeStateCompress);
|
||||
}
|
||||
@@ -475,11 +480,11 @@ BMK_benchMemAdvancedNoAlloc(
|
||||
}
|
||||
|
||||
{ int const ratioAccuracy = (ratio < 10.) ? 3 : 2;
|
||||
OUTPUTLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.*f), %6.*f MB/s, %6.1f MB/s \r",
|
||||
OUTPUTLEVEL(2, "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s, %6.1f MB/s\r",
|
||||
marks[markNb], displayName,
|
||||
(unsigned)srcSize, (unsigned)cSize,
|
||||
ratioAccuracy, ratio,
|
||||
benchResult.cSpeed < (10 MB) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT,
|
||||
benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT,
|
||||
(double)benchResult.dSpeed / MB_UNIT);
|
||||
}
|
||||
decompressionCompleted = BMK_isCompleted_TimedFn(timeStateDecompress);
|
||||
|
||||
+154
-79
@@ -31,7 +31,6 @@
|
||||
|
||||
#include "timefn.h" /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */
|
||||
#include "../lib/common/mem.h" /* read */
|
||||
#include "../lib/common/error_private.h"
|
||||
#include "dibio.h"
|
||||
|
||||
|
||||
@@ -49,6 +48,7 @@
|
||||
static const size_t g_maxMemory = (sizeof(size_t) == 4) ? (2 GB - 64 MB) : ((size_t)(512 MB) << sizeof(size_t));
|
||||
|
||||
#define NOISELENGTH 32
|
||||
#define MAX_SAMPLES_SIZE (2 GB) /* training dataset limited to 2GB */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -88,6 +88,15 @@ static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
|
||||
#undef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
/**
|
||||
Returns the size of a file.
|
||||
If error returns -1.
|
||||
*/
|
||||
static S64 DiB_getFileSize (const char * fileName)
|
||||
{
|
||||
U64 const fileSize = UTIL_getFileSize(fileName);
|
||||
return (fileSize == UTIL_FILESIZE_UNKNOWN) ? -1 : (S64)fileSize;
|
||||
}
|
||||
|
||||
/* ********************************************************
|
||||
* File related operations
|
||||
@@ -101,47 +110,67 @@ static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
|
||||
* *bufferSizePtr is modified, it provides the amount data loaded within buffer.
|
||||
* sampleSizes is filled with the size of each sample.
|
||||
*/
|
||||
static unsigned DiB_loadFiles(void* buffer, size_t* bufferSizePtr,
|
||||
size_t* sampleSizes, unsigned sstSize,
|
||||
const char** fileNamesTable, unsigned nbFiles, size_t targetChunkSize,
|
||||
unsigned displayLevel)
|
||||
static int DiB_loadFiles(
|
||||
void* buffer, size_t* bufferSizePtr,
|
||||
size_t* sampleSizes, int sstSize,
|
||||
const char** fileNamesTable, int nbFiles,
|
||||
size_t targetChunkSize, int displayLevel )
|
||||
{
|
||||
char* const buff = (char*)buffer;
|
||||
size_t pos = 0;
|
||||
unsigned nbLoadedChunks = 0, fileIndex;
|
||||
size_t totalDataLoaded = 0;
|
||||
int nbSamplesLoaded = 0;
|
||||
int fileIndex = 0;
|
||||
FILE * f = NULL;
|
||||
|
||||
for (fileIndex=0; fileIndex<nbFiles; fileIndex++) {
|
||||
const char* const fileName = fileNamesTable[fileIndex];
|
||||
unsigned long long const fs64 = UTIL_getFileSize(fileName);
|
||||
unsigned long long remainingToLoad = (fs64 == UTIL_FILESIZE_UNKNOWN) ? 0 : fs64;
|
||||
U32 const nbChunks = targetChunkSize ? (U32)((fs64 + (targetChunkSize-1)) / targetChunkSize) : 1;
|
||||
U64 const chunkSize = targetChunkSize ? MIN(targetChunkSize, fs64) : fs64;
|
||||
size_t const maxChunkSize = (size_t)MIN(chunkSize, SAMPLESIZE_MAX);
|
||||
U32 cnb;
|
||||
FILE* const f = fopen(fileName, "rb");
|
||||
if (f==NULL) EXM_THROW(10, "zstd: dictBuilder: %s %s ", fileName, strerror(errno));
|
||||
DISPLAYUPDATE(2, "Loading %s... \r", fileName);
|
||||
for (cnb=0; cnb<nbChunks; cnb++) {
|
||||
size_t const toLoad = (size_t)MIN(maxChunkSize, remainingToLoad);
|
||||
if (toLoad > *bufferSizePtr-pos) break;
|
||||
{ size_t const readSize = fread(buff+pos, 1, toLoad, f);
|
||||
if (readSize != toLoad) EXM_THROW(11, "Pb reading %s", fileName);
|
||||
pos += readSize;
|
||||
sampleSizes[nbLoadedChunks++] = toLoad;
|
||||
remainingToLoad -= targetChunkSize;
|
||||
if (nbLoadedChunks == sstSize) { /* no more space left in sampleSizes table */
|
||||
fileIndex = nbFiles; /* stop there */
|
||||
assert(targetChunkSize <= SAMPLESIZE_MAX);
|
||||
|
||||
while ( nbSamplesLoaded < sstSize && fileIndex < nbFiles ) {
|
||||
size_t fileDataLoaded;
|
||||
S64 const fileSize = DiB_getFileSize(fileNamesTable[fileIndex]);
|
||||
if (fileSize <= 0) /* skip if zero-size or file error */
|
||||
continue;
|
||||
|
||||
f = fopen( fileNamesTable[fileIndex], "rb");
|
||||
if (f == NULL)
|
||||
EXM_THROW(10, "zstd: dictBuilder: %s %s ", fileNamesTable[fileIndex], strerror(errno));
|
||||
DISPLAYUPDATE(2, "Loading %s... \r", fileNamesTable[fileIndex]);
|
||||
|
||||
/* Load the first chunk of data from the file */
|
||||
fileDataLoaded = targetChunkSize > 0 ?
|
||||
(size_t)MIN(fileSize, (S64)targetChunkSize) :
|
||||
(size_t)MIN(fileSize, SAMPLESIZE_MAX );
|
||||
if (totalDataLoaded + fileDataLoaded > *bufferSizePtr)
|
||||
break;
|
||||
if (fread( buff+totalDataLoaded, 1, fileDataLoaded, f ) != fileDataLoaded)
|
||||
EXM_THROW(11, "Pb reading %s", fileNamesTable[fileIndex]);
|
||||
sampleSizes[nbSamplesLoaded++] = fileDataLoaded;
|
||||
totalDataLoaded += fileDataLoaded;
|
||||
|
||||
/* If file-chunking is enabled, load the rest of the file as more samples */
|
||||
if (targetChunkSize > 0) {
|
||||
while( (S64)fileDataLoaded < fileSize && nbSamplesLoaded < sstSize ) {
|
||||
size_t const chunkSize = MIN((size_t)(fileSize-fileDataLoaded), targetChunkSize);
|
||||
if (totalDataLoaded + chunkSize > *bufferSizePtr) /* buffer is full */
|
||||
break;
|
||||
}
|
||||
if (toLoad < targetChunkSize) {
|
||||
fseek(f, (long)(targetChunkSize - toLoad), SEEK_CUR);
|
||||
} } }
|
||||
fclose(f);
|
||||
|
||||
if (fread( buff+totalDataLoaded, 1, chunkSize, f ) != chunkSize)
|
||||
EXM_THROW(11, "Pb reading %s", fileNamesTable[fileIndex]);
|
||||
sampleSizes[nbSamplesLoaded++] = chunkSize;
|
||||
totalDataLoaded += chunkSize;
|
||||
fileDataLoaded += chunkSize;
|
||||
}
|
||||
}
|
||||
fileIndex += 1;
|
||||
fclose(f); f = NULL;
|
||||
}
|
||||
if (f != NULL)
|
||||
fclose(f);
|
||||
|
||||
DISPLAYLEVEL(2, "\r%79s\r", "");
|
||||
*bufferSizePtr = pos;
|
||||
DISPLAYLEVEL(4, "loaded : %u KB \n", (unsigned)(pos >> 10))
|
||||
return nbLoadedChunks;
|
||||
DISPLAYLEVEL(4, "Loaded %d KB total training data, %d nb samples \n",
|
||||
(int)(totalDataLoaded / (1 KB)), nbSamplesLoaded );
|
||||
*bufferSizePtr = totalDataLoaded;
|
||||
return nbSamplesLoaded;
|
||||
}
|
||||
|
||||
#define DiB_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
@@ -223,11 +252,10 @@ static void DiB_saveDict(const char* dictFileName,
|
||||
if (n!=0) EXM_THROW(5, "%s : flush error", dictFileName) }
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
U64 totalSizeToLoad;
|
||||
unsigned oneSampleTooLarge;
|
||||
unsigned nbSamples;
|
||||
S64 totalSizeToLoad;
|
||||
int nbSamples;
|
||||
int oneSampleTooLarge;
|
||||
} fileStats;
|
||||
|
||||
/*! DiB_fileStats() :
|
||||
@@ -235,46 +263,92 @@ typedef struct {
|
||||
* provides the amount of data to be loaded and the resulting nb of samples.
|
||||
* This is useful primarily for allocation purpose => sample buffer, and sample sizes table.
|
||||
*/
|
||||
static fileStats DiB_fileStats(const char** fileNamesTable, unsigned nbFiles, size_t chunkSize, unsigned displayLevel)
|
||||
static fileStats DiB_fileStats(const char** fileNamesTable, int nbFiles, size_t chunkSize, int displayLevel)
|
||||
{
|
||||
fileStats fs;
|
||||
unsigned n;
|
||||
int n;
|
||||
memset(&fs, 0, sizeof(fs));
|
||||
|
||||
// We assume that if chunking is requested, the chunk size is < SAMPLESIZE_MAX
|
||||
assert( chunkSize <= SAMPLESIZE_MAX );
|
||||
|
||||
for (n=0; n<nbFiles; n++) {
|
||||
U64 const fileSize = UTIL_getFileSize(fileNamesTable[n]);
|
||||
U64 const srcSize = (fileSize == UTIL_FILESIZE_UNKNOWN) ? 0 : fileSize;
|
||||
U32 const nbSamples = (U32)(chunkSize ? (srcSize + (chunkSize-1)) / chunkSize : 1);
|
||||
U64 const chunkToLoad = chunkSize ? MIN(chunkSize, srcSize) : srcSize;
|
||||
size_t const cappedChunkSize = (size_t)MIN(chunkToLoad, SAMPLESIZE_MAX);
|
||||
fs.totalSizeToLoad += cappedChunkSize * nbSamples;
|
||||
fs.oneSampleTooLarge |= (chunkSize > 2*SAMPLESIZE_MAX);
|
||||
fs.nbSamples += nbSamples;
|
||||
S64 const fileSize = DiB_getFileSize(fileNamesTable[n]);
|
||||
// TODO: is there a minimum sample size? What if the file is 1-byte?
|
||||
if (fileSize == 0) {
|
||||
DISPLAYLEVEL(3, "Sample file '%s' has zero size, skipping...\n", fileNamesTable[n]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* the case where we are breaking up files in sample chunks */
|
||||
if (chunkSize > 0)
|
||||
{
|
||||
// TODO: is there a minimum sample size? Can we have a 1-byte sample?
|
||||
fs.nbSamples += (int)((fileSize + chunkSize-1) / chunkSize);
|
||||
fs.totalSizeToLoad += fileSize;
|
||||
}
|
||||
else {
|
||||
/* the case where one file is one sample */
|
||||
if (fileSize > SAMPLESIZE_MAX) {
|
||||
/* flag excessively large sample files */
|
||||
fs.oneSampleTooLarge |= (fileSize > 2*SAMPLESIZE_MAX);
|
||||
|
||||
/* Limit to the first SAMPLESIZE_MAX (128kB) of the file */
|
||||
DISPLAYLEVEL(3, "Sample file '%s' is too large, limiting to %d KB",
|
||||
fileNamesTable[n], SAMPLESIZE_MAX / (1 KB));
|
||||
}
|
||||
fs.nbSamples += 1;
|
||||
fs.totalSizeToLoad += MIN(fileSize, SAMPLESIZE_MAX);
|
||||
}
|
||||
}
|
||||
DISPLAYLEVEL(4, "Preparing to load : %u KB \n", (unsigned)(fs.totalSizeToLoad >> 10));
|
||||
DISPLAYLEVEL(4, "Found training data %d files, %d KB, %d samples\n", nbFiles, (int)(fs.totalSizeToLoad / (1 KB)), fs.nbSamples);
|
||||
return fs;
|
||||
}
|
||||
|
||||
|
||||
int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
||||
const char** fileNamesTable, unsigned nbFiles, size_t chunkSize,
|
||||
int DiB_trainFromFiles(const char* dictFileName, size_t maxDictSize,
|
||||
const char** fileNamesTable, int nbFiles, size_t chunkSize,
|
||||
ZDICT_legacy_params_t* params, ZDICT_cover_params_t* coverParams,
|
||||
ZDICT_fastCover_params_t* fastCoverParams, int optimize)
|
||||
ZDICT_fastCover_params_t* fastCoverParams, int optimize, unsigned memLimit)
|
||||
{
|
||||
unsigned const displayLevel = params ? params->zParams.notificationLevel :
|
||||
coverParams ? coverParams->zParams.notificationLevel :
|
||||
fastCoverParams ? fastCoverParams->zParams.notificationLevel :
|
||||
0; /* should never happen */
|
||||
fileStats fs;
|
||||
size_t* sampleSizes; /* vector of sample sizes. Each sample can be up to SAMPLESIZE_MAX */
|
||||
int nbSamplesLoaded; /* nb of samples effectively loaded in srcBuffer */
|
||||
size_t loadedSize; /* total data loaded in srcBuffer for all samples */
|
||||
void* srcBuffer /* contiguous buffer with training data/samples */;
|
||||
void* const dictBuffer = malloc(maxDictSize);
|
||||
fileStats const fs = DiB_fileStats(fileNamesTable, nbFiles, chunkSize, displayLevel);
|
||||
size_t* const sampleSizes = (size_t*)malloc(fs.nbSamples * sizeof(size_t));
|
||||
size_t const memMult = params ? MEMMULT :
|
||||
coverParams ? COVER_MEMMULT:
|
||||
FASTCOVER_MEMMULT;
|
||||
size_t const maxMem = DiB_findMaxMem(fs.totalSizeToLoad * memMult) / memMult;
|
||||
size_t loadedSize = (size_t) MIN ((unsigned long long)maxMem, fs.totalSizeToLoad);
|
||||
void* const srcBuffer = malloc(loadedSize+NOISELENGTH);
|
||||
int result = 0;
|
||||
|
||||
int const displayLevel = params ? params->zParams.notificationLevel :
|
||||
coverParams ? coverParams->zParams.notificationLevel :
|
||||
fastCoverParams ? fastCoverParams->zParams.notificationLevel : 0;
|
||||
|
||||
/* Shuffle input files before we start assessing how much sample datA to load.
|
||||
The purpose of the shuffle is to pick random samples when the sample
|
||||
set is larger than what we can load in memory. */
|
||||
DISPLAYLEVEL(3, "Shuffling input files\n");
|
||||
DiB_shuffle(fileNamesTable, nbFiles);
|
||||
|
||||
/* Figure out how much sample data to load with how many samples */
|
||||
fs = DiB_fileStats(fileNamesTable, nbFiles, chunkSize, displayLevel);
|
||||
|
||||
{
|
||||
int const memMult = params ? MEMMULT :
|
||||
coverParams ? COVER_MEMMULT:
|
||||
FASTCOVER_MEMMULT;
|
||||
size_t const maxMem = DiB_findMaxMem(fs.totalSizeToLoad * memMult) / memMult;
|
||||
/* Limit the size of the training data to the free memory */
|
||||
/* Limit the size of the training data to 2GB */
|
||||
/* TODO: there is opportunity to stop DiB_fileStats() early when the data limit is reached */
|
||||
loadedSize = (size_t)MIN( MIN((S64)maxMem, fs.totalSizeToLoad), MAX_SAMPLES_SIZE );
|
||||
if (memLimit != 0) {
|
||||
DISPLAYLEVEL(2, "! Warning : setting manual memory limit for dictionary training data at %u MB \n",
|
||||
(unsigned)(memLimit / (1 MB)));
|
||||
loadedSize = (size_t)MIN(loadedSize, memLimit);
|
||||
}
|
||||
srcBuffer = malloc(loadedSize+NOISELENGTH);
|
||||
sampleSizes = (size_t*)malloc(fs.nbSamples * sizeof(size_t));
|
||||
}
|
||||
|
||||
/* Checks */
|
||||
if ((!sampleSizes) || (!srcBuffer) || (!dictBuffer))
|
||||
EXM_THROW(12, "not enough memory for DiB_trainFiles"); /* should not happen */
|
||||
@@ -289,31 +363,32 @@ int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
||||
DISPLAYLEVEL(2, "! Alternatively, split files into fixed-size blocks representative of samples, with -B# \n");
|
||||
EXM_THROW(14, "nb of samples too low"); /* we now clearly forbid this case */
|
||||
}
|
||||
if (fs.totalSizeToLoad < (unsigned long long)maxDictSize * 8) {
|
||||
if (fs.totalSizeToLoad < (S64)maxDictSize * 8) {
|
||||
DISPLAYLEVEL(2, "! Warning : data size of samples too small for target dictionary size \n");
|
||||
DISPLAYLEVEL(2, "! Samples should be about 100x larger than target dictionary size \n");
|
||||
}
|
||||
|
||||
/* init */
|
||||
if (loadedSize < fs.totalSizeToLoad)
|
||||
DISPLAYLEVEL(1, "Not enough memory; training on %u MB only...\n", (unsigned)(loadedSize >> 20));
|
||||
if ((S64)loadedSize < fs.totalSizeToLoad)
|
||||
DISPLAYLEVEL(1, "Training samples set too large (%u MB); training on %u MB only...\n",
|
||||
(unsigned)(fs.totalSizeToLoad / (1 MB)),
|
||||
(unsigned)(loadedSize / (1 MB)));
|
||||
|
||||
/* Load input buffer */
|
||||
DISPLAYLEVEL(3, "Shuffling input files\n");
|
||||
DiB_shuffle(fileNamesTable, nbFiles);
|
||||
|
||||
DiB_loadFiles(srcBuffer, &loadedSize, sampleSizes, fs.nbSamples, fileNamesTable, nbFiles, chunkSize, displayLevel);
|
||||
nbSamplesLoaded = DiB_loadFiles(
|
||||
srcBuffer, &loadedSize, sampleSizes, fs.nbSamples, fileNamesTable,
|
||||
nbFiles, chunkSize, displayLevel);
|
||||
|
||||
{ size_t dictSize;
|
||||
if (params) {
|
||||
DiB_fillNoise((char*)srcBuffer + loadedSize, NOISELENGTH); /* guard band, for end of buffer condition */
|
||||
dictSize = ZDICT_trainFromBuffer_legacy(dictBuffer, maxDictSize,
|
||||
srcBuffer, sampleSizes, fs.nbSamples,
|
||||
srcBuffer, sampleSizes, nbSamplesLoaded,
|
||||
*params);
|
||||
} else if (coverParams) {
|
||||
if (optimize) {
|
||||
dictSize = ZDICT_optimizeTrainFromBuffer_cover(dictBuffer, maxDictSize,
|
||||
srcBuffer, sampleSizes, fs.nbSamples,
|
||||
srcBuffer, sampleSizes, nbSamplesLoaded,
|
||||
coverParams);
|
||||
if (!ZDICT_isError(dictSize)) {
|
||||
unsigned splitPercentage = (unsigned)(coverParams->splitPoint * 100);
|
||||
@@ -322,13 +397,13 @@ int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
||||
}
|
||||
} else {
|
||||
dictSize = ZDICT_trainFromBuffer_cover(dictBuffer, maxDictSize, srcBuffer,
|
||||
sampleSizes, fs.nbSamples, *coverParams);
|
||||
sampleSizes, nbSamplesLoaded, *coverParams);
|
||||
}
|
||||
} else {
|
||||
assert(fastCoverParams != NULL);
|
||||
if (optimize) {
|
||||
dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(dictBuffer, maxDictSize,
|
||||
srcBuffer, sampleSizes, fs.nbSamples,
|
||||
srcBuffer, sampleSizes, nbSamplesLoaded,
|
||||
fastCoverParams);
|
||||
if (!ZDICT_isError(dictSize)) {
|
||||
unsigned splitPercentage = (unsigned)(fastCoverParams->splitPoint * 100);
|
||||
@@ -338,7 +413,7 @@ int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
||||
}
|
||||
} else {
|
||||
dictSize = ZDICT_trainFromBuffer_fastCover(dictBuffer, maxDictSize, srcBuffer,
|
||||
sampleSizes, fs.nbSamples, *fastCoverParams);
|
||||
sampleSizes, nbSamplesLoaded, *fastCoverParams);
|
||||
}
|
||||
}
|
||||
if (ZDICT_isError(dictSize)) {
|
||||
|
||||
+3
-3
@@ -31,9 +31,9 @@
|
||||
`parameters` is optional and can be provided with values set to 0, meaning "default".
|
||||
@return : 0 == ok. Any other : error.
|
||||
*/
|
||||
int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
||||
const char** fileNamesTable, unsigned nbFiles, size_t chunkSize,
|
||||
int DiB_trainFromFiles(const char* dictFileName, size_t maxDictSize,
|
||||
const char** fileNamesTable, int nbFiles, size_t chunkSize,
|
||||
ZDICT_legacy_params_t* params, ZDICT_cover_params_t* coverParams,
|
||||
ZDICT_fastCover_params_t* fastCoverParams, int optimize);
|
||||
ZDICT_fastCover_params_t* fastCoverParams, int optimize, unsigned memLimit);
|
||||
|
||||
#endif
|
||||
|
||||
+82
-11
@@ -732,29 +732,43 @@ static size_t FIO_createDictBuffer(void** bufferPtr, const char* fileName, FIO_p
|
||||
{
|
||||
FILE* fileHandle;
|
||||
U64 fileSize;
|
||||
stat_t statbuf;
|
||||
|
||||
assert(bufferPtr != NULL);
|
||||
*bufferPtr = NULL;
|
||||
if (fileName == NULL) return 0;
|
||||
|
||||
DISPLAYLEVEL(4,"Loading %s as dictionary \n", fileName);
|
||||
fileHandle = fopen(fileName, "rb");
|
||||
if (fileHandle==NULL) EXM_THROW(31, "%s: %s", fileName, strerror(errno));
|
||||
|
||||
fileSize = UTIL_getFileSize(fileName);
|
||||
if (!UTIL_stat(fileName, &statbuf)) {
|
||||
EXM_THROW(31, "Stat failed on dictionary file %s: %s", fileName, strerror(errno));
|
||||
}
|
||||
|
||||
if (!UTIL_isRegularFileStat(&statbuf)) {
|
||||
EXM_THROW(32, "Dictionary %s must be a regular file.", fileName);
|
||||
}
|
||||
|
||||
fileHandle = fopen(fileName, "rb");
|
||||
|
||||
if (fileHandle == NULL) {
|
||||
EXM_THROW(33, "Couldn't open dictionary %s: %s", fileName, strerror(errno));
|
||||
}
|
||||
|
||||
fileSize = UTIL_getFileSizeStat(&statbuf);
|
||||
{
|
||||
size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;
|
||||
if (fileSize > dictSizeMax) {
|
||||
EXM_THROW(32, "Dictionary file %s is too large (> %u bytes)",
|
||||
EXM_THROW(34, "Dictionary file %s is too large (> %u bytes)",
|
||||
fileName, (unsigned)dictSizeMax); /* avoid extreme cases */
|
||||
}
|
||||
}
|
||||
*bufferPtr = malloc((size_t)fileSize);
|
||||
if (*bufferPtr==NULL) EXM_THROW(34, "%s", strerror(errno));
|
||||
{ size_t const readSize = fread(*bufferPtr, 1, (size_t)fileSize, fileHandle);
|
||||
if (readSize != fileSize)
|
||||
if (readSize != fileSize) {
|
||||
EXM_THROW(35, "Error reading dictionary file %s : %s",
|
||||
fileName, strerror(errno));
|
||||
}
|
||||
}
|
||||
fclose(fileHandle);
|
||||
return (size_t)fileSize;
|
||||
@@ -889,26 +903,25 @@ static int FIO_removeMultiFilesWarning(FIO_ctx_t* const fCtx, const FIO_prefs_t*
|
||||
if (fCtx->nbFilesTotal > 1 && !prefs->overwrite) {
|
||||
if (g_display_prefs.displayLevel <= displayLevelCutoff) {
|
||||
if (prefs->removeSrcFile) {
|
||||
DISPLAYLEVEL(1, "zstd: Aborting... not deleting files and processing into dst: %s", outFileName);
|
||||
DISPLAYLEVEL(1, "zstd: Aborting... not deleting files and processing into dst: %s\n", outFileName);
|
||||
error = 1;
|
||||
}
|
||||
} else {
|
||||
if (!strcmp(outFileName, stdoutmark)) {
|
||||
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into stdout. ");
|
||||
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into stdout. \n");
|
||||
} else {
|
||||
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into a single output file: %s ", outFileName);
|
||||
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into a single output file: %s \n", outFileName);
|
||||
}
|
||||
DISPLAYLEVEL(2, "\nThe concatenated output CANNOT regenerate the original directory tree. ")
|
||||
DISPLAYLEVEL(2, "The concatenated output CANNOT regenerate the original directory tree. \n")
|
||||
if (prefs->removeSrcFile) {
|
||||
if (fCtx->hasStdoutOutput) {
|
||||
DISPLAYLEVEL(1, "\nAborting. Use -f if you really want to delete the files and output to stdout");
|
||||
DISPLAYLEVEL(1, "Aborting. Use -f if you really want to delete the files and output to stdout\n");
|
||||
error = 1;
|
||||
} else {
|
||||
error = g_display_prefs.displayLevel > displayLevelCutoff && UTIL_requireUserConfirmation("This is a destructive operation. Proceed? (y/n): ", "Aborting...", "yY", fCtx->hasStdinInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
DISPLAY("\n");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@@ -1332,6 +1345,7 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
|
||||
FILE* const dstFile = ress.dstFile;
|
||||
U64 compressedfilesize = 0;
|
||||
ZSTD_EndDirective directive = ZSTD_e_continue;
|
||||
U64 pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
||||
|
||||
/* stats */
|
||||
ZSTD_frameProgression previous_zfp_update = { 0, 0, 0, 0, 0, 0 };
|
||||
@@ -1348,12 +1362,25 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
|
||||
|
||||
/* init */
|
||||
if (fileSize != UTIL_FILESIZE_UNKNOWN) {
|
||||
pledgedSrcSize = fileSize;
|
||||
CHECK(ZSTD_CCtx_setPledgedSrcSize(ress.cctx, fileSize));
|
||||
} else if (prefs->streamSrcSize > 0) {
|
||||
/* unknown source size; use the declared stream size */
|
||||
pledgedSrcSize = prefs->streamSrcSize;
|
||||
CHECK( ZSTD_CCtx_setPledgedSrcSize(ress.cctx, prefs->streamSrcSize) );
|
||||
}
|
||||
|
||||
{
|
||||
int windowLog;
|
||||
UTIL_HumanReadableSize_t windowSize;
|
||||
CHECK(ZSTD_CCtx_getParameter(ress.cctx, ZSTD_c_windowLog, &windowLog));
|
||||
if (windowLog == 0) {
|
||||
const ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, fileSize, 0);
|
||||
windowLog = cParams.windowLog;
|
||||
}
|
||||
windowSize = UTIL_makeHumanReadableSize(MAX(1ULL, MIN(1ULL << windowLog, pledgedSrcSize)));
|
||||
DISPLAYLEVEL(4, "Decompression will require %.*f%s of memory\n", windowSize.precision, windowSize.value, windowSize.suffix);
|
||||
}
|
||||
(void)srcFileName;
|
||||
|
||||
/* Main compression loop */
|
||||
@@ -1768,6 +1795,50 @@ FIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char* checked_index(const char* options[], size_t length, size_t index) {
|
||||
assert(index < length);
|
||||
// Necessary to avoid warnings since -O3 will omit the above `assert`
|
||||
(void) length;
|
||||
return options[index];
|
||||
}
|
||||
|
||||
#define INDEX(options, index) checked_index((options), sizeof(options) / sizeof(char*), (index))
|
||||
|
||||
void FIO_displayCompressionParameters(const FIO_prefs_t* prefs) {
|
||||
static const char* formatOptions[5] = {ZSTD_EXTENSION, GZ_EXTENSION, XZ_EXTENSION,
|
||||
LZMA_EXTENSION, LZ4_EXTENSION};
|
||||
static const char* sparseOptions[3] = {" --no-sparse", "", " --sparse"};
|
||||
static const char* checkSumOptions[3] = {" --no-check", "", " --check"};
|
||||
static const char* rowMatchFinderOptions[3] = {"", " --no-row-match-finder", " --row-match-finder"};
|
||||
static const char* compressLiteralsOptions[3] = {"", " --compress-literals", " --no-compress-literals"};
|
||||
|
||||
assert(g_display_prefs.displayLevel >= 4);
|
||||
|
||||
DISPLAY("--format=%s", formatOptions[prefs->compressionType]);
|
||||
DISPLAY("%s", INDEX(sparseOptions, prefs->sparseFileSupport));
|
||||
DISPLAY("%s", prefs->dictIDFlag ? "" : " --no-dictID");
|
||||
DISPLAY("%s", INDEX(checkSumOptions, prefs->checksumFlag));
|
||||
DISPLAY(" --block-size=%d", prefs->blockSize);
|
||||
if (prefs->adaptiveMode)
|
||||
DISPLAY(" --adapt=min=%d,max=%d", prefs->minAdaptLevel, prefs->maxAdaptLevel);
|
||||
DISPLAY("%s", INDEX(rowMatchFinderOptions, prefs->useRowMatchFinder));
|
||||
DISPLAY("%s", prefs->rsyncable ? " --rsyncable" : "");
|
||||
if (prefs->streamSrcSize)
|
||||
DISPLAY(" --stream-size=%u", (unsigned) prefs->streamSrcSize);
|
||||
if (prefs->srcSizeHint)
|
||||
DISPLAY(" --size-hint=%d", prefs->srcSizeHint);
|
||||
if (prefs->targetCBlockSize)
|
||||
DISPLAY(" --target-compressed-block-size=%u", (unsigned) prefs->targetCBlockSize);
|
||||
DISPLAY("%s", INDEX(compressLiteralsOptions, prefs->literalCompressionMode));
|
||||
DISPLAY(" --memory=%u", prefs->memLimit ? prefs->memLimit : 128 MB);
|
||||
DISPLAY(" --threads=%d", prefs->nbWorkers);
|
||||
DISPLAY("%s", prefs->excludeCompressedFiles ? " --exclude-compressed" : "");
|
||||
DISPLAY(" --%scontent-size", prefs->contentSize ? "" : "no-");
|
||||
DISPLAY("\n");
|
||||
}
|
||||
|
||||
#undef INDEX
|
||||
|
||||
int FIO_compressFilename(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs, const char* dstFileName,
|
||||
const char* srcFileName, const char* dictFileName,
|
||||
int compressionLevel, ZSTD_compressionParameters comprParams)
|
||||
|
||||
@@ -108,6 +108,7 @@ void FIO_setExcludeCompressedFile(FIO_prefs_t* const prefs, int excludeCompresse
|
||||
void FIO_setAllowBlockDevices(FIO_prefs_t* const prefs, int allowBlockDevices);
|
||||
void FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value);
|
||||
void FIO_setContentSize(FIO_prefs_t* const prefs, int value);
|
||||
void FIO_displayCompressionParameters(const FIO_prefs_t* prefs);
|
||||
|
||||
/* FIO_ctx_t functions */
|
||||
void FIO_setNbFilesTotal(FIO_ctx_t* const fCtx, int value);
|
||||
|
||||
+5
-5
@@ -992,7 +992,7 @@ makeUniqueMirroredDestDirs(char** srcDirNames, unsigned nbFile, const char* outD
|
||||
char* prevDirName = srcDirNames[i - 1];
|
||||
char* currDirName = srcDirNames[i];
|
||||
|
||||
/* note: we alwasy compare trimmed path, i.e.:
|
||||
/* note: we always compare trimmed path, i.e.:
|
||||
* src dir of "./foo" and "/foo" will be both saved into:
|
||||
* "outDirName/foo/" */
|
||||
if (!firstIsParentOrSameDirOfSecond(trimPath(prevDirName),
|
||||
@@ -1000,7 +1000,7 @@ makeUniqueMirroredDestDirs(char** srcDirNames, unsigned nbFile, const char* outD
|
||||
uniqueDirNr++;
|
||||
|
||||
/* we need maintain original src dir name instead of trimmed
|
||||
* dir, so we can retrive the original src dir's mode_t */
|
||||
* dir, so we can retrieve the original src dir's mode_t */
|
||||
uniqueDirNames[uniqueDirNr - 1] = currDirName;
|
||||
}
|
||||
|
||||
@@ -1359,11 +1359,11 @@ int UTIL_countCores(int logical)
|
||||
* see: man 3 sysconf */
|
||||
int UTIL_countCores(int logical)
|
||||
{
|
||||
/* suppress unused parameter warning */
|
||||
(void) logical;
|
||||
|
||||
static int numCores = 0;
|
||||
|
||||
/* suppress unused parameter warning */
|
||||
(void)logical;
|
||||
|
||||
if (numCores != 0) return numCores;
|
||||
|
||||
numCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ extern "C" {
|
||||
# define SET_REALTIME_PRIORITY /* disabled */
|
||||
# endif
|
||||
|
||||
#else /* unknown non-unix operating systen */
|
||||
#else /* unknown non-unix operating system */
|
||||
# define UTIL_sleep(s) /* disabled */
|
||||
# define UTIL_sleepMilli(milli) /* disabled */
|
||||
# define SET_REALTIME_PRIORITY /* disabled */
|
||||
|
||||
+8
-3
@@ -1,4 +1,4 @@
|
||||
.TH "ZSTD" "1" "September 2021" "zstd 1.5.1" "User Commands"
|
||||
.TH "ZSTD" "1" "December 2021" "zstd 1.5.1" "User Commands"
|
||||
.SH "NAME"
|
||||
\fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files
|
||||
.SH "SYNOPSIS"
|
||||
@@ -91,7 +91,7 @@ Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \
|
||||
.IP
|
||||
Note: cannot use both this and \-D together Note: \fB\-\-long\fR mode will be automatically activated if chainLog < fileLog (fileLog being the windowLog required to cover the whole file)\. You can also manually force it\. Node: for all levels, you can use \-\-patch\-from in \-\-single\-thread mode to improve compression ratio at the cost of speed 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
|
||||
\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 the faster compression levels will see a small compression speed hit\. 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 milage may vary\.
|
||||
\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 the faster compression levels will see a small compression speed hit\. 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
|
||||
\fB\-C\fR, \fB\-\-[no\-]check\fR: add integrity check computed from uncompressed data (default: enabled)
|
||||
.IP "\[ci]" 4
|
||||
@@ -102,6 +102,8 @@ Note: cannot use both this and \-D together Note: \fB\-\-long\fR mode will be au
|
||||
\fB\-M#\fR, \fB\-\-memory=#\fR: Set a memory usage limit\. By default, Zstandard uses 128 MB 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 (ie\. you can increase or decrease it)\.
|
||||
.IP
|
||||
This is also used during compression when using with \-\-patch\-from=\. In this case, this parameter overrides that maximum size allowed for a dictionary\. (128 MB)\.
|
||||
.IP
|
||||
Additionally, this can be used to limit memory for dictionary training\. This parameter overrides the default limit of 2 GB\. zstd will load training samples up to the memory limit and ignore the rest\.
|
||||
.IP "\[ci]" 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
|
||||
@@ -111,7 +113,7 @@ This is also used during compression when using with \-\-patch\-from=\. In this
|
||||
.IP "\[ci]" 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\.
|
||||
.IP "\[ci]" 4
|
||||
\fB\-c\fR, \fB\-\-stdout\fR: force write to standard output, even if it is the console
|
||||
\fB\-c\fR, \fB\-\-stdout\fR: write to standard output (even if it is the console)
|
||||
.IP "\[ci]" 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
|
||||
@@ -173,6 +175,9 @@ Use \fB#\fR compression level during training (optional)\. Will generate statist
|
||||
\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)\. See above for details\.
|
||||
.TP
|
||||
\fB\-\-dictID=#\fR
|
||||
A dictionary ID is a locally unique ID that a decoder can use to verify it is using the right dictionary\. By default, zstd will create a 4\-bytes random number ID\. It\'s possible to give a precise number instead\. 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\. However, it\'s up to the dictionary manager to not assign twice the same ID to 2 different dictionaries\.
|
||||
.TP
|
||||
|
||||
+8
-2
@@ -171,7 +171,7 @@ the last one takes effect.
|
||||
compression speed hit.
|
||||
This feature does not work with `--single-thread`. You probably don't want
|
||||
to use it with long range mode, since it will decrease the effectiveness of
|
||||
the synchronization points, but your milage may vary.
|
||||
the synchronization points, but your mileage may vary.
|
||||
* `-C`, `--[no-]check`:
|
||||
add integrity check computed from uncompressed data (default: enabled)
|
||||
* `--[no-]content-size`:
|
||||
@@ -190,6 +190,10 @@ the last one takes effect.
|
||||
|
||||
This is also used during compression when using with --patch-from=. In this case,
|
||||
this parameter overrides that maximum size allowed for a dictionary. (128 MB).
|
||||
|
||||
Additionally, this can be used to limit memory for dictionary training. This parameter
|
||||
overrides the default limit of 2 GB. zstd will load training samples up to the memory limit
|
||||
and ignore the rest.
|
||||
* `--stream-size=#` :
|
||||
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.
|
||||
@@ -208,7 +212,7 @@ the last one takes effect.
|
||||
disable input and output checks. Allows overwriting existing files, input
|
||||
from console, output to stdout, operating on links, block devices, etc.
|
||||
* `-c`, `--stdout`:
|
||||
force write to standard output, even if it is the console
|
||||
write to standard output (even if it is the console)
|
||||
* `--[no-]sparse`:
|
||||
enable / disable sparse FS support,
|
||||
to make files with many zeroes smaller on disk.
|
||||
@@ -329,6 +333,8 @@ Compression of small files similar to the sample set will be greatly improved.
|
||||
resulting in a _small_ compression ratio improvement for this level.
|
||||
* `-B#`:
|
||||
Split input files into blocks of size # (default: no split)
|
||||
* `-M#`, `--memory=#`:
|
||||
Limit the amount of sample data loaded for training (default: 2 GB). See above for details.
|
||||
* `--dictID=#`:
|
||||
A dictionary ID is a locally unique ID
|
||||
that a decoder can use to verify it is using the right dictionary.
|
||||
|
||||
+54
-24
@@ -163,7 +163,7 @@ static void usage_advanced(const char* programName)
|
||||
DISPLAYOUT( "Advanced arguments : \n");
|
||||
DISPLAYOUT( " -V : display Version number and exit \n");
|
||||
|
||||
DISPLAYOUT( " -c : force write to standard output, even if it is the console \n");
|
||||
DISPLAYOUT( " -c : write to standard output (even if it is the console) \n");
|
||||
|
||||
DISPLAYOUT( " -v : verbose mode; specify multiple times to increase verbosity \n");
|
||||
DISPLAYOUT( " -q : suppress warnings; specify twice to suppress errors too \n");
|
||||
@@ -647,6 +647,48 @@ static void printVersion(void)
|
||||
} }
|
||||
}
|
||||
|
||||
#define ZSTD_NB_STRATEGIES 9
|
||||
static const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { "", "ZSTD_fast",
|
||||
"ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2",
|
||||
"ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"};
|
||||
|
||||
#ifndef ZSTD_NOCOMPRESS
|
||||
|
||||
static void printDefaultCParams(const char* filename, const char* dictFileName, int cLevel) {
|
||||
unsigned long long fileSize = UTIL_getFileSize(filename);
|
||||
const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0;
|
||||
const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize);
|
||||
if (fileSize != UTIL_FILESIZE_UNKNOWN) DISPLAY("%s (%u bytes)\n", filename, (unsigned)fileSize);
|
||||
else DISPLAY("%s (src size unknown)\n", filename);
|
||||
DISPLAY(" - windowLog : %u\n", cParams.windowLog);
|
||||
DISPLAY(" - chainLog : %u\n", cParams.chainLog);
|
||||
DISPLAY(" - hashLog : %u\n", cParams.hashLog);
|
||||
DISPLAY(" - searchLog : %u\n", cParams.searchLog);
|
||||
DISPLAY(" - minMatch : %u\n", cParams.minMatch);
|
||||
DISPLAY(" - targetLength : %u\n", cParams.targetLength);
|
||||
assert(cParams.strategy < ZSTD_NB_STRATEGIES + 1);
|
||||
DISPLAY(" - strategy : %s (%u)\n", ZSTD_strategyMap[(int)cParams.strategy], (unsigned)cParams.strategy);
|
||||
}
|
||||
|
||||
static void printActualCParams(const char* filename, const char* dictFileName, int cLevel, const ZSTD_compressionParameters* cParams) {
|
||||
unsigned long long fileSize = UTIL_getFileSize(filename);
|
||||
const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0;
|
||||
ZSTD_compressionParameters actualCParams = ZSTD_getCParams(cLevel, fileSize, dictSize);
|
||||
assert(g_displayLevel >= 4);
|
||||
actualCParams.windowLog = cParams->windowLog == 0 ? actualCParams.windowLog : cParams->windowLog;
|
||||
actualCParams.chainLog = cParams->chainLog == 0 ? actualCParams.chainLog : cParams->chainLog;
|
||||
actualCParams.hashLog = cParams->hashLog == 0 ? actualCParams.hashLog : cParams->hashLog;
|
||||
actualCParams.searchLog = cParams->searchLog == 0 ? actualCParams.searchLog : cParams->searchLog;
|
||||
actualCParams.minMatch = cParams->minMatch == 0 ? actualCParams.minMatch : cParams->minMatch;
|
||||
actualCParams.targetLength = cParams->targetLength == 0 ? actualCParams.targetLength : cParams->targetLength;
|
||||
actualCParams.strategy = cParams->strategy == 0 ? actualCParams.strategy : cParams->strategy;
|
||||
DISPLAY("--zstd=wlog=%d,clog=%d,hlog=%d,slog=%d,mml=%d,tlen=%d,strat=%d\n",
|
||||
actualCParams.windowLog, actualCParams.chainLog, actualCParams.hashLog, actualCParams.searchLog,
|
||||
actualCParams.minMatch, actualCParams.targetLength, actualCParams.strategy);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Environment variables for parameter setting */
|
||||
#define ENV_CLEVEL "ZSTD_CLEVEL"
|
||||
#define ENV_NBTHREADS "ZSTD_NBTHREADS" /* takes lower precedence than directly specifying -T# in the CLI */
|
||||
@@ -723,11 +765,6 @@ static unsigned init_nbThreads(void) {
|
||||
val32 = readU32FromChar(&__nb); \
|
||||
}
|
||||
|
||||
#define ZSTD_NB_STRATEGIES 9
|
||||
static const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { "", "ZSTD_fast",
|
||||
"ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2",
|
||||
"ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"};
|
||||
|
||||
typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train, zom_list } zstd_operation_mode;
|
||||
|
||||
#define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
|
||||
@@ -1290,18 +1327,18 @@ int main(int argCount, const char* argv[])
|
||||
int const optimize = !coverParams.k || !coverParams.d;
|
||||
coverParams.nbThreads = (unsigned)nbWorkers;
|
||||
coverParams.zParams = zParams;
|
||||
operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (unsigned)filenames->tableSize, blockSize, NULL, &coverParams, NULL, optimize);
|
||||
operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, blockSize, NULL, &coverParams, NULL, optimize, memLimit);
|
||||
} else if (dict == fastCover) {
|
||||
int const optimize = !fastCoverParams.k || !fastCoverParams.d;
|
||||
fastCoverParams.nbThreads = (unsigned)nbWorkers;
|
||||
fastCoverParams.zParams = zParams;
|
||||
operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (unsigned)filenames->tableSize, blockSize, NULL, NULL, &fastCoverParams, optimize);
|
||||
operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, blockSize, NULL, NULL, &fastCoverParams, optimize, memLimit);
|
||||
} else {
|
||||
ZDICT_legacy_params_t dictParams;
|
||||
memset(&dictParams, 0, sizeof(dictParams));
|
||||
dictParams.selectivityLevel = dictSelect;
|
||||
dictParams.zParams = zParams;
|
||||
operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (unsigned)filenames->tableSize, blockSize, &dictParams, NULL, NULL, 0);
|
||||
operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, blockSize, &dictParams, NULL, NULL, 0, memLimit);
|
||||
}
|
||||
#else
|
||||
(void)dictCLevel; (void)dictSelect; (void)dictID; (void)maxDictSize; /* not used when ZSTD_NODICT set */
|
||||
@@ -1365,7 +1402,7 @@ int main(int argCount, const char* argv[])
|
||||
/* No status message in pipe mode (stdin - stdout) */
|
||||
hasStdout = outFileName && !strcmp(outFileName,stdoutmark);
|
||||
|
||||
if (hasStdout && (g_displayLevel==2)) g_displayLevel=1;
|
||||
if ((hasStdout || !IS_CONSOLE(stderr)) && (g_displayLevel==2)) g_displayLevel=1;
|
||||
|
||||
/* IO Stream/File */
|
||||
FIO_setHasStdoutOutput(fCtx, hasStdout);
|
||||
@@ -1411,25 +1448,18 @@ int main(int argCount, const char* argv[])
|
||||
assert(ZSTD_NB_STRATEGIES == strategyBounds.upperBound);
|
||||
(void)strategyBounds; }
|
||||
|
||||
if (showDefaultCParams) {
|
||||
if (showDefaultCParams || g_displayLevel >= 4) {
|
||||
size_t fileNb;
|
||||
for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) {
|
||||
unsigned long long fileSize = UTIL_getFileSize(filenames->fileNames[fileNb]);
|
||||
const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0;
|
||||
const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize);
|
||||
if (fileSize != UTIL_FILESIZE_UNKNOWN) DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], (unsigned)fileSize);
|
||||
else DISPLAY("%s (src size unknown)\n", filenames->fileNames[fileNb]);
|
||||
DISPLAY(" - windowLog : %u\n", cParams.windowLog);
|
||||
DISPLAY(" - chainLog : %u\n", cParams.chainLog);
|
||||
DISPLAY(" - hashLog : %u\n", cParams.hashLog);
|
||||
DISPLAY(" - searchLog : %u\n", cParams.searchLog);
|
||||
DISPLAY(" - minMatch : %u\n", cParams.minMatch);
|
||||
DISPLAY(" - targetLength : %u\n", cParams.targetLength);
|
||||
assert(cParams.strategy < ZSTD_NB_STRATEGIES + 1);
|
||||
DISPLAY(" - strategy : %s (%u)\n", ZSTD_strategyMap[(int)cParams.strategy], (unsigned)cParams.strategy);
|
||||
if (showDefaultCParams)
|
||||
printDefaultCParams(filenames->fileNames[fileNb], dictFileName, cLevel);
|
||||
if (g_displayLevel >= 4)
|
||||
printActualCParams(filenames->fileNames[fileNb], dictFileName, cLevel, &compressionParams);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_displayLevel >= 4)
|
||||
FIO_displayCompressionParameters(prefs);
|
||||
if ((filenames->tableSize==1) && outFileName)
|
||||
operationResult = FIO_compressFilename(fCtx, prefs, outFileName, filenames->fileNames[0], dictFileName, cLevel, compressionParams);
|
||||
else
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
.TH "ZSTDGREP" "1" "September 2021" "zstd 1.5.1" "User Commands"
|
||||
.TH "ZSTDGREP" "1" "December 2021" "zstd 1.5.1" "User Commands"
|
||||
.SH "NAME"
|
||||
\fBzstdgrep\fR \- print lines matching a pattern in zstandard\-compressed files
|
||||
.SH "SYNOPSIS"
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
.TH "ZSTDLESS" "1" "September 2021" "zstd 1.5.1" "User Commands"
|
||||
.TH "ZSTDLESS" "1" "December 2021" "zstd 1.5.1" "User Commands"
|
||||
.SH "NAME"
|
||||
\fBzstdless\fR \- view zstandard\-compressed files
|
||||
.SH "SYNOPSIS"
|
||||
|
||||
+3
-4
@@ -45,7 +45,7 @@ ZSTDDECOMP_FILES := $(sort $(ZSTD_DECOMPRESS_FILES))
|
||||
ZSTD_FILES := $(ZSTDDECOMP_FILES) $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES)
|
||||
ZDICT_FILES := $(sort $(ZSTD_DICTBUILDER_FILES))
|
||||
|
||||
ZSTD_F1 := $(wildcard $(ZSTD_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))
|
||||
@@ -206,7 +206,7 @@ bigdict: $(ZSTDMT_OBJECTS) $(PRGDIR)/datagen.c bigdict.c
|
||||
invalidDictionaries : $(ZSTD_OBJECTS) invalidDictionaries.c
|
||||
|
||||
legacy : CPPFLAGS += -I$(ZSTDDIR)/legacy -UZSTD_LEGACY_SUPPORT -DZSTD_LEGACY_SUPPORT=4
|
||||
legacy : $(ZSTD_FILES) $(wildcard $(ZSTDDIR)/legacy/*.c) legacy.c
|
||||
legacy : $(ZSTD_FILES) $(sort $(wildcard $(ZSTDDIR)/legacy/*.c)) legacy.c
|
||||
|
||||
decodecorpus : LDLIBS += -lm
|
||||
decodecorpus : $(filter-out zstdc_zstd_compress.o, $(ZSTD_OBJECTS)) $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c decodecorpus.c
|
||||
@@ -248,7 +248,7 @@ clean:
|
||||
# valgrind tests are validated only for some posix platforms
|
||||
#----------------------------------------------------------------------------------
|
||||
UNAME := $(shell uname)
|
||||
ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS))
|
||||
ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS AIX))
|
||||
HOST_OS = POSIX
|
||||
|
||||
valgrindTest: VALGRIND = valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1
|
||||
@@ -267,7 +267,6 @@ valgrindTest: zstd datagen fuzzer fullbench
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ifneq (,$(filter MINGW% MSYS%,$(UNAME)))
|
||||
HOST_OS = MSYS
|
||||
endif
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ optional arguments:
|
||||
--mode MODE 'fastmode', 'onetime', 'current', or 'continuous' (see
|
||||
README.md for details)
|
||||
--dict DICT filename of dictionary to use (when set, this
|
||||
dictioanry will be used to compress the files provided
|
||||
dictionary will be used to compress the files provided
|
||||
inside --directory)
|
||||
```
|
||||
|
||||
|
||||
@@ -296,7 +296,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument("--emails", help="email addresses of people who will be alerted upon regression. Only for continuous mode", default=None)
|
||||
parser.add_argument("--frequency", help="specifies the number of seconds to wait before each successive check for new PRs in continuous mode", default=DEFAULT_MAX_API_CALL_FREQUENCY_SEC)
|
||||
parser.add_argument("--mode", help="'fastmode', 'onetime', 'current', or 'continuous' (see README.md for details)", default="current")
|
||||
parser.add_argument("--dict", help="filename of dictionary to use (when set, this dictioanry will be used to compress the files provided inside --directory)", default=None)
|
||||
parser.add_argument("--dict", help="filename of dictionary to use (when set, this dictionary will be used to compress the files provided inside --directory)", default=None)
|
||||
|
||||
args = parser.parse_args()
|
||||
filenames = args.directory
|
||||
|
||||
+21
-24
@@ -633,17 +633,16 @@ static inline void initSeqStore(seqStore_t *seqStore) {
|
||||
}
|
||||
|
||||
/* Randomly generate sequence commands */
|
||||
static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
|
||||
size_t contentSize, size_t literalsSize, dictInfo info)
|
||||
static U32
|
||||
generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
|
||||
size_t contentSize, size_t literalsSize, dictInfo info)
|
||||
{
|
||||
/* The total length of all the matches */
|
||||
size_t const remainingMatch = contentSize - literalsSize;
|
||||
size_t excessMatch = 0;
|
||||
U32 numSequences = 0;
|
||||
|
||||
U32 i;
|
||||
|
||||
|
||||
const BYTE* literals = LITERAL_BUFFER;
|
||||
BYTE* srcPtr = frame->src;
|
||||
|
||||
@@ -703,32 +702,31 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
|
||||
lenPastStart = MIN(lenPastStart+MIN_SEQ_LEN, (U32)info.dictContentSize);
|
||||
offset = (U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart) + lenPastStart;
|
||||
}
|
||||
{
|
||||
U32 const matchLenBound = MIN(frame->header.windowSize, lenPastStart);
|
||||
{ U32 const matchLenBound = MIN(frame->header.windowSize, lenPastStart);
|
||||
matchLen = MIN(matchLen, matchLenBound);
|
||||
}
|
||||
}
|
||||
}
|
||||
offsetCode = offset + ZSTD_REP_MOVE;
|
||||
offsetCode = STORE_OFFSET(offset);
|
||||
repIndex = 2;
|
||||
} else {
|
||||
/* do a repeat offset */
|
||||
offsetCode = RAND(seed) % 3;
|
||||
U32 const randomRepIndex = RAND(seed) % 3;
|
||||
offsetCode = STORE_REPCODE(randomRepIndex + 1); /* expects values between 1 & 3 */
|
||||
if (literalLen > 0) {
|
||||
offset = frame->stats.rep[offsetCode];
|
||||
repIndex = offsetCode;
|
||||
offset = frame->stats.rep[randomRepIndex];
|
||||
repIndex = randomRepIndex;
|
||||
} else {
|
||||
/* special case */
|
||||
offset = offsetCode == 2 ? frame->stats.rep[0] - 1
|
||||
: frame->stats.rep[offsetCode + 1];
|
||||
repIndex = MIN(2, offsetCode + 1);
|
||||
/* special case : literalLen == 0 */
|
||||
offset = randomRepIndex == 2 ? frame->stats.rep[0] - 1
|
||||
: frame->stats.rep[randomRepIndex + 1];
|
||||
repIndex = MIN(2, randomRepIndex + 1);
|
||||
}
|
||||
}
|
||||
} while (((!info.useDict) && (offset > (size_t)((BYTE*)srcPtr - (BYTE*)frame->srcStart))) || offset == 0);
|
||||
|
||||
{
|
||||
{ BYTE* const dictEnd = info.dictContent + info.dictContentSize;
|
||||
size_t j;
|
||||
BYTE* const dictEnd = info.dictContent + info.dictContentSize;
|
||||
for (j = 0; j < matchLen; j++) {
|
||||
if ((U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart) < offset) {
|
||||
/* copy from dictionary instead of literals */
|
||||
@@ -739,8 +737,7 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
|
||||
*srcPtr = *(srcPtr-offset);
|
||||
}
|
||||
srcPtr++;
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
{ int r;
|
||||
for (r = repIndex; r > 0; r--) {
|
||||
@@ -754,12 +751,12 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
|
||||
DISPLAYLEVEL(7, " srcPos: %8u seqNb: %3u",
|
||||
(unsigned)((BYTE*)srcPtr - (BYTE*)frame->srcStart), (unsigned)i);
|
||||
DISPLAYLEVEL(6, "\n");
|
||||
if (offsetCode < 3) {
|
||||
if (STORED_IS_REPCODE(offsetCode)) { /* expects sumtype numeric representation of ZSTD_storeSeq() */
|
||||
DISPLAYLEVEL(7, " repeat offset: %d\n", (int)repIndex);
|
||||
}
|
||||
/* use libzstd sequence handling */
|
||||
ZSTD_storeSeq(seqStore, literalLen, literals, literals + literalLen,
|
||||
offsetCode, matchLen - MINMATCH);
|
||||
offsetCode, matchLen);
|
||||
|
||||
literalsSize -= literalLen;
|
||||
excessMatch -= (matchLen - MIN_SEQ_LEN);
|
||||
@@ -949,9 +946,9 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr,
|
||||
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].mlBase, ML_bits[mlCodeTable[nbSeq-1]]);
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
|
||||
BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, ofCodeTable[nbSeq-1]);
|
||||
BIT_flushBits(&blockStream);
|
||||
|
||||
{ size_t n;
|
||||
@@ -971,9 +968,9 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr,
|
||||
BIT_flushBits(&blockStream); /* (7)*/
|
||||
BIT_addBits(&blockStream, sequences[n].litLength, llBits);
|
||||
if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
|
||||
BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
|
||||
BIT_addBits(&blockStream, sequences[n].mlBase, mlBits);
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
|
||||
BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
|
||||
BIT_addBits(&blockStream, sequences[n].offBase, ofBits); /* 31 */
|
||||
BIT_flushBits(&blockStream); /* (7)*/
|
||||
} }
|
||||
|
||||
|
||||
+40
-12
@@ -108,7 +108,25 @@ local_ZSTD_compress(const void* src, size_t srcSize,
|
||||
p.fParams = f;
|
||||
p.cParams = *(ZSTD_compressionParameters*)payload;
|
||||
return ZSTD_compress_advanced (g_zcc, dst, dstSize, src, srcSize, NULL ,0, p);
|
||||
//return ZSTD_compress(dst, dstSize, src, srcSize, cLevel);
|
||||
}
|
||||
|
||||
static size_t
|
||||
local_ZSTD_compress_freshCCtx(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstSize,
|
||||
void* payload)
|
||||
{
|
||||
ZSTD_parameters p;
|
||||
ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 };
|
||||
p.fParams = f;
|
||||
p.cParams = *(ZSTD_compressionParameters*)payload;
|
||||
if (g_zcc != NULL) ZSTD_freeCCtx(g_zcc);
|
||||
g_zcc = ZSTD_createCCtx();
|
||||
assert(g_zcc != NULL);
|
||||
{ size_t const r = ZSTD_compress_advanced (g_zcc, dst, dstSize, src, srcSize, NULL ,0, p);
|
||||
ZSTD_freeCCtx(g_zcc);
|
||||
g_zcc = NULL;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t g_cSize = 0;
|
||||
@@ -123,11 +141,15 @@ static size_t local_ZSTD_decompress(const void* src, size_t srcSize,
|
||||
static ZSTD_DCtx* g_zdc = NULL;
|
||||
|
||||
#ifndef ZSTD_DLL_IMPORT
|
||||
extern size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* ctx, const void* src, size_t srcSize);
|
||||
typedef enum {
|
||||
not_streaming = 0,
|
||||
is_streaming = 1
|
||||
} streaming_operation;
|
||||
extern size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* ctx, const void* src, size_t srcSize, void* dst, size_t dstCapacity, const streaming_operation streaming);
|
||||
static size_t local_ZSTD_decodeLiteralsBlock(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2)
|
||||
{
|
||||
(void)src; (void)srcSize; (void)dst; (void)dstSize;
|
||||
return ZSTD_decodeLiteralsBlock(g_zdc, buff2, g_cSize);
|
||||
return ZSTD_decodeLiteralsBlock(g_zdc, buff2, g_cSize, dst, dstSize, not_streaming);
|
||||
}
|
||||
|
||||
static size_t local_ZSTD_decodeSeqHeaders(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2)
|
||||
@@ -226,14 +248,15 @@ local_ZSTD_compressStream_freshCCtx(const void* src, size_t srcSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* payload)
|
||||
{
|
||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
size_t r;
|
||||
assert(cctx != NULL);
|
||||
if (g_cstream != NULL) ZSTD_freeCCtx(g_cstream);
|
||||
g_cstream = ZSTD_createCCtx();
|
||||
assert(g_cstream != NULL);
|
||||
|
||||
r = local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, payload);
|
||||
|
||||
ZSTD_freeCCtx(cctx);
|
||||
return r;
|
||||
{ size_t const r = local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, payload);
|
||||
ZSTD_freeCCtx(g_cstream);
|
||||
g_cstream = NULL;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
@@ -426,6 +449,9 @@ static int benchMem(unsigned benchNb,
|
||||
case 2:
|
||||
benchFunction = local_ZSTD_decompress; benchName = "decompress";
|
||||
break;
|
||||
case 3:
|
||||
benchFunction = local_ZSTD_compress_freshCCtx; benchName = "compress_freshCCtx";
|
||||
break;
|
||||
#ifndef ZSTD_DLL_IMPORT
|
||||
case 11:
|
||||
benchFunction = local_ZSTD_compressContinue; benchName = "compressContinue";
|
||||
@@ -504,7 +530,6 @@ static int benchMem(unsigned benchNb,
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_targetLength, (int)cparams.targetLength);
|
||||
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_strategy, cparams.strategy);
|
||||
|
||||
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_compressionLevel, cLevel);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_windowLog, (int)cparams.windowLog);
|
||||
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_hashLog, (int)cparams.hashLog);
|
||||
@@ -523,6 +548,9 @@ static int benchMem(unsigned benchNb,
|
||||
case 2:
|
||||
g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel);
|
||||
break;
|
||||
case 3:
|
||||
payload = &cparams;
|
||||
break;
|
||||
#ifndef ZSTD_DLL_IMPORT
|
||||
case 11:
|
||||
payload = &cparams;
|
||||
@@ -577,7 +605,7 @@ static int benchMem(unsigned benchNb,
|
||||
ip += ZSTD_blockHeaderSize; /* skip block header */
|
||||
ZSTD_decompressBegin(g_zdc);
|
||||
CONTROL(iend > ip);
|
||||
ip += ZSTD_decodeLiteralsBlock(g_zdc, ip, (size_t)(iend-ip)); /* skip literal segment */
|
||||
ip += ZSTD_decodeLiteralsBlock(g_zdc, ip, (size_t)(iend-ip), dstBuff, dstBuffSize, not_streaming); /* skip literal segment */
|
||||
g_cSize = (size_t)(iend-ip);
|
||||
memcpy(dstBuff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */
|
||||
srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */
|
||||
|
||||
@@ -17,6 +17,7 @@ decompress_dstSize_tooSmall
|
||||
fse_read_ncount
|
||||
sequence_compression_api
|
||||
seekable_roundtrip
|
||||
huf_decompress
|
||||
huf_round_trip
|
||||
fuzz-*.log
|
||||
rt_lib_*
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ FUZZ_SRC := \
|
||||
$(ZSTDCOMP_SRC) \
|
||||
$(ZSTDDICT_SRC) \
|
||||
$(ZSTDLEGACY_SRC)
|
||||
FUZZ_SRC := $(wildcard $(FUZZ_SRC))
|
||||
FUZZ_SRC := $(sort $(wildcard $(FUZZ_SRC)))
|
||||
|
||||
FUZZ_D_OBJ1 := $(subst $(ZSTDDIR)/common/,d_lib_common_,$(FUZZ_SRC))
|
||||
FUZZ_D_OBJ2 := $(subst $(ZSTDDIR)/compress/,d_lib_compress_,$(FUZZ_D_OBJ1))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user