commit
83b51e9f88
16
.cirrus.yml
Normal file
16
.cirrus.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
env:
|
||||||
|
CIRRUS_CLONE_DEPTH: 1
|
||||||
|
ARCH: amd64
|
||||||
|
|
||||||
|
task:
|
||||||
|
freebsd_instance:
|
||||||
|
matrix:
|
||||||
|
image: freebsd-12-0-release-amd64
|
||||||
|
image: freebsd-11-2-release-amd64
|
||||||
|
install_script:
|
||||||
|
- sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf
|
||||||
|
- pkg upgrade -y
|
||||||
|
- pkg install -y gmake coreutils
|
||||||
|
script: |
|
||||||
|
MOREFLAGS="-Werror" gmake -j all
|
||||||
|
gmake shortest
|
14
.travis.yml
14
.travis.yml
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
language: c
|
language: c
|
||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: required
|
|
||||||
|
|
||||||
git:
|
git:
|
||||||
depth: 1
|
depth: 1
|
||||||
@ -179,14 +178,17 @@ matrix:
|
|||||||
|
|
||||||
# meson dedicated test
|
# meson dedicated test
|
||||||
- name: Xenial (Meson + clang)
|
- name: Xenial (Meson + clang)
|
||||||
|
# env: ALLOW_FAILURES=true
|
||||||
dist: xenial
|
dist: xenial
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
before_install:
|
install:
|
||||||
- sudo apt-get install -qq liblz4-dev valgrind tree
|
- sudo apt-get install -qq liblz4-dev valgrind tree
|
||||||
- curl -o ~/get-pip.py 'https://bootstrap.pypa.io/get-pip.py'
|
- travis_retry curl -o ~/ninja.zip -L 'https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip'
|
||||||
- python3 ~/get-pip.py --user
|
&& unzip ~/ninja.zip -d ~/.local/bin
|
||||||
- pip3 install --user meson ninja
|
- travis_retry curl -o ~/get-pip.py -L 'https://bootstrap.pypa.io/get-pip.py'
|
||||||
|
&& python3 ~/get-pip.py --user
|
||||||
|
&& pip3 install --user meson
|
||||||
script:
|
script:
|
||||||
- meson --buildtype=debug
|
- meson --buildtype=debug
|
||||||
-Db_lundef=false
|
-Db_lundef=false
|
||||||
@ -198,4 +200,4 @@ matrix:
|
|||||||
- DESTDIR=./staging ninja install
|
- DESTDIR=./staging ninja install
|
||||||
- tree ./staging
|
- tree ./staging
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- name: Xenial (Meson + clang)
|
- env: ALLOW_FAILURES=true
|
||||||
|
39
CHANGELOG
39
CHANGELOG
@ -1,3 +1,40 @@
|
|||||||
|
v1.4.0
|
||||||
|
perf: Improve level 1 compression speed in most scenarios by 6% by @gbtucker and @terrelln
|
||||||
|
api: Move the advanced API, including all functions in the staging section, to the stable section
|
||||||
|
api: Make ZSTD_e_flush and ZSTD_e_end block for maximum forward progress
|
||||||
|
api: Rename ZSTD_CCtxParam_getParameter to ZSTD_CCtxParams_getParameter
|
||||||
|
api: Rename ZSTD_CCtxParam_setParameter to ZSTD_CCtxParams_setParameter
|
||||||
|
api: Don't export ZSTDMT functions from the shared library by default
|
||||||
|
api: Require ZSTD_MULTITHREAD to be defined to use ZSTDMT
|
||||||
|
api: Add ZSTD_decompressBound() to provide an upper bound on decompressed size by @shakeelrao
|
||||||
|
api: Fix ZSTD_decompressDCtx() corner cases with a dictionary
|
||||||
|
api: Move ZSTD_getDictID_*() functions to the stable section
|
||||||
|
api: Add ZSTD_c_literalCompressionMode flag to enable or disable literal compression by @terrelln
|
||||||
|
api: Allow compression parameters to be set when a dictionary is used
|
||||||
|
api: Allow setting parameters before or after ZSTD_CCtx_loadDictionary() is called
|
||||||
|
api: Fix ZSTD_estimateCStreamSize_usingCCtxParams()
|
||||||
|
api: Setting ZSTD_d_maxWindowLog to 0 means use the default
|
||||||
|
cli: Ensure that a dictionary is not used to compress itself by @shakeelrao
|
||||||
|
cli: Add --[no-]compress-literals flag to enable or disable literal compression
|
||||||
|
doc: Update the examples to use the advanced API
|
||||||
|
doc: Explain how to transition from old streaming functions to the advanced API in the header
|
||||||
|
build: Improve the Windows release packages
|
||||||
|
build: Improve CMake build by @hjmjohnson
|
||||||
|
build: Build fixes for FreeBSD by @lwhsu
|
||||||
|
build: Remove redundant warnings by @thatsafunnyname
|
||||||
|
build: Fix tests on OpenBSD by @bket
|
||||||
|
build: Extend fuzzer build system to work with the new clang engine
|
||||||
|
build: CMake now creates the libzstd.so.1 symlink
|
||||||
|
build: Improve Menson build by @lzutao
|
||||||
|
misc: Fix symbolic link detection on FreeBSD
|
||||||
|
misc: Use physical core count for -T0 on FreeBSD by @cemeyer
|
||||||
|
misc: Fix zstd --list on truncated files by @kostmo
|
||||||
|
misc: Improve logging in debug mode by @felixhandte
|
||||||
|
misc: Add CirrusCI tests by @lwhsu
|
||||||
|
misc: Optimize dictionary memory usage in corner cases
|
||||||
|
misc: Improve the dictionary builder on small or homogeneous data
|
||||||
|
misc: Fix spelling across the repo by @jsoref
|
||||||
|
|
||||||
v1.3.8
|
v1.3.8
|
||||||
perf: better decompression speed on large files (+7%) and cold dictionaries (+15%)
|
perf: better decompression speed on large files (+7%) and cold dictionaries (+15%)
|
||||||
perf: slightly better compression ratio at high compression modes
|
perf: slightly better compression ratio at high compression modes
|
||||||
@ -239,7 +276,7 @@ v1.0.0
|
|||||||
Change Licensing, all project is now BSD, Copyright Facebook
|
Change Licensing, all project is now BSD, Copyright Facebook
|
||||||
Small decompression speed improvement
|
Small decompression speed improvement
|
||||||
API : Streaming API supports legacy format
|
API : Streaming API supports legacy format
|
||||||
API : ZDICT_getDictID(), ZSTD_sizeof_{CCtx, DCtx, CStream, DStream}(), ZSTD_setDStreamParamter()
|
API : ZDICT_getDictID(), ZSTD_sizeof_{CCtx, DCtx, CStream, DStream}(), ZSTD_setDStreamParameter()
|
||||||
CLI supports legacy formats v0.4+
|
CLI supports legacy formats v0.4+
|
||||||
Fixed : compression fails on certain huge files, reported by Jesse McGrew
|
Fixed : compression fails on certain huge files, reported by Jesse McGrew
|
||||||
Enhanced documentation, by Przemyslaw Skibinski
|
Enhanced documentation, by Przemyslaw Skibinski
|
||||||
|
8
Makefile
8
Makefile
@ -156,7 +156,7 @@ list:
|
|||||||
done \
|
done \
|
||||||
} | column -t -s $$'\t'
|
} | column -t -s $$'\t'
|
||||||
|
|
||||||
.PHONY: install clangtest armtest usan asan uasan
|
.PHONY: install armtest usan asan uasan
|
||||||
install:
|
install:
|
||||||
@$(MAKE) -C $(ZSTDDIR) $@
|
@$(MAKE) -C $(ZSTDDIR) $@
|
||||||
@$(MAKE) -C $(PRGDIR) $@
|
@$(MAKE) -C $(PRGDIR) $@
|
||||||
@ -188,7 +188,7 @@ gcc7build: clean
|
|||||||
.PHONY: clangbuild
|
.PHONY: clangbuild
|
||||||
clangbuild: clean
|
clangbuild: clean
|
||||||
clang -v
|
clang -v
|
||||||
CXX=clang++ CC=clang $(MAKE) all MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation"
|
CXX=clang++ CC=clang CFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation" $(MAKE) all
|
||||||
|
|
||||||
m32build: clean
|
m32build: clean
|
||||||
gcc -v
|
gcc -v
|
||||||
@ -232,10 +232,6 @@ gcc6test: clean
|
|||||||
gcc-6 -v
|
gcc-6 -v
|
||||||
$(MAKE) all CC=gcc-6 MOREFLAGS="-Werror"
|
$(MAKE) all CC=gcc-6 MOREFLAGS="-Werror"
|
||||||
|
|
||||||
clangtest: clean
|
|
||||||
clang -v
|
|
||||||
$(MAKE) all CXX=clang++ CC=clang MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation"
|
|
||||||
|
|
||||||
armtest: clean
|
armtest: clean
|
||||||
$(MAKE) -C $(TESTDIR) datagen # use native, faster
|
$(MAKE) -C $(TESTDIR) datagen # use native, faster
|
||||||
$(MAKE) -C $(TESTDIR) test CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS="-Werror -static" FUZZER_FLAGS=--no-big-tests
|
$(MAKE) -C $(TESTDIR) test CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS="-Werror -static" FUZZER_FLAGS=--no-big-tests
|
||||||
|
25
README.md
25
README.md
@ -14,6 +14,7 @@ a list of known ports and bindings is provided on [Zstandard homepage](http://ww
|
|||||||
[![Build Status][travisDevBadge]][travisLink]
|
[![Build Status][travisDevBadge]][travisLink]
|
||||||
[![Build status][AppveyorDevBadge]][AppveyorLink]
|
[![Build status][AppveyorDevBadge]][AppveyorLink]
|
||||||
[![Build status][CircleDevBadge]][CircleLink]
|
[![Build status][CircleDevBadge]][CircleLink]
|
||||||
|
[![Build status][CirrusDevBadge]][CirrusLink]
|
||||||
|
|
||||||
[travisDevBadge]: https://travis-ci.org/facebook/zstd.svg?branch=dev "Continuous Integration test suite"
|
[travisDevBadge]: https://travis-ci.org/facebook/zstd.svg?branch=dev "Continuous Integration test suite"
|
||||||
[travisLink]: https://travis-ci.org/facebook/zstd
|
[travisLink]: https://travis-ci.org/facebook/zstd
|
||||||
@ -21,14 +22,16 @@ a list of known ports and bindings is provided on [Zstandard homepage](http://ww
|
|||||||
[AppveyorLink]: https://ci.appveyor.com/project/YannCollet/zstd-p0yf0
|
[AppveyorLink]: https://ci.appveyor.com/project/YannCollet/zstd-p0yf0
|
||||||
[CircleDevBadge]: https://circleci.com/gh/facebook/zstd/tree/dev.svg?style=shield "Short test suite"
|
[CircleDevBadge]: https://circleci.com/gh/facebook/zstd/tree/dev.svg?style=shield "Short test suite"
|
||||||
[CircleLink]: https://circleci.com/gh/facebook/zstd
|
[CircleLink]: https://circleci.com/gh/facebook/zstd
|
||||||
|
[CirrusDevBadge]: https://api.cirrus-ci.com/github/facebook/zstd.svg?branch=dev
|
||||||
|
[CirrusLink]: https://cirrus-ci.com/github/facebook/zstd
|
||||||
|
|
||||||
## Benchmarks
|
## Benchmarks
|
||||||
|
|
||||||
For reference, several fast compression algorithms were tested and compared
|
For reference, several fast compression algorithms were tested and compared
|
||||||
on a server running Linux Debian (`Linux version 4.14.0-3-amd64`),
|
on a server running Arch Linux (`Linux version 5.0.5-arch1-1`),
|
||||||
with a Core i7-6700K CPU @ 4.0GHz,
|
with a Core i9-9900K CPU @ 5.0GHz,
|
||||||
using [lzbench], an open-source in-memory benchmark by @inikep
|
using [lzbench], an open-source in-memory benchmark by @inikep
|
||||||
compiled with [gcc] 7.3.0,
|
compiled with [gcc] 8.2.1,
|
||||||
on the [Silesia compression corpus].
|
on the [Silesia compression corpus].
|
||||||
|
|
||||||
[lzbench]: https://github.com/inikep/lzbench
|
[lzbench]: https://github.com/inikep/lzbench
|
||||||
@ -37,14 +40,14 @@ on the [Silesia compression corpus].
|
|||||||
|
|
||||||
| Compressor name | Ratio | Compression| Decompress.|
|
| Compressor name | Ratio | Compression| Decompress.|
|
||||||
| --------------- | ------| -----------| ---------- |
|
| --------------- | ------| -----------| ---------- |
|
||||||
| **zstd 1.3.4 -1** | 2.877 | 470 MB/s | 1380 MB/s |
|
| **zstd 1.4.0 -1** | 2.884 | 530 MB/s | 1360 MB/s |
|
||||||
| zlib 1.2.11 -1 | 2.743 | 110 MB/s | 400 MB/s |
|
| zlib 1.2.11 -1 | 2.743 | 110 MB/s | 440 MB/s |
|
||||||
| brotli 1.0.2 -0 | 2.701 | 410 MB/s | 430 MB/s |
|
| brotli 1.0.7 -0 | 2.701 | 430 MB/s | 470 MB/s |
|
||||||
| quicklz 1.5.0 -1 | 2.238 | 550 MB/s | 710 MB/s |
|
| quicklz 1.5.0 -1 | 2.238 | 600 MB/s | 800 MB/s |
|
||||||
| lzo1x 2.09 -1 | 2.108 | 650 MB/s | 830 MB/s |
|
| lzo1x 2.09 -1 | 2.106 | 680 MB/s | 950 MB/s |
|
||||||
| lz4 1.8.1 | 2.101 | 750 MB/s | 3700 MB/s |
|
| lz4 1.8.3 | 2.101 | 800 MB/s | 4220 MB/s |
|
||||||
| snappy 1.1.4 | 2.091 | 530 MB/s | 1800 MB/s |
|
| snappy 1.1.4 | 2.073 | 580 MB/s | 2020 MB/s |
|
||||||
| lzf 3.6 -1 | 2.077 | 400 MB/s | 860 MB/s |
|
| lzf 3.6 -1 | 2.077 | 440 MB/s | 930 MB/s |
|
||||||
|
|
||||||
[zlib]: http://www.zlib.net/
|
[zlib]: http://www.zlib.net/
|
||||||
[LZ4]: http://www.lz4.org/
|
[LZ4]: http://www.lz4.org/
|
||||||
|
@ -408,6 +408,10 @@
|
|||||||
RelativePath="..\..\..\programs\util.c"
|
RelativePath="..\..\..\programs\util.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\programs\timefn.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\compress\zstd_fast.c"
|
RelativePath="..\..\..\lib\compress\zstd_fast.c"
|
||||||
>
|
>
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
@ -121,7 +121,7 @@
|
|||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
@ -195,7 +195,7 @@
|
|||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
@ -272,7 +272,7 @@
|
|||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\programs"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\programs"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
@ -332,6 +332,10 @@
|
|||||||
RelativePath="..\..\..\programs\util.c"
|
RelativePath="..\..\..\programs\util.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\programs\timefn.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\programs\datagen.c"
|
RelativePath="..\..\..\programs\datagen.c"
|
||||||
>
|
>
|
||||||
|
@ -336,6 +336,10 @@
|
|||||||
RelativePath="..\..\..\programs\util.c"
|
RelativePath="..\..\..\programs\util.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\programs\timefn.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\programs\benchfn.c"
|
RelativePath="..\..\..\programs\benchfn.c"
|
||||||
>
|
>
|
||||||
|
@ -167,6 +167,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\..\lib\common\xxhash.c" />
|
<ClCompile Include="..\..\..\lib\common\xxhash.c" />
|
||||||
<ClCompile Include="..\..\..\programs\util.c" />
|
<ClCompile Include="..\..\..\programs\util.c" />
|
||||||
|
<ClCompile Include="..\..\..\programs\timefn.c" />
|
||||||
<ClCompile Include="..\..\..\programs\datagen.c" />
|
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||||
<ClCompile Include="..\..\..\programs\benchfn.c" />
|
<ClCompile Include="..\..\..\programs\benchfn.c" />
|
||||||
<ClCompile Include="..\..\..\tests\fullbench.c" />
|
<ClCompile Include="..\..\..\tests\fullbench.c" />
|
||||||
|
@ -156,7 +156,6 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
||||||
<ClCompile Include="..\..\..\programs\util.c" />
|
|
||||||
<ClCompile Include="..\..\..\lib\common\debug.c" />
|
<ClCompile Include="..\..\..\lib\common\debug.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\fse_decompress.c" />
|
<ClCompile Include="..\..\..\lib\common\fse_decompress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\zstd_common.c" />
|
<ClCompile Include="..\..\..\lib\common\zstd_common.c" />
|
||||||
@ -178,6 +177,8 @@
|
|||||||
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress_block.c" />
|
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress_block.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\zstd_ddict.c" />
|
<ClCompile Include="..\..\..\lib\decompress\zstd_ddict.c" />
|
||||||
|
<ClCompile Include="..\..\..\programs\util.c" />
|
||||||
|
<ClCompile Include="..\..\..\programs\timefn.c" />
|
||||||
<ClCompile Include="..\..\..\programs\datagen.c" />
|
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||||
<ClCompile Include="..\..\..\programs\benchfn.c" />
|
<ClCompile Include="..\..\..\programs\benchfn.c" />
|
||||||
<ClCompile Include="..\..\..\tests\fullbench.c" />
|
<ClCompile Include="..\..\..\tests\fullbench.c" />
|
||||||
|
@ -90,7 +90,7 @@
|
|||||||
</PrecompiledHeader>
|
</PrecompiledHeader>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
<EnablePREfast>false</EnablePREfast>
|
<EnablePREfast>false</EnablePREfast>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -105,7 +105,7 @@
|
|||||||
</PrecompiledHeader>
|
</PrecompiledHeader>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
<EnablePREfast>false</EnablePREfast>
|
<EnablePREfast>false</EnablePREfast>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -122,7 +122,7 @@
|
|||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<EnablePREfast>false</EnablePREfast>
|
<EnablePREfast>false</EnablePREfast>
|
||||||
<TreatWarningAsError>false</TreatWarningAsError>
|
<TreatWarningAsError>false</TreatWarningAsError>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
@ -142,7 +142,7 @@
|
|||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<TreatWarningAsError>false</TreatWarningAsError>
|
<TreatWarningAsError>false</TreatWarningAsError>
|
||||||
<EnablePREfast>false</EnablePREfast>
|
<EnablePREfast>false</EnablePREfast>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
@ -182,6 +182,7 @@
|
|||||||
<ClCompile Include="..\..\..\lib\dictBuilder\divsufsort.c" />
|
<ClCompile Include="..\..\..\lib\dictBuilder\divsufsort.c" />
|
||||||
<ClCompile Include="..\..\..\lib\dictBuilder\zdict.c" />
|
<ClCompile Include="..\..\..\lib\dictBuilder\zdict.c" />
|
||||||
<ClCompile Include="..\..\..\programs\util.c" />
|
<ClCompile Include="..\..\..\programs\util.c" />
|
||||||
|
<ClCompile Include="..\..\..\programs\timefn.c" />
|
||||||
<ClCompile Include="..\..\..\programs\datagen.c" />
|
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||||
<ClCompile Include="..\..\..\tests\fuzzer.c" />
|
<ClCompile Include="..\..\..\tests\fuzzer.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
<ClCompile Include="..\..\..\lib\legacy\zstd_v06.c" />
|
<ClCompile Include="..\..\..\lib\legacy\zstd_v06.c" />
|
||||||
<ClCompile Include="..\..\..\lib\legacy\zstd_v07.c" />
|
<ClCompile Include="..\..\..\lib\legacy\zstd_v07.c" />
|
||||||
<ClCompile Include="..\..\..\programs\util.c" />
|
<ClCompile Include="..\..\..\programs\util.c" />
|
||||||
|
<ClCompile Include="..\..\..\programs\timefn.c" />
|
||||||
<ClCompile Include="..\..\..\programs\benchfn.c" />
|
<ClCompile Include="..\..\..\programs\benchfn.c" />
|
||||||
<ClCompile Include="..\..\..\programs\benchzstd.c" />
|
<ClCompile Include="..\..\..\programs\benchzstd.c" />
|
||||||
<ClCompile Include="..\..\..\programs\datagen.c" />
|
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||||
|
@ -7,17 +7,57 @@
|
|||||||
# in the COPYING file in the root directory of this source tree).
|
# in the COPYING file in the root directory of this source tree).
|
||||||
# ################################################################
|
# ################################################################
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.9)
|
cmake_minimum_required(VERSION 2.8.9 FATAL_ERROR)
|
||||||
|
|
||||||
project(zstd)
|
# As of 2018-12-26 ZSTD has been validated to build with cmake version 3.13.2 new policies.
|
||||||
set(ZSTD_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..")
|
# Set and use the newest cmake policies that are validated to work
|
||||||
|
set(ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION "3")
|
||||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
set(ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION "13") #Policies never changed at PATCH level
|
||||||
message(STATUS "No build type selected, defaulting to Release")
|
if("${CMAKE_MAJOR_VERSION}" LESS 3)
|
||||||
set(CMAKE_BUILD_TYPE "Release")
|
set(ZSTD_CMAKE_POLICY_VERSION "${CMAKE_VERSION}")
|
||||||
|
elseif( "${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}" EQUAL "${CMAKE_MAJOR_VERSION}" AND
|
||||||
|
"${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}" GREATER "${CMAKE_MINOR_VERSION}")
|
||||||
|
set(ZSTD_CMAKE_POLICY_VERSION "${CMAKE_VERSION}")
|
||||||
|
else()
|
||||||
|
set(ZSTD_CMAKE_POLICY_VERSION "${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}.${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}.0")
|
||||||
endif()
|
endif()
|
||||||
|
cmake_policy(VERSION ${ZSTD_CMAKE_POLICY_VERSION})
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
|
||||||
|
set(ZSTD_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..")
|
||||||
|
set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib)
|
||||||
|
# Parse version
|
||||||
|
include(GetZstdLibraryVersion)
|
||||||
|
GetZstdLibraryVersion(${LIBRARY_DIR}/zstd.h zstd_VERSION_MAJOR zstd_VERSION_MINOR zstd_VERSION_PATCH)
|
||||||
|
|
||||||
|
if( CMAKE_MAJOR_VERSION LESS 3 )
|
||||||
|
## Provide cmake 3+ behavior for older versions of cmake
|
||||||
|
project(zstd)
|
||||||
|
set(PROJECT_VERSION_MAJOR ${zstd_VERSION_MAJOR})
|
||||||
|
set(PROJECT_VERSION_MINOR ${zstd_VERSION_MINOR})
|
||||||
|
set(PROJECT_VERSION_PATCH ${zstd_VERSION_PATCH})
|
||||||
|
set(PROJECT_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}")
|
||||||
|
enable_language(C) # Main library is in C
|
||||||
|
enable_language(CXX) # Testing contributed code also utilizes CXX
|
||||||
|
else()
|
||||||
|
project(zstd
|
||||||
|
VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}"
|
||||||
|
LANGUAGES C # Main library is in C
|
||||||
|
CXX # Testing contributed code also utilizes CXX
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
message(STATUS "ZSTD VERSION: ${zstd_VERSION}")
|
||||||
|
set(zstd_HOMEPAGE_URL "http://www.zstd.net")
|
||||||
|
set(zstd_DESCRIPTION "Zstandard is a real-time compression algorithm, providing high compression ratios.")
|
||||||
|
|
||||||
|
# Set a default build type if none was specified
|
||||||
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
message(STATUS "Setting build type to 'Release' as none was specified.")
|
||||||
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
|
||||||
|
# Set the possible values of build type for cmake-gui
|
||||||
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||||
|
endif()
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
@ -50,9 +50,11 @@ macro(ADD_ZSTD_COMPILATION_FLAGS)
|
|||||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||||
|
if( ${flag_var} )
|
||||||
separate_arguments(${flag_var})
|
separate_arguments(${flag_var})
|
||||||
list(REMOVE_DUPLICATES ${flag_var})
|
list(REMOVE_DUPLICATES ${flag_var})
|
||||||
string(REPLACE ";" " " ${flag_var} "${${flag_var}}")
|
string(REPLACE ";" " " ${flag_var} "${${flag_var}}")
|
||||||
|
endif()
|
||||||
endforeach ()
|
endforeach ()
|
||||||
|
|
||||||
if (MSVC AND ZSTD_USE_STATIC_RUNTIME)
|
if (MSVC AND ZSTD_USE_STATIC_RUNTIME)
|
||||||
@ -60,7 +62,9 @@ macro(ADD_ZSTD_COMPILATION_FLAGS)
|
|||||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||||
|
if ( ${flag_var} )
|
||||||
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||||
|
endif()
|
||||||
endforeach ()
|
endforeach ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
function(GetZstdLibraryVersion _header _major _minor _release)
|
function(GetZstdLibraryVersion _header _major _minor _patch)
|
||||||
# Read file content
|
# Read file content
|
||||||
file(READ ${_header} CONTENT)
|
file(READ ${_header} CONTENT)
|
||||||
|
|
||||||
string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" VERSION_REGEX "${CONTENT}")
|
string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" VERSION_REGEX "${CONTENT}")
|
||||||
set(${_major} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
set(${_major} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||||
set(${_minor} ${CMAKE_MATCH_2} PARENT_SCOPE)
|
set(${_minor} ${CMAKE_MATCH_2} PARENT_SCOPE)
|
||||||
set(${_release} ${CMAKE_MATCH_3} PARENT_SCOPE)
|
set(${_patch} ${CMAKE_MATCH_3} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
Contributions to the cmake build configurations are welcome. Please
|
Contributions to the cmake build configurations are welcome. Please
|
||||||
use case sensitivity that matches modern (ie. cmake version 2.6 and above)
|
use case sensitivity that matches modern (ie. cmake version 2.6 and above)
|
||||||
conventions of using lower-case for commands, and upper-case for
|
conventions of using lower-case for commands, and upper-case for
|
||||||
varibles.
|
variables.
|
||||||
|
|
||||||
# CMake Style Recommendations
|
# CMake Style Recommendations
|
||||||
|
|
||||||
|
@ -18,14 +18,8 @@ if(NOT ZSTD_BUILD_SHARED AND NOT ZSTD_BUILD_STATIC)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Define library directory, where sources and header files are located
|
# Define library directory, where sources and header files are located
|
||||||
set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib)
|
|
||||||
include_directories(${LIBRARY_DIR} ${LIBRARY_DIR}/common)
|
include_directories(${LIBRARY_DIR} ${LIBRARY_DIR}/common)
|
||||||
|
|
||||||
# Parse version
|
|
||||||
include(GetZstdLibraryVersion)
|
|
||||||
GetZstdLibraryVersion(${LIBRARY_DIR}/zstd.h LIBVER_MAJOR LIBVER_MINOR LIBVER_RELEASE)
|
|
||||||
message(STATUS "ZSTD VERSION ${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}")
|
|
||||||
|
|
||||||
set(Sources
|
set(Sources
|
||||||
${LIBRARY_DIR}/common/entropy_common.c
|
${LIBRARY_DIR}/common/entropy_common.c
|
||||||
${LIBRARY_DIR}/common/fse_decompress.c
|
${LIBRARY_DIR}/common/fse_decompress.c
|
||||||
@ -155,7 +149,8 @@ if (ZSTD_BUILD_SHARED)
|
|||||||
libzstd_shared
|
libzstd_shared
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
OUTPUT_NAME zstd
|
OUTPUT_NAME zstd
|
||||||
SOVERSION ${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE})
|
VERSION ${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}
|
||||||
|
SOVERSION ${zstd_VERSION_MAJOR})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (ZSTD_BUILD_STATIC)
|
if (ZSTD_BUILD_STATIC)
|
||||||
@ -170,7 +165,7 @@ if (UNIX)
|
|||||||
set(PREFIX "${CMAKE_INSTALL_PREFIX}")
|
set(PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||||
set(LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
set(LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||||
set(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
|
set(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
|
||||||
set(VERSION "${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}")
|
set(VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}")
|
||||||
add_custom_target(libzstd.pc ALL
|
add_custom_target(libzstd.pc ALL
|
||||||
${CMAKE_COMMAND} -DIN="${LIBRARY_DIR}/libzstd.pc.in" -DOUT="libzstd.pc"
|
${CMAKE_COMMAND} -DIN="${LIBRARY_DIR}/libzstd.pc.in" -DOUT="libzstd.pc"
|
||||||
-DPREFIX="${PREFIX}" -DLIBDIR="${LIBDIR}" -DINCLUDEDIR="${INCLUDEDIR}" -DVERSION="${VERSION}"
|
-DPREFIX="${PREFIX}" -DLIBDIR="${LIBDIR}" -DINCLUDEDIR="${INCLUDEDIR}" -DVERSION="${VERSION}"
|
||||||
|
@ -26,7 +26,7 @@ if (MSVC)
|
|||||||
set(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstd.rc)
|
set(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstd.rc)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_executable(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${PlatformDependResources})
|
add_executable(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${PlatformDependResources})
|
||||||
target_link_libraries(zstd libzstd_static)
|
target_link_libraries(zstd libzstd_static)
|
||||||
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
||||||
target_link_libraries(zstd rt)
|
target_link_libraries(zstd rt)
|
||||||
@ -63,7 +63,7 @@ if (UNIX)
|
|||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdgrep.1 DESTINATION "${MAN_INSTALL_DIR}")
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdgrep.1 DESTINATION "${MAN_INSTALL_DIR}")
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdless.1 DESTINATION "${MAN_INSTALL_DIR}")
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdless.1 DESTINATION "${MAN_INSTALL_DIR}")
|
||||||
|
|
||||||
add_executable(zstd-frugal ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/fileio.c)
|
add_executable(zstd-frugal ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/fileio.c)
|
||||||
target_link_libraries(zstd-frugal libzstd_static)
|
target_link_libraries(zstd-frugal libzstd_static)
|
||||||
set_property(TARGET zstd-frugal APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_NOBENCH;ZSTD_NODICT")
|
set_property(TARGET zstd-frugal APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_NOBENCH;ZSTD_NODICT")
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -43,13 +43,13 @@ include_directories(${TESTS_DIR} ${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/c
|
|||||||
add_executable(datagen ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/datagencli.c)
|
add_executable(datagen ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/datagencli.c)
|
||||||
target_link_libraries(datagen libzstd_static)
|
target_link_libraries(datagen libzstd_static)
|
||||||
|
|
||||||
add_executable(fullbench ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${TESTS_DIR}/fullbench.c)
|
add_executable(fullbench ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${TESTS_DIR}/fullbench.c)
|
||||||
target_link_libraries(fullbench libzstd_static)
|
target_link_libraries(fullbench libzstd_static)
|
||||||
|
|
||||||
add_executable(fuzzer ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${TESTS_DIR}/fuzzer.c)
|
add_executable(fuzzer ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/fuzzer.c)
|
||||||
target_link_libraries(fuzzer libzstd_static)
|
target_link_libraries(fuzzer libzstd_static)
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${TESTS_DIR}/paramgrill.c)
|
add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/paramgrill.c)
|
||||||
target_link_libraries(paramgrill libzstd_static m) #m is math library
|
target_link_libraries(paramgrill libzstd_static m) #m is math library
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -7,7 +7,7 @@ modern software development tools and practices, such as unit tests,
|
|||||||
coverage reports, Valgrind, CCache and the like.
|
coverage reports, Valgrind, CCache and the like.
|
||||||
|
|
||||||
This Meson build system is provided with no guarantee and maintained
|
This Meson build system is provided with no guarantee and maintained
|
||||||
by Dima Krasner <dima@dimakrasner.com>.
|
by Dima Krasner \<dima@dimakrasner.com\>.
|
||||||
|
|
||||||
It outputs one `libzstd`, either shared or static, depending on
|
It outputs one `libzstd`, either shared or static, depending on
|
||||||
`default_library` option.
|
`default_library` option.
|
||||||
@ -17,7 +17,7 @@ It outputs one `libzstd`, either shared or static, depending on
|
|||||||
`cd` to this meson directory (`build/meson`)
|
`cd` to this meson directory (`build/meson`)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
meson --buildtype=release -D with-contrib=true -D with-tests=true -D with-contrib=true builddir
|
meson --buildtype=release -Dbuild_{programs,contrib}=true builddir
|
||||||
cd builddir
|
cd builddir
|
||||||
ninja # to build
|
ninja # to build
|
||||||
ninja install # to install
|
ninja install # to install
|
||||||
|
@ -98,7 +98,7 @@ if use_debug
|
|||||||
if cc_id == compiler_gcc or cc_id == compiler_clang
|
if cc_id == compiler_gcc or cc_id == compiler_clang
|
||||||
libzstd_debug_cflags = ['-Wstrict-aliasing=1', '-Wswitch-enum',
|
libzstd_debug_cflags = ['-Wstrict-aliasing=1', '-Wswitch-enum',
|
||||||
'-Wdeclaration-after-statement', '-Wstrict-prototypes',
|
'-Wdeclaration-after-statement', '-Wstrict-prototypes',
|
||||||
'-Wundef', '-Wpointer-arith', '-Wformat-security', '-Wvla',
|
'-Wundef', '-Wpointer-arith', '-Wvla',
|
||||||
'-Wformat=2', '-Winit-self', '-Wfloat-equal', '-Wwrite-strings',
|
'-Wformat=2', '-Winit-self', '-Wfloat-equal', '-Wwrite-strings',
|
||||||
'-Wredundant-decls', '-Wmissing-prototypes', '-Wc++-compat']
|
'-Wredundant-decls', '-Wmissing-prototypes', '-Wc++-compat']
|
||||||
endif
|
endif
|
||||||
@ -116,9 +116,9 @@ libzstd = library('zstd',
|
|||||||
libzstd_dep = declare_dependency(link_with: libzstd,
|
libzstd_dep = declare_dependency(link_with: libzstd,
|
||||||
include_directories: libzstd_includes)
|
include_directories: libzstd_includes)
|
||||||
|
|
||||||
pkgconfig.generate(name: 'libzstd',
|
pkgconfig.generate(libzstd,
|
||||||
|
name: 'libzstd',
|
||||||
filebase: 'libzstd',
|
filebase: 'libzstd',
|
||||||
libraries: [libzstd],
|
|
||||||
description: 'fast lossless compression algorithm library',
|
description: 'fast lossless compression algorithm library',
|
||||||
version: zstd_libversion,
|
version: zstd_libversion,
|
||||||
url: 'http://www.zstd.net/')
|
url: 'http://www.zstd.net/')
|
||||||
|
@ -11,9 +11,11 @@
|
|||||||
project('zstd',
|
project('zstd',
|
||||||
['c', 'cpp'],
|
['c', 'cpp'],
|
||||||
license: ['BSD', 'GPLv2'],
|
license: ['BSD', 'GPLv2'],
|
||||||
default_options : ['c_std=c99',
|
default_options : [
|
||||||
|
'c_std=c99',
|
||||||
'cpp_std=c++11',
|
'cpp_std=c++11',
|
||||||
'buildtype=release'],
|
'buildtype=release'
|
||||||
|
],
|
||||||
version: '1.3.8',
|
version: '1.3.8',
|
||||||
meson_version: '>=0.47.0')
|
meson_version: '>=0.47.0')
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ zstd_rootdir = '../../..'
|
|||||||
|
|
||||||
zstd_programs_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'),
|
zstd_programs_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||||
|
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/fileio.c'),
|
join_paths(zstd_rootdir, 'programs/fileio.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
||||||
@ -63,6 +64,7 @@ zstd = executable('zstd',
|
|||||||
install: true)
|
install: true)
|
||||||
|
|
||||||
zstd_frugal_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'),
|
zstd_frugal_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'),
|
||||||
|
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/fileio.c')]
|
join_paths(zstd_rootdir, 'programs/fileio.c')]
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ datagen = executable('datagen',
|
|||||||
|
|
||||||
fullbench_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
fullbench_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||||
|
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
||||||
join_paths(zstd_rootdir, 'tests/fullbench.c')]
|
join_paths(zstd_rootdir, 'tests/fullbench.c')]
|
||||||
@ -51,6 +52,7 @@ fullbench = executable('fullbench',
|
|||||||
|
|
||||||
fuzzer_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
fuzzer_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||||
|
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||||
join_paths(zstd_rootdir, 'tests/fuzzer.c')]
|
join_paths(zstd_rootdir, 'tests/fuzzer.c')]
|
||||||
fuzzer = executable('fuzzer',
|
fuzzer = executable('fuzzer',
|
||||||
fuzzer_sources,
|
fuzzer_sources,
|
||||||
@ -60,6 +62,7 @@ fuzzer = executable('fuzzer',
|
|||||||
|
|
||||||
zbufftest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
zbufftest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||||
|
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||||
join_paths(zstd_rootdir, 'tests/zbufftest.c')]
|
join_paths(zstd_rootdir, 'tests/zbufftest.c')]
|
||||||
zbufftest = executable('zbufftest',
|
zbufftest = executable('zbufftest',
|
||||||
zbufftest_sources,
|
zbufftest_sources,
|
||||||
@ -70,6 +73,7 @@ zbufftest = executable('zbufftest',
|
|||||||
|
|
||||||
zstreamtest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
zstreamtest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||||
|
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||||
join_paths(zstd_rootdir, 'tests/seqgen.c'),
|
join_paths(zstd_rootdir, 'tests/seqgen.c'),
|
||||||
join_paths(zstd_rootdir, 'tests/zstreamtest.c')]
|
join_paths(zstd_rootdir, 'tests/zstreamtest.c')]
|
||||||
zstreamtest = executable('zstreamtest',
|
zstreamtest = executable('zstreamtest',
|
||||||
@ -79,6 +83,7 @@ zstreamtest = executable('zstreamtest',
|
|||||||
install: false)
|
install: false)
|
||||||
|
|
||||||
paramgrill_sources = [join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
paramgrill_sources = [join_paths(zstd_rootdir, 'programs/benchfn.c'),
|
||||||
|
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
join_paths(zstd_rootdir, 'programs/benchzstd.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/datagen.c'),
|
join_paths(zstd_rootdir, 'programs/datagen.c'),
|
||||||
join_paths(zstd_rootdir, 'programs/util.c'),
|
join_paths(zstd_rootdir, 'programs/util.c'),
|
||||||
@ -116,6 +121,7 @@ legacy = executable('legacy',
|
|||||||
install: false)
|
install: false)
|
||||||
|
|
||||||
decodecorpus_sources = [join_paths(zstd_rootdir, 'programs/util.c'),
|
decodecorpus_sources = [join_paths(zstd_rootdir, 'programs/util.c'),
|
||||||
|
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||||
join_paths(zstd_rootdir, 'tests/decodecorpus.c')]
|
join_paths(zstd_rootdir, 'tests/decodecorpus.c')]
|
||||||
decodecorpus = executable('decodecorpus',
|
decodecorpus = executable('decodecorpus',
|
||||||
decodecorpus_sources,
|
decodecorpus_sources,
|
||||||
@ -132,6 +138,7 @@ symbols = executable('symbols',
|
|||||||
install: false)
|
install: false)
|
||||||
|
|
||||||
poolTests_sources = [join_paths(zstd_rootdir, 'programs/util.c'),
|
poolTests_sources = [join_paths(zstd_rootdir, 'programs/util.c'),
|
||||||
|
join_paths(zstd_rootdir, 'programs/timefn.c'),
|
||||||
join_paths(zstd_rootdir, 'tests/poolTests.c'),
|
join_paths(zstd_rootdir, 'tests/poolTests.c'),
|
||||||
join_paths(zstd_rootdir, 'lib/common/pool.c'),
|
join_paths(zstd_rootdir, 'lib/common/pool.c'),
|
||||||
join_paths(zstd_rootdir, 'lib/common/threading.c'),
|
join_paths(zstd_rootdir, 'lib/common/threading.c'),
|
||||||
|
@ -13,7 +13,7 @@ CPPFLAGS += -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
|
|||||||
CFLAGS ?= -O3
|
CFLAGS ?= -O3
|
||||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||||
-Wstrict-prototypes -Wundef -Wformat-security \
|
-Wstrict-prototypes -Wundef \
|
||||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||||
-Wredundant-decls
|
-Wredundant-decls
|
||||||
CFLAGS += $(DEBUGFLAGS)
|
CFLAGS += $(DEBUGFLAGS)
|
||||||
@ -22,10 +22,10 @@ FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(MULTITHREAD_LDFLAGS)
|
|||||||
|
|
||||||
all: adapt datagen
|
all: adapt datagen
|
||||||
|
|
||||||
adapt: $(ZSTD_FILES) $(PRGDIR)/util.c adapt.c
|
adapt: $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c adapt.c
|
||||||
$(CC) $(FLAGS) $^ -o $@
|
$(CC) $(FLAGS) $^ -o $@
|
||||||
|
|
||||||
adapt-debug: $(ZSTD_FILES) $(PRGDIR)/util.c adapt.c
|
adapt-debug: $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c adapt.c
|
||||||
$(CC) $(FLAGS) -DDEBUG_MODE=2 $^ -o adapt
|
$(CC) $(FLAGS) -DDEBUG_MODE=2 $^ -o adapt
|
||||||
|
|
||||||
datagen : $(PRGDIR)/datagen.c datagencli.c
|
datagen : $(PRGDIR)/datagen.c datagencli.c
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <string.h> /* memset */
|
#include <string.h> /* memset */
|
||||||
#include "zstd_internal.h"
|
#include "zstd_internal.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "timefn.h" /* UTIL_time_t, UTIL_getTime, UTIL_getSpanTimeMicro */
|
||||||
|
|
||||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||||
#define PRINT(...) fprintf(stdout, __VA_ARGS__)
|
#define PRINT(...) fprintf(stdout, __VA_ARGS__)
|
||||||
|
@ -5,7 +5,7 @@ The `Dockerfile` script requires a version of `docker` >= 17.05
|
|||||||
|
|
||||||
## Installing docker
|
## Installing docker
|
||||||
|
|
||||||
The officiel docker install docs use a ppa with a modern version available:
|
The official docker install docs use a ppa with a modern version available:
|
||||||
https://docs.docker.com/install/linux/docker-ce/ubuntu/
|
https://docs.docker.com/install/linux/docker-ce/ubuntu/
|
||||||
|
|
||||||
## How to run
|
## How to run
|
||||||
|
@ -127,7 +127,7 @@ dictInfo* createDictFromFiles(sampleInfo *info, unsigned maxDictSize,
|
|||||||
|
|
||||||
|
|
||||||
/** compressWithDict() :
|
/** compressWithDict() :
|
||||||
* Compress samples from sample buffer given dicionary stored on dictionary buffer and compression level
|
* Compress samples from sample buffer given dictionary stored on dictionary buffer and compression level
|
||||||
* @return compression ratio
|
* @return compression ratio
|
||||||
*/
|
*/
|
||||||
double compressWithDict(sampleInfo *srcInfo, dictInfo* dInfo, int compressionLevel, int displayLevel) {
|
double compressWithDict(sampleInfo *srcInfo, dictInfo* dInfo, int compressionLevel, int displayLevel) {
|
||||||
@ -194,7 +194,7 @@ double compressWithDict(sampleInfo *srcInfo, dictInfo* dInfo, int compressionLev
|
|||||||
totalCompressedSize += compressedSize;
|
totalCompressedSize += compressedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sum orignal sizes */
|
/* Sum original sizes */
|
||||||
for (i = 0; i<srcInfo->nbSamples; i++) {
|
for (i = 0; i<srcInfo->nbSamples; i++) {
|
||||||
totalOriginalSize += srcInfo->samplesSizes[i];
|
totalOriginalSize += srcInfo->samplesSizes[i];
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ typedef struct {
|
|||||||
*
|
*
|
||||||
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
|
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
|
||||||
*
|
*
|
||||||
* Once the dmer with hash value d is in the dictionay we set F(d) = F(d)/2.
|
* Once the dmer with hash value d is in the dictionary we set F(d) = F(d)/2.
|
||||||
*/
|
*/
|
||||||
static FASTCOVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
static FASTCOVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
||||||
U32 *freqs, U32 begin,U32 end,
|
U32 *freqs, U32 begin,U32 end,
|
||||||
@ -149,7 +149,7 @@ static FASTCOVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
|||||||
while (activeSegment.end < end) {
|
while (activeSegment.end < end) {
|
||||||
/* Get hash value of current dmer */
|
/* Get hash value of current dmer */
|
||||||
const size_t index = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, parameters.f, ctx->d);
|
const size_t index = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, parameters.f, ctx->d);
|
||||||
/* Add frequency of this index to score if this is the first occurence of index in active segment */
|
/* Add frequency of this index to score if this is the first occurrence of index in active segment */
|
||||||
if (ctx->segmentFreqs[index] == 0) {
|
if (ctx->segmentFreqs[index] == 0) {
|
||||||
activeSegment.score += freqs[index];
|
activeSegment.score += freqs[index];
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ CFLAGS ?= -O3
|
|||||||
CFLAGS += -std=gnu99
|
CFLAGS += -std=gnu99
|
||||||
DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||||
-Wstrict-aliasing=1 -Wswitch-enum \
|
-Wstrict-aliasing=1 -Wswitch-enum \
|
||||||
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \
|
-Wstrict-prototypes -Wundef -Wpointer-arith \
|
||||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||||
-Wredundant-decls
|
-Wredundant-decls
|
||||||
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||||
@ -28,7 +28,7 @@ default: largeNbDicts
|
|||||||
|
|
||||||
all : largeNbDicts
|
all : largeNbDicts
|
||||||
|
|
||||||
largeNbDicts: util.o benchfn.o datagen.o xxhash.o largeNbDicts.c $(LIBZSTD)
|
largeNbDicts: util.o timefn.o benchfn.o datagen.o xxhash.o largeNbDicts.c $(LIBZSTD)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@
|
||||||
|
|
||||||
.PHONY: $(LIBZSTD)
|
.PHONY: $(LIBZSTD)
|
||||||
@ -38,6 +38,9 @@ $(LIBZSTD):
|
|||||||
benchfn.o: $(PROGDIR)/benchfn.c
|
benchfn.o: $(PROGDIR)/benchfn.c
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
||||||
|
|
||||||
|
timefn.o: $(PROGDIR)/timefn.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
||||||
|
|
||||||
datagen.o: $(PROGDIR)/datagen.c
|
datagen.o: $(PROGDIR)/datagen.c
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
||||||
|
|
||||||
@ -48,6 +51,7 @@ util.o: $(PROGDIR)/util.c
|
|||||||
xxhash.o : $(LIBDIR)/common/xxhash.c
|
xxhash.o : $(LIBDIR)/common/xxhash.c
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) *.o
|
$(RM) *.o
|
||||||
$(MAKE) -C $(LIBDIR) clean > /dev/null
|
$(MAKE) -C $(LIBDIR) clean > /dev/null
|
||||||
|
@ -424,7 +424,7 @@ static ddict_collection_t createDDictCollection(const void* dictBuffer, size_t d
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* mess with adresses, so that linear scanning dictionaries != linear address scanning */
|
/* mess with addresses, so that linear scanning dictionaries != linear address scanning */
|
||||||
void shuffleDictionaries(ddict_collection_t dicts)
|
void shuffleDictionaries(ddict_collection_t dicts)
|
||||||
{
|
{
|
||||||
size_t const nbDicts = dicts.nbDDict;
|
size_t const nbDicts = dicts.nbDDict;
|
||||||
|
@ -4,7 +4,7 @@ Date: Mon, 17 Jul 2017 17:08:19 -0700
|
|||||||
Subject: [PATCH v5 2/5] lib: Add zstd modules
|
Subject: [PATCH v5 2/5] lib: Add zstd modules
|
||||||
|
|
||||||
Add zstd compression and decompression kernel modules.
|
Add zstd compression and decompression kernel modules.
|
||||||
zstd offers a wide varity of compression speed and quality trade-offs.
|
zstd offers a wide variety of compression speed and quality trade-offs.
|
||||||
It can compress at speeds approaching lz4, and quality approaching lzma.
|
It can compress at speeds approaching lz4, and quality approaching lzma.
|
||||||
zstd decompressions at speeds more than twice as fast as zlib, and
|
zstd decompressions at speeds more than twice as fast as zlib, and
|
||||||
decompression speed remains roughly the same across all compression levels.
|
decompression speed remains roughly the same across all compression levels.
|
||||||
@ -21,7 +21,7 @@ will be easier to keep the kernel zstd up to date.
|
|||||||
I benchmarked zstd compression as a special character device. I ran zstd
|
I benchmarked zstd compression as a special character device. I ran zstd
|
||||||
and zlib compression at several levels, as well as performing no
|
and zlib compression at several levels, as well as performing no
|
||||||
compression, which measure the time spent copying the data to kernel space.
|
compression, which measure the time spent copying the data to kernel space.
|
||||||
Data is passed to the compresser 4096 B at a time. The benchmark file is
|
Data is passed to the compressor 4096 B at a time. The benchmark file is
|
||||||
located in the upstream zstd source repository under
|
located in the upstream zstd source repository under
|
||||||
`contrib/linux-kernel/zstd_compress_test.c` [2].
|
`contrib/linux-kernel/zstd_compress_test.c` [2].
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ Tested in userland using the test-suite in the zstd repo under
|
|||||||
`contrib/linux-kernel/test/UserlandTest.cpp` [5] by mocking the kernel
|
`contrib/linux-kernel/test/UserlandTest.cpp` [5] by mocking the kernel
|
||||||
functions. Fuzz tested using libfuzzer [6] with the fuzz harnesses under
|
functions. Fuzz tested using libfuzzer [6] with the fuzz harnesses under
|
||||||
`contrib/linux-kernel/test/{RoundTripCrash.c,DecompressCrash.c}` [7] [8]
|
`contrib/linux-kernel/test/{RoundTripCrash.c,DecompressCrash.c}` [7] [8]
|
||||||
with ASAN, UBSAN, and MSAN. Additionaly, it was tested while testing the
|
with ASAN, UBSAN, and MSAN. Additionally, it was tested while testing the
|
||||||
BtrFS and SquashFS patches coming next.
|
BtrFS and SquashFS patches coming next.
|
||||||
|
|
||||||
[1] https://clang.llvm.org/docs/ClangFormat.html
|
[1] https://clang.llvm.org/docs/ClangFormat.html
|
||||||
@ -4200,14 +4200,14 @@ index 0000000..ff18ae6
|
|||||||
+ BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
|
+ BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
|
||||||
+ U32 const fcsCode =
|
+ U32 const fcsCode =
|
||||||
+ params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */
|
+ params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */
|
||||||
+ BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
|
+ BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
|
||||||
+ size_t pos;
|
+ size_t pos;
|
||||||
+
|
+
|
||||||
+ if (dstCapacity < ZSTD_frameHeaderSize_max)
|
+ if (dstCapacity < ZSTD_frameHeaderSize_max)
|
||||||
+ return ERROR(dstSize_tooSmall);
|
+ return ERROR(dstSize_tooSmall);
|
||||||
+
|
+
|
||||||
+ ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER);
|
+ ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER);
|
||||||
+ op[4] = frameHeaderDecriptionByte;
|
+ op[4] = frameHeaderDescriptionByte;
|
||||||
+ pos = 5;
|
+ pos = 5;
|
||||||
+ if (!singleSegment)
|
+ if (!singleSegment)
|
||||||
+ op[pos++] = windowLogByte;
|
+ op[pos++] = windowLogByte;
|
||||||
@ -8812,8 +8812,8 @@ index 0000000..ef3d174
|
|||||||
+ U32 position = 0;
|
+ U32 position = 0;
|
||||||
+ U32 symbol;
|
+ U32 symbol;
|
||||||
+ for (symbol = 0; symbol <= maxSymbolValue; symbol++) {
|
+ for (symbol = 0; symbol <= maxSymbolValue; symbol++) {
|
||||||
+ int nbOccurences;
|
+ int nbOccurrences;
|
||||||
+ for (nbOccurences = 0; nbOccurences < normalizedCounter[symbol]; nbOccurences++) {
|
+ for (nbOccurrences = 0; nbOccurrences < normalizedCounter[symbol]; nbOccurrences++) {
|
||||||
+ tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
+ tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
||||||
+ position = (position + step) & tableMask;
|
+ position = (position + step) & tableMask;
|
||||||
+ while (position > highThreshold)
|
+ while (position > highThreshold)
|
||||||
@ -9944,7 +9944,7 @@ index 0000000..2143da2
|
|||||||
+ HUF_repeat_none, /**< Cannot use the previous table */
|
+ HUF_repeat_none, /**< Cannot use the previous table */
|
||||||
+ HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
|
+ HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
|
||||||
+ 4}X_repeat */
|
+ 4}X_repeat */
|
||||||
+ HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */
|
+ HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */
|
||||||
+} HUF_repeat;
|
+} HUF_repeat;
|
||||||
+/** HUF_compress4X_repeat() :
|
+/** HUF_compress4X_repeat() :
|
||||||
+* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
|
+* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
|
||||||
|
@ -11,7 +11,7 @@ Signed-off-by: Nick Terrell <terrelln@fb.com>
|
|||||||
---
|
---
|
||||||
v4 -> v5:
|
v4 -> v5:
|
||||||
- Fix patch documentation to reflect that Sean Purcell is the author
|
- Fix patch documentation to reflect that Sean Purcell is the author
|
||||||
- Don't strip trailing whitespace of unreleated code
|
- Don't strip trailing whitespace of unrelated code
|
||||||
- Make zstd_display_options() static
|
- Make zstd_display_options() static
|
||||||
|
|
||||||
v5 -> v6:
|
v5 -> v6:
|
||||||
@ -224,7 +224,7 @@ index 0000000..dcab75a
|
|||||||
+ * set the default options, this is to ensure any user supplied
|
+ * set the default options, this is to ensure any user supplied
|
||||||
+ * -X options on the appending mksquashfs command line are over-ridden.
|
+ * -X options on the appending mksquashfs command line are over-ridden.
|
||||||
+ *
|
+ *
|
||||||
+ * This function returns 0 on sucessful extraction of options, and -1 on error.
|
+ * This function returns 0 on successful extraction of options, and -1 on error.
|
||||||
+ */
|
+ */
|
||||||
+static int zstd_extract_options(int block_size, void *buffer, int size)
|
+static int zstd_extract_options(int block_size, void *buffer, int size)
|
||||||
+{
|
+{
|
||||||
|
@ -2436,14 +2436,14 @@ static size_t ZSTD_writeFrameHeader(void *dst, size_t dstCapacity, ZSTD_paramete
|
|||||||
BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
|
BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
|
||||||
U32 const fcsCode =
|
U32 const fcsCode =
|
||||||
params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */
|
params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */
|
||||||
BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
|
BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
|
||||||
size_t pos;
|
size_t pos;
|
||||||
|
|
||||||
if (dstCapacity < ZSTD_frameHeaderSize_max)
|
if (dstCapacity < ZSTD_frameHeaderSize_max)
|
||||||
return ERROR(dstSize_tooSmall);
|
return ERROR(dstSize_tooSmall);
|
||||||
|
|
||||||
ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER);
|
ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER);
|
||||||
op[4] = frameHeaderDecriptionByte;
|
op[4] = frameHeaderDescriptionByte;
|
||||||
pos = 5;
|
pos = 5;
|
||||||
if (!singleSegment)
|
if (!singleSegment)
|
||||||
op[pos++] = windowLogByte;
|
op[pos++] = windowLogByte;
|
||||||
|
@ -141,8 +141,8 @@ size_t FSE_buildCTable_wksp(FSE_CTable *ct, const short *normalizedCounter, unsi
|
|||||||
U32 position = 0;
|
U32 position = 0;
|
||||||
U32 symbol;
|
U32 symbol;
|
||||||
for (symbol = 0; symbol <= maxSymbolValue; symbol++) {
|
for (symbol = 0; symbol <= maxSymbolValue; symbol++) {
|
||||||
int nbOccurences;
|
int nbOccurrences;
|
||||||
for (nbOccurences = 0; nbOccurences < normalizedCounter[symbol]; nbOccurences++) {
|
for (nbOccurrences = 0; nbOccurrences < normalizedCounter[symbol]; nbOccurrences++) {
|
||||||
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
||||||
position = (position + step) & tableMask;
|
position = (position + step) & tableMask;
|
||||||
while (position > highThreshold)
|
while (position > highThreshold)
|
||||||
|
@ -134,7 +134,7 @@ typedef enum {
|
|||||||
HUF_repeat_none, /**< Cannot use the previous table */
|
HUF_repeat_none, /**< Cannot use the previous table */
|
||||||
HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
|
HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
|
||||||
4}X_repeat */
|
4}X_repeat */
|
||||||
HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */
|
HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */
|
||||||
} HUF_repeat;
|
} HUF_repeat;
|
||||||
/** HUF_compress4X_repeat() :
|
/** HUF_compress4X_repeat() :
|
||||||
* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
|
* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef LINUX_COMIPLER_H_
|
#ifndef LINUX_COMPILER_H_
|
||||||
#define LINUX_COMIPLER_H_
|
#define LINUX_COMPILER_H_
|
||||||
|
|
||||||
#ifndef __always_inline
|
#ifndef __always_inline
|
||||||
# define __always_inline inline
|
# define __always_inline inline
|
||||||
@ -9,4 +9,4 @@
|
|||||||
# define noinline __attribute__((__noinline__))
|
# define noinline __attribute__((__noinline__))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // LINUX_COMIPLER_H_
|
#endif // LINUX_COMPILER_H_
|
||||||
|
@ -190,13 +190,15 @@ $(ZSTDDIR)/libzstd.a: $(ZSTD_FILES)
|
|||||||
CFLAGS="$(ALL_CFLAGS)" LDFLAGS="$(ALL_LDFLAGS)" $(MAKE) -C $(ZSTDDIR) libzstd.a
|
CFLAGS="$(ALL_CFLAGS)" LDFLAGS="$(ALL_LDFLAGS)" $(MAKE) -C $(ZSTDDIR) libzstd.a
|
||||||
|
|
||||||
# Rules to build the tests
|
# Rules to build the tests
|
||||||
test/RoundTripTest$(EXT): test/RoundTripTest.o $(PROGDIR)/datagen.o Options.o \
|
test/RoundTripTest$(EXT): test/RoundTripTest.o $(PROGDIR)/datagen.o \
|
||||||
|
$(PROGDIR)/util.o Options.o \
|
||||||
Pzstd.o SkippableFrame.o $(ZSTDDIR)/libzstd.a
|
Pzstd.o SkippableFrame.o $(ZSTDDIR)/libzstd.a
|
||||||
$(LD_COMMAND)
|
$(LD_COMMAND)
|
||||||
|
|
||||||
test/%Test$(EXT): PZSTD_LDFLAGS += $(GTEST_LIB)
|
test/%Test$(EXT): PZSTD_LDFLAGS += $(GTEST_LIB)
|
||||||
test/%Test$(EXT): LIBS += -lgtest -lgtest_main
|
test/%Test$(EXT): LIBS += -lgtest -lgtest_main
|
||||||
test/%Test$(EXT): test/%Test.o $(PROGDIR)/datagen.o Options.o Pzstd.o \
|
test/%Test$(EXT): test/%Test.o $(PROGDIR)/datagen.o \
|
||||||
|
$(PROGDIR)/util.o Options.o Pzstd.o \
|
||||||
SkippableFrame.o $(ZSTDDIR)/libzstd.a
|
SkippableFrame.o $(ZSTDDIR)/libzstd.a
|
||||||
$(LD_COMMAND)
|
$(LD_COMMAND)
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ static std::uint64_t handleOneInput(const Options &options,
|
|||||||
SharedState& state) {
|
SharedState& state) {
|
||||||
auto inputSize = fileSizeOrZero(inputFile);
|
auto inputSize = fileSizeOrZero(inputFile);
|
||||||
// WorkQueue outlives ThreadPool so in the case of error we are certain
|
// WorkQueue outlives ThreadPool so in the case of error we are certain
|
||||||
// we don't accidently try to call push() on it after it is destroyed
|
// we don't accidentally try to call push() on it after it is destroyed
|
||||||
WorkQueue<std::shared_ptr<BufferWorkQueue>> outs{options.numThreads + 1};
|
WorkQueue<std::shared_ptr<BufferWorkQueue>> outs{options.numThreads + 1};
|
||||||
std::uint64_t bytesRead;
|
std::uint64_t bytesRead;
|
||||||
std::uint64_t bytesWritten;
|
std::uint64_t bytesWritten;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A subset of `folly/Range.h`.
|
* A subset of `folly/Range.h`.
|
||||||
* All code copied verbatiam modulo formatting
|
* All code copied verbatim modulo formatting
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class ResourcePool {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns A unique pointer to a resource. The resource is null iff
|
* @returns A unique pointer to a resource. The resource is null iff
|
||||||
* there are no avaiable resources and `factory()` returns null.
|
* there are no available resources and `factory()` returns null.
|
||||||
*/
|
*/
|
||||||
UniquePtr get() {
|
UniquePtr get() {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
@ -12,8 +12,8 @@ __`zstd_compression_format.md`__ : This document defines the Zstandard compressi
|
|||||||
Compliant decoders must adhere to this document,
|
Compliant decoders must adhere to this document,
|
||||||
and compliant encoders must generate data that follows it.
|
and compliant encoders must generate data that follows it.
|
||||||
|
|
||||||
Should you look for ressources to develop your own port of Zstandard algorithm,
|
Should you look for resources to develop your own port of Zstandard algorithm,
|
||||||
you may find the following ressources useful :
|
you may find the following resources useful :
|
||||||
|
|
||||||
__`educational_decoder`__ : This directory contains an implementation of a Zstandard decoder,
|
__`educational_decoder`__ : This directory contains an implementation of a Zstandard decoder,
|
||||||
compliant with the Zstandard compression format.
|
compliant with the Zstandard compression format.
|
||||||
|
@ -7,7 +7,7 @@ CPPFLAGS += -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
|
|||||||
CFLAGS ?= -O3
|
CFLAGS ?= -O3
|
||||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||||
-Wstrict-prototypes -Wundef -Wformat-security \
|
-Wstrict-prototypes -Wundef \
|
||||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||||
-Wredundant-decls
|
-Wredundant-decls
|
||||||
CFLAGS += $(DEBUGFLAGS)
|
CFLAGS += $(DEBUGFLAGS)
|
||||||
|
@ -358,7 +358,7 @@ static u32 copy_literals(const size_t seq, istream_t *litstream,
|
|||||||
ostream_t *const out);
|
ostream_t *const out);
|
||||||
|
|
||||||
// Given an offset code from a sequence command (either an actual offset value
|
// Given an offset code from a sequence command (either an actual offset value
|
||||||
// or an index for previous offset), computes the correct offset and udpates
|
// or an index for previous offset), computes the correct offset and updates
|
||||||
// the offset history
|
// the offset history
|
||||||
static size_t compute_offset(sequence_command_t seq, u64 *const offset_hist);
|
static size_t compute_offset(sequence_command_t seq, u64 *const offset_hist);
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -25,28 +25,28 @@ all: simple_compression simple_decompression \
|
|||||||
$(LIB) :
|
$(LIB) :
|
||||||
$(MAKE) -C ../lib libzstd.a
|
$(MAKE) -C ../lib libzstd.a
|
||||||
|
|
||||||
simple_compression : simple_compression.c utils.h $(LIB)
|
simple_compression : simple_compression.c common.h $(LIB)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
simple_decompression : simple_decompression.c utils.h $(LIB)
|
simple_decompression : simple_decompression.c common.h $(LIB)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
multiple_simple_compression : multiple_simple_compression.c utils.h $(LIB)
|
multiple_simple_compression : multiple_simple_compression.c common.h $(LIB)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
dictionary_compression : dictionary_compression.c utils.h $(LIB)
|
dictionary_compression : dictionary_compression.c common.h $(LIB)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
dictionary_decompression : dictionary_decompression.c utils.h $(LIB)
|
dictionary_decompression : dictionary_decompression.c common.h $(LIB)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
streaming_compression : streaming_compression.c utils.h $(LIB)
|
streaming_compression : streaming_compression.c common.h $(LIB)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
multiple_streaming_compression : multiple_streaming_compression.c utils.h $(LIB)
|
multiple_streaming_compression : multiple_streaming_compression.c common.h $(LIB)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
streaming_decompression : streaming_decompression.c utils.h $(LIB)
|
streaming_decompression : streaming_decompression.c common.h $(LIB)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
streaming_memory_usage : streaming_memory_usage.c $(LIB)
|
streaming_memory_usage : streaming_memory_usage.c $(LIB)
|
||||||
|
@ -11,15 +11,15 @@
|
|||||||
/*
|
/*
|
||||||
* This header file has common utility functions used in examples.
|
* This header file has common utility functions used in examples.
|
||||||
*/
|
*/
|
||||||
#ifndef UTILS_H
|
#ifndef COMMON_H
|
||||||
#define UTILS_H
|
#define COMMON_H
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, free, exit
|
#include <stdlib.h> // malloc, free, exit
|
||||||
#include <stdio.h> // fprintf, perror, fopen, etc.
|
#include <stdio.h> // fprintf, perror, fopen, etc.
|
||||||
#include <string.h> // strlen, strcat, memset, strerror
|
#include <string.h> // strerror
|
||||||
#include <errno.h> // errno
|
#include <errno.h> // errno
|
||||||
#include <assert.h> // assert
|
|
||||||
#include <sys/stat.h> // stat
|
#include <sys/stat.h> // stat
|
||||||
|
#include <zstd.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the returned error code from utility functions.
|
* Define the returned error code from utility functions.
|
||||||
@ -34,7 +34,34 @@ typedef enum {
|
|||||||
ERROR_saveFile = 7,
|
ERROR_saveFile = 7,
|
||||||
ERROR_malloc = 8,
|
ERROR_malloc = 8,
|
||||||
ERROR_largeFile = 9,
|
ERROR_largeFile = 9,
|
||||||
} UTILS_ErrorCode;
|
} COMMON_ErrorCode;
|
||||||
|
|
||||||
|
/*! CHECK
|
||||||
|
* Check that the condition holds. If it doesn't print a message and die.
|
||||||
|
*/
|
||||||
|
#define CHECK(cond, ...) \
|
||||||
|
do { \
|
||||||
|
if (!(cond)) { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"%s:%d CHECK(%s) failed: ", \
|
||||||
|
__FILE__, \
|
||||||
|
__LINE__, \
|
||||||
|
#cond); \
|
||||||
|
fprintf(stderr, "" __VA_ARGS__); \
|
||||||
|
fprintf(stderr, "\n"); \
|
||||||
|
exit(1); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*! CHECK_ZSTD
|
||||||
|
* Check the zstd error code and die if an error occurred after printing a
|
||||||
|
* message.
|
||||||
|
*/
|
||||||
|
#define CHECK_ZSTD(fn, ...) \
|
||||||
|
do { \
|
||||||
|
size_t const err = (fn); \
|
||||||
|
CHECK(!ZSTD_isError(err), "%s", ZSTD_getErrorName(err)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/*! fsize_orDie() :
|
/*! fsize_orDie() :
|
||||||
* Get the size of a given file path.
|
* Get the size of a given file path.
|
||||||
@ -150,10 +177,10 @@ static void* malloc_orDie(size_t size)
|
|||||||
* @return If successful this function will load file into buffer and
|
* @return If successful this function will load file into buffer and
|
||||||
* return file size, otherwise it will printout an error to stderr and exit.
|
* return file size, otherwise it will printout an error to stderr and exit.
|
||||||
*/
|
*/
|
||||||
static size_t loadFile_orDie(const char* fileName, void* buffer, int bufferSize)
|
static size_t loadFile_orDie(const char* fileName, void* buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
size_t const fileSize = fsize_orDie(fileName);
|
size_t const fileSize = fsize_orDie(fileName);
|
||||||
assert(fileSize <= bufferSize);
|
CHECK(fileSize <= bufferSize, "File too large!");
|
||||||
|
|
||||||
FILE* const inFile = fopen_orDie(fileName, "rb");
|
FILE* const inFile = fopen_orDie(fileName, "rb");
|
||||||
size_t const readSize = fread(buffer, 1, fileSize, inFile);
|
size_t const readSize = fread(buffer, 1, fileSize, inFile);
|
@ -7,13 +7,11 @@
|
|||||||
* in the COPYING file in the root directory of this source tree).
|
* in the COPYING file in the root directory of this source tree).
|
||||||
* You may select, at your option, one of the above-listed licenses.
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h> // malloc, exit
|
|
||||||
#include <stdio.h> // printf
|
#include <stdio.h> // printf
|
||||||
#include <string.h> // strerror
|
#include <stdlib.h> // free
|
||||||
#include <errno.h> // errno
|
#include <string.h> // memset, strcat
|
||||||
#include <sys/stat.h> // stat
|
|
||||||
#include <zstd.h> // presumes zstd library is installed
|
#include <zstd.h> // presumes zstd library is installed
|
||||||
#include "utils.h"
|
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||||
|
|
||||||
/* createDict() :
|
/* createDict() :
|
||||||
`dictFileName` is supposed to have been created using `zstd --train` */
|
`dictFileName` is supposed to have been created using `zstd --train` */
|
||||||
@ -23,10 +21,7 @@ static ZSTD_CDict* createCDict_orDie(const char* dictFileName, int cLevel)
|
|||||||
printf("loading dictionary %s \n", dictFileName);
|
printf("loading dictionary %s \n", dictFileName);
|
||||||
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
|
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
|
||||||
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel);
|
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel);
|
||||||
if (!cdict) {
|
CHECK(cdict != NULL, "ZSTD_createCDict() failed!");
|
||||||
fprintf(stderr, "ZSTD_createCDict error \n");
|
|
||||||
exit(7);
|
|
||||||
}
|
|
||||||
free(dictBuffer);
|
free(dictBuffer);
|
||||||
return cdict;
|
return cdict;
|
||||||
}
|
}
|
||||||
@ -39,13 +34,16 @@ static void compress(const char* fname, const char* oname, const ZSTD_CDict* cdi
|
|||||||
size_t const cBuffSize = ZSTD_compressBound(fSize);
|
size_t const cBuffSize = ZSTD_compressBound(fSize);
|
||||||
void* const cBuff = malloc_orDie(cBuffSize);
|
void* const cBuff = malloc_orDie(cBuffSize);
|
||||||
|
|
||||||
|
/* Compress using the dictionary.
|
||||||
|
* This function writes the dictionary id, and content size into the header.
|
||||||
|
* But, it doesn't use a checksum. You can control these options using the
|
||||||
|
* advanced API: ZSTD_CCtx_setParameter(), ZSTD_CCtx_refCDict(),
|
||||||
|
* and ZSTD_compress2().
|
||||||
|
*/
|
||||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||||
if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); }
|
CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||||
size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict);
|
size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict);
|
||||||
if (ZSTD_isError(cSize)) {
|
CHECK_ZSTD(cSize);
|
||||||
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
|
|
||||||
exit(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
saveFile_orDie(oname, cBuff, cSize);
|
saveFile_orDie(oname, cBuff, cSize);
|
||||||
|
|
||||||
|
@ -9,15 +9,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, exit
|
|
||||||
#include <stdio.h> // printf
|
#include <stdio.h> // printf
|
||||||
#include <string.h> // strerror
|
#include <stdlib.h> // free
|
||||||
#include <errno.h> // errno
|
|
||||||
#include <sys/stat.h> // stat
|
|
||||||
#define ZSTD_STATIC_LINKING_ONLY // ZSTD_findDecompressedSize
|
|
||||||
#include <zstd.h> // presumes zstd library is installed
|
#include <zstd.h> // presumes zstd library is installed
|
||||||
#include "utils.h"
|
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||||
|
|
||||||
/* createDict() :
|
/* createDict() :
|
||||||
`dictFileName` is supposed to have been created using `zstd --train` */
|
`dictFileName` is supposed to have been created using `zstd --train` */
|
||||||
@ -27,7 +22,7 @@ static ZSTD_DDict* createDict_orDie(const char* dictFileName)
|
|||||||
printf("loading dictionary %s \n", dictFileName);
|
printf("loading dictionary %s \n", dictFileName);
|
||||||
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
|
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
|
||||||
ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize);
|
ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize);
|
||||||
if (ddict==NULL) { fprintf(stderr, "ZSTD_createDDict error \n"); exit(5); }
|
CHECK(ddict != NULL, "ZSTD_createDDict() failed!");
|
||||||
free(dictBuffer);
|
free(dictBuffer);
|
||||||
return ddict;
|
return ddict;
|
||||||
}
|
}
|
||||||
@ -36,24 +31,40 @@ static void decompress(const char* fname, const ZSTD_DDict* ddict)
|
|||||||
{
|
{
|
||||||
size_t cSize;
|
size_t cSize;
|
||||||
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
|
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
|
||||||
unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize);
|
/* Read the content size from the frame header. For simplicity we require
|
||||||
if (rSize==ZSTD_CONTENTSIZE_ERROR) {
|
* that it is always present. By default, zstd will write the content size
|
||||||
fprintf(stderr, "%s : it was not compressed by zstd.\n", fname);
|
* in the header when it is known. If you can't guarantee that the frame
|
||||||
exit(5);
|
* content size is always written into the header, either use streaming
|
||||||
} else if (rSize==ZSTD_CONTENTSIZE_UNKNOWN) {
|
* decompression, or ZSTD_decompressBound().
|
||||||
fprintf(stderr, "%s : original size unknown \n", fname);
|
*/
|
||||||
exit(6);
|
unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
|
||||||
}
|
CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, "%s: not compressed by zstd!", fname);
|
||||||
|
CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, "%s: original size unknown!", fname);
|
||||||
void* const rBuff = malloc_orDie((size_t)rSize);
|
void* const rBuff = malloc_orDie((size_t)rSize);
|
||||||
|
|
||||||
|
/* Check that the dictionary ID matches.
|
||||||
|
* If a non-zstd dictionary is used, then both will be zero.
|
||||||
|
* By default zstd always writes the dictionary ID into the frame.
|
||||||
|
* Zstd will check if there is a dictionary ID mismatch as well.
|
||||||
|
*/
|
||||||
|
unsigned const expectedDictID = ZSTD_getDictID_fromDDict(ddict);
|
||||||
|
unsigned const actualDictID = ZSTD_getDictID_fromFrame(cBuff, cSize);
|
||||||
|
CHECK(actualDictID == expectedDictID,
|
||||||
|
"DictID mismatch: expected %u got %u",
|
||||||
|
expectedDictID,
|
||||||
|
actualDictID);
|
||||||
|
|
||||||
|
/* Decompress using the dictionary.
|
||||||
|
* If you need to control the decompression parameters, then use the
|
||||||
|
* advanced API: ZSTD_DCtx_setParameter(), ZSTD_DCtx_refDDict(), and
|
||||||
|
* ZSTD_decompressDCtx().
|
||||||
|
*/
|
||||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||||
if (dctx==NULL) { fprintf(stderr, "ZSTD_createDCtx() error \n"); exit(10); }
|
CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
|
||||||
size_t const dSize = ZSTD_decompress_usingDDict(dctx, rBuff, rSize, cBuff, cSize, ddict);
|
size_t const dSize = ZSTD_decompress_usingDDict(dctx, rBuff, rSize, cBuff, cSize, ddict);
|
||||||
if (dSize != rSize) {
|
CHECK_ZSTD(dSize);
|
||||||
fprintf(stderr, "error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize));
|
/* When zstd knows the content size, it will error if it doesn't match. */
|
||||||
exit(7);
|
CHECK(dSize == rSize, "Impossible because zstd will check this condition!");
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
|
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
|
||||||
|
@ -8,13 +8,11 @@
|
|||||||
* You may select, at your option, one of the above-listed licenses.
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, free, exit
|
#include <stdio.h> // printf
|
||||||
#include <stdio.h> // fprintf, perror, fopen, etc.
|
#include <stdlib.h> // free
|
||||||
#include <string.h> // strlen, strcat, memset, strerror
|
#include <string.h> // memcpy, strlen
|
||||||
#include <errno.h> // errno
|
|
||||||
#include <sys/stat.h> // stat
|
|
||||||
#include <zstd.h> // presumes zstd library is installed
|
#include <zstd.h> // presumes zstd library is installed
|
||||||
#include "utils.h"
|
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void* fBuffer;
|
void* fBuffer;
|
||||||
@ -28,7 +26,7 @@ typedef struct {
|
|||||||
* allocate memory for buffers big enough to compress all files
|
* allocate memory for buffers big enough to compress all files
|
||||||
* as well as memory for output file name (ofn)
|
* as well as memory for output file name (ofn)
|
||||||
*/
|
*/
|
||||||
static resources createResources_orDie(int argc, const char** argv, char **ofn, int* ofnBufferLen)
|
static resources createResources_orDie(int argc, const char** argv, char **ofn, size_t* ofnBufferLen)
|
||||||
{
|
{
|
||||||
size_t maxFilenameLength=0;
|
size_t maxFilenameLength=0;
|
||||||
size_t maxFileSize = 0;
|
size_t maxFileSize = 0;
|
||||||
@ -52,7 +50,7 @@ static resources createResources_orDie(int argc, const char** argv, char **ofn,
|
|||||||
ress.fBuffer = malloc_orDie(ress.fBufferSize);
|
ress.fBuffer = malloc_orDie(ress.fBufferSize);
|
||||||
ress.cBuffer = malloc_orDie(ress.cBufferSize);
|
ress.cBuffer = malloc_orDie(ress.cBufferSize);
|
||||||
ress.cctx = ZSTD_createCCtx();
|
ress.cctx = ZSTD_createCCtx();
|
||||||
if (ress.cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); }
|
CHECK(ress.cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||||
return ress;
|
return ress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,16 +67,17 @@ static void compressFile_orDie(resources ress, const char* fname, const char* on
|
|||||||
{
|
{
|
||||||
size_t fSize = loadFile_orDie(fname, ress.fBuffer, ress.fBufferSize);
|
size_t fSize = loadFile_orDie(fname, ress.fBuffer, ress.fBufferSize);
|
||||||
|
|
||||||
|
/* Compress using the context.
|
||||||
|
* If you need more control over parameters, use the advanced API:
|
||||||
|
* ZSTD_CCtx_setParameter(), and ZSTD_compress2().
|
||||||
|
*/
|
||||||
size_t const cSize = ZSTD_compressCCtx(ress.cctx, ress.cBuffer, ress.cBufferSize, ress.fBuffer, fSize, 1);
|
size_t const cSize = ZSTD_compressCCtx(ress.cctx, ress.cBuffer, ress.cBufferSize, ress.fBuffer, fSize, 1);
|
||||||
if (ZSTD_isError(cSize)) {
|
CHECK_ZSTD(cSize);
|
||||||
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
|
|
||||||
exit(8);
|
|
||||||
}
|
|
||||||
|
|
||||||
saveFile_orDie(oname, ress.cBuffer, cSize);
|
saveFile_orDie(oname, ress.cBuffer, cSize);
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
// printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname);
|
printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char** argv)
|
int main(int argc, const char** argv)
|
||||||
@ -94,21 +93,21 @@ int main(int argc, const char** argv)
|
|||||||
|
|
||||||
/* memory allocation for outFilename and resources */
|
/* memory allocation for outFilename and resources */
|
||||||
char* outFilename;
|
char* outFilename;
|
||||||
int outFilenameBufferLen;
|
size_t outFilenameBufferLen;
|
||||||
resources const ress = createResources_orDie(argc, argv, &outFilename, &outFilenameBufferLen);
|
resources const ress = createResources_orDie(argc, argv, &outFilename, &outFilenameBufferLen);
|
||||||
|
|
||||||
/* compress files with shared context, input and output buffers */
|
/* compress files with shared context, input and output buffers */
|
||||||
int argNb;
|
int argNb;
|
||||||
for (argNb = 1; argNb < argc; argNb++) {
|
for (argNb = 1; argNb < argc; argNb++) {
|
||||||
const char* const inFilename = argv[argNb];
|
const char* const inFilename = argv[argNb];
|
||||||
int inFilenameLen = strlen(inFilename);
|
size_t const inFilenameLen = strlen(inFilename);
|
||||||
assert(inFilenameLen + 5 <= outFilenameBufferLen);
|
CHECK(inFilenameLen + 5 <= outFilenameBufferLen, "File name too long!");
|
||||||
memcpy(outFilename, inFilename, inFilenameLen);
|
memcpy(outFilename, inFilename, inFilenameLen);
|
||||||
memcpy(outFilename+inFilenameLen, ".zst", 5);
|
memcpy(outFilename+inFilenameLen, ".zst", 5);
|
||||||
compressFile_orDie(ress, inFilename, outFilename);
|
compressFile_orDie(ress, inFilename, outFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free momery */
|
/* free memory */
|
||||||
freeResources(ress,outFilename);
|
freeResources(ress,outFilename);
|
||||||
|
|
||||||
printf("compressed %i files \n", argc-1);
|
printf("compressed %i files \n", argc-1);
|
||||||
|
@ -14,65 +14,79 @@
|
|||||||
* All structures and buffers will be created only once,
|
* All structures and buffers will be created only once,
|
||||||
* and shared across all compression operations */
|
* and shared across all compression operations */
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, exit
|
#include <stdio.h> // printf
|
||||||
#include <stdio.h> // fprintf, perror, feof
|
#include <stdlib.h> // free
|
||||||
#include <string.h> // strerror
|
#include <string.h> // memset, strcat
|
||||||
#include <errno.h> // errno
|
|
||||||
#define ZSTD_STATIC_LINKING_ONLY // streaming API defined as "experimental" for the time being
|
|
||||||
#include <zstd.h> // presumes zstd library is installed
|
#include <zstd.h> // presumes zstd library is installed
|
||||||
#include "utils.h"
|
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void* buffIn;
|
void* buffIn;
|
||||||
void* buffOut;
|
void* buffOut;
|
||||||
size_t buffInSize;
|
size_t buffInSize;
|
||||||
size_t buffOutSize;
|
size_t buffOutSize;
|
||||||
ZSTD_CStream* cstream;
|
ZSTD_CCtx* cctx;
|
||||||
} resources;
|
} resources;
|
||||||
|
|
||||||
static resources createResources_orDie()
|
static resources createResources_orDie(int cLevel)
|
||||||
{
|
{
|
||||||
resources ress;
|
resources ress;
|
||||||
ress.buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */
|
ress.buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */
|
||||||
ress.buffOutSize= ZSTD_CStreamOutSize(); /* can always flush a full block */
|
ress.buffOutSize= ZSTD_CStreamOutSize(); /* can always flush a full block */
|
||||||
ress.buffIn = malloc_orDie(ress.buffInSize);
|
ress.buffIn = malloc_orDie(ress.buffInSize);
|
||||||
ress.buffOut= malloc_orDie(ress.buffOutSize);
|
ress.buffOut= malloc_orDie(ress.buffOutSize);
|
||||||
ress.cstream = ZSTD_createCStream();
|
ress.cctx = ZSTD_createCCtx();
|
||||||
if (ress.cstream==NULL) { fprintf(stderr, "ZSTD_createCStream() error \n"); exit(10); }
|
CHECK(ress.cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||||
|
|
||||||
|
/* Set any compression parameters you want here.
|
||||||
|
* They will persist for every compression operation.
|
||||||
|
* Here we set the compression level, and enable the checksum.
|
||||||
|
*/
|
||||||
|
CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) );
|
||||||
|
CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, 1) );
|
||||||
return ress;
|
return ress;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeResources(resources ress)
|
static void freeResources(resources ress)
|
||||||
{
|
{
|
||||||
ZSTD_freeCStream(ress.cstream);
|
ZSTD_freeCCtx(ress.cctx);
|
||||||
free(ress.buffIn);
|
free(ress.buffIn);
|
||||||
free(ress.buffOut);
|
free(ress.buffOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void compressFile_orDie(resources ress, const char* fname, const char* outName, int cLevel)
|
static void compressFile_orDie(resources ress, const char* fname, const char* outName)
|
||||||
{
|
{
|
||||||
|
// Open the input and output files.
|
||||||
FILE* const fin = fopen_orDie(fname, "rb");
|
FILE* const fin = fopen_orDie(fname, "rb");
|
||||||
FILE* const fout = fopen_orDie(outName, "wb");
|
FILE* const fout = fopen_orDie(outName, "wb");
|
||||||
|
|
||||||
size_t const initResult = ZSTD_initCStream(ress.cstream, cLevel);
|
/* Reset the context to a clean state to start a new compression operation.
|
||||||
if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initCStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); }
|
* The parameters are sticky, so we keep the compression level and extra
|
||||||
|
* parameters that we set in createResources_orDie().
|
||||||
|
*/
|
||||||
|
CHECK_ZSTD( ZSTD_CCtx_reset(ress.cctx, ZSTD_reset_session_only) );
|
||||||
|
|
||||||
size_t read, toRead = ress.buffInSize;
|
size_t const toRead = ress.buffInSize;
|
||||||
|
size_t read;
|
||||||
while ( (read = fread_orDie(ress.buffIn, toRead, fin)) ) {
|
while ( (read = fread_orDie(ress.buffIn, toRead, fin)) ) {
|
||||||
ZSTD_inBuffer input = { ress.buffIn, read, 0 };
|
/* This loop is the same as streaming_compression.c.
|
||||||
while (input.pos < input.size) {
|
* See that file for detailed comments.
|
||||||
ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 };
|
*/
|
||||||
toRead = ZSTD_compressStream(ress.cstream, &output , &input); /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */
|
int const lastChunk = (read < toRead);
|
||||||
if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_compressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); }
|
ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;
|
||||||
if (toRead > ress.buffInSize) toRead = ress.buffInSize; /* Safely handle when `buffInSize` is manually changed to a smaller value */
|
|
||||||
fwrite_orDie(ress.buffOut, output.pos, fout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ZSTD_inBuffer input = { ress.buffIn, read, 0 };
|
||||||
|
int finished;
|
||||||
|
do {
|
||||||
ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 };
|
ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 };
|
||||||
size_t const remainingToFlush = ZSTD_endStream(ress.cstream, &output); /* close frame */
|
size_t const remaining = ZSTD_compressStream2(ress.cctx, &output, &input, mode);
|
||||||
if (remainingToFlush) { fprintf(stderr, "not fully flushed"); exit(13); }
|
CHECK_ZSTD(remaining);
|
||||||
fwrite_orDie(ress.buffOut, output.pos, fout);
|
fwrite_orDie(ress.buffOut, output.pos, fout);
|
||||||
|
finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
|
||||||
|
} while (!finished);
|
||||||
|
CHECK(input.pos == input.size,
|
||||||
|
"Impossible: zstd only returns 0 when the input is completely consumed!");
|
||||||
|
}
|
||||||
|
|
||||||
fclose_orDie(fout);
|
fclose_orDie(fout);
|
||||||
fclose_orDie(fin);
|
fclose_orDie(fin);
|
||||||
@ -89,7 +103,8 @@ int main(int argc, const char** argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
resources const ress = createResources_orDie();
|
int const cLevel = 7;
|
||||||
|
resources const ress = createResources_orDie(cLevel);
|
||||||
void* ofnBuffer = NULL;
|
void* ofnBuffer = NULL;
|
||||||
size_t ofnbSize = 0;
|
size_t ofnbSize = 0;
|
||||||
|
|
||||||
@ -106,7 +121,7 @@ int main(int argc, const char** argv)
|
|||||||
memset(ofnBuffer, 0, ofnSize);
|
memset(ofnBuffer, 0, ofnSize);
|
||||||
strcat(ofnBuffer, ifn);
|
strcat(ofnBuffer, ifn);
|
||||||
strcat(ofnBuffer, ".zst");
|
strcat(ofnBuffer, ".zst");
|
||||||
compressFile_orDie(ress, ifn, ofnBuffer, 7);
|
compressFile_orDie(ress, ifn, ofnBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
freeResources(ress);
|
freeResources(ress);
|
||||||
|
@ -8,13 +8,11 @@
|
|||||||
* You may select, at your option, one of the above-listed licenses.
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, free, exit
|
#include <stdio.h> // printf
|
||||||
#include <stdio.h> // fprintf, perror, fopen, etc.
|
#include <stdlib.h> // free
|
||||||
#include <string.h> // strlen, strcat, memset, strerror
|
#include <string.h> // strlen, strcat, memset
|
||||||
#include <errno.h> // errno
|
|
||||||
#include <sys/stat.h> // stat
|
|
||||||
#include <zstd.h> // presumes zstd library is installed
|
#include <zstd.h> // presumes zstd library is installed
|
||||||
#include "utils.h"
|
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||||
|
|
||||||
static void compress_orDie(const char* fname, const char* oname)
|
static void compress_orDie(const char* fname, const char* oname)
|
||||||
{
|
{
|
||||||
@ -23,11 +21,12 @@ static void compress_orDie(const char* fname, const char* oname)
|
|||||||
size_t const cBuffSize = ZSTD_compressBound(fSize);
|
size_t const cBuffSize = ZSTD_compressBound(fSize);
|
||||||
void* const cBuff = malloc_orDie(cBuffSize);
|
void* const cBuff = malloc_orDie(cBuffSize);
|
||||||
|
|
||||||
|
/* Compress.
|
||||||
|
* If you are doing many compressions, you may want to reuse the context.
|
||||||
|
* See the multiple_simple_compression.c example.
|
||||||
|
*/
|
||||||
size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1);
|
size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1);
|
||||||
if (ZSTD_isError(cSize)) {
|
CHECK_ZSTD(cSize);
|
||||||
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
|
|
||||||
exit(8);
|
|
||||||
}
|
|
||||||
|
|
||||||
saveFile_orDie(oname, cBuff, cSize);
|
saveFile_orDie(oname, cBuff, cSize);
|
||||||
|
|
||||||
|
@ -8,37 +8,36 @@
|
|||||||
* You may select, at your option, one of the above-listed licenses.
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, exit
|
|
||||||
#include <stdio.h> // printf
|
#include <stdio.h> // printf
|
||||||
#include <string.h> // strerror
|
#include <stdlib.h> // free
|
||||||
#include <errno.h> // errno
|
|
||||||
#include <sys/stat.h> // stat
|
|
||||||
#define ZSTD_STATIC_LINKING_ONLY // ZSTD_findDecompressedSize
|
|
||||||
#include <zstd.h> // presumes zstd library is installed
|
#include <zstd.h> // presumes zstd library is installed
|
||||||
#include "utils.h"
|
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||||
|
|
||||||
static void decompress(const char* fname)
|
static void decompress(const char* fname)
|
||||||
{
|
{
|
||||||
size_t cSize;
|
size_t cSize;
|
||||||
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
|
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
|
||||||
unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize);
|
/* Read the content size from the frame header. For simplicity we require
|
||||||
if (rSize==ZSTD_CONTENTSIZE_ERROR) {
|
* that it is always present. By default, zstd will write the content size
|
||||||
fprintf(stderr, "%s : it was not compressed by zstd.\n", fname);
|
* in the header when it is known. If you can't guarantee that the frame
|
||||||
exit(5);
|
* content size is always written into the header, either use streaming
|
||||||
} else if (rSize==ZSTD_CONTENTSIZE_UNKNOWN) {
|
* decompression, or ZSTD_decompressBound().
|
||||||
fprintf(stderr,
|
*/
|
||||||
"%s : original size unknown. Use streaming decompression instead.\n", fname);
|
unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
|
||||||
exit(6);
|
CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, "%s: not compressed by zstd!", fname);
|
||||||
}
|
CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, "%s: original size unknown!", fname);
|
||||||
|
|
||||||
void* const rBuff = malloc_orDie((size_t)rSize);
|
void* const rBuff = malloc_orDie((size_t)rSize);
|
||||||
|
|
||||||
|
/* Decompress.
|
||||||
|
* If you are doing many decompressions, you may want to reuse the context
|
||||||
|
* and use ZSTD_decompressDCtx(). If you want to set advanced parameters,
|
||||||
|
* use ZSTD_DCtx_setParameter().
|
||||||
|
*/
|
||||||
size_t const dSize = ZSTD_decompress(rBuff, rSize, cBuff, cSize);
|
size_t const dSize = ZSTD_decompress(rBuff, rSize, cBuff, cSize);
|
||||||
|
CHECK_ZSTD(dSize);
|
||||||
if (dSize != rSize) {
|
/* When zstd knows the content size, it will error if it doesn't match. */
|
||||||
fprintf(stderr, "error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize));
|
CHECK(dSize == rSize, "Impossible because zstd will check this condition!");
|
||||||
exit(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
|
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
|
||||||
|
@ -9,54 +9,79 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, free, exit
|
#include <stdio.h> // printf
|
||||||
#include <stdio.h> // fprintf, perror, feof, fopen, etc.
|
#include <stdlib.h> // free
|
||||||
#include <string.h> // strlen, memset, strcat
|
#include <string.h> // memset, strcat, strlen
|
||||||
#include <zstd.h> // presumes zstd library is installed
|
#include <zstd.h> // presumes zstd library is installed
|
||||||
#include "utils.h"
|
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||||
|
|
||||||
|
|
||||||
static void compressFile_orDie(const char* fname, const char* outName, int cLevel)
|
static void compressFile_orDie(const char* fname, const char* outName, int cLevel)
|
||||||
{
|
{
|
||||||
|
/* Open the input and output files. */
|
||||||
FILE* const fin = fopen_orDie(fname, "rb");
|
FILE* const fin = fopen_orDie(fname, "rb");
|
||||||
FILE* const fout = fopen_orDie(outName, "wb");
|
FILE* const fout = fopen_orDie(outName, "wb");
|
||||||
size_t const buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */
|
/* Create the input and output buffers.
|
||||||
|
* They may be any size, but we recommend using these functions to size them.
|
||||||
|
* Performance will only suffer significantly for very tiny buffers.
|
||||||
|
*/
|
||||||
|
size_t const buffInSize = ZSTD_CStreamInSize();
|
||||||
void* const buffIn = malloc_orDie(buffInSize);
|
void* const buffIn = malloc_orDie(buffInSize);
|
||||||
size_t const buffOutSize = ZSTD_CStreamOutSize(); /* can always flush a full block */
|
size_t const buffOutSize = ZSTD_CStreamOutSize();
|
||||||
void* const buffOut = malloc_orDie(buffOutSize);
|
void* const buffOut = malloc_orDie(buffOutSize);
|
||||||
|
|
||||||
ZSTD_CStream* const cstream = ZSTD_createCStream();
|
/* Create the context. */
|
||||||
if (cstream==NULL) { fprintf(stderr, "ZSTD_createCStream() error \n"); exit(10); }
|
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||||
size_t const initResult = ZSTD_initCStream(cstream, cLevel);
|
CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||||
if (ZSTD_isError(initResult)) {
|
|
||||||
fprintf(stderr, "ZSTD_initCStream() error : %s \n",
|
|
||||||
ZSTD_getErrorName(initResult));
|
|
||||||
exit(11);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read, toRead = buffInSize;
|
/* Set any parameters you want.
|
||||||
|
* Here we set the compression level, and enable the checksum.
|
||||||
|
*/
|
||||||
|
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel) );
|
||||||
|
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) );
|
||||||
|
|
||||||
|
/* This loop read from the input file, compresses that entire chunk,
|
||||||
|
* and writes all output produced to the output file.
|
||||||
|
*/
|
||||||
|
size_t const toRead = buffInSize;
|
||||||
|
size_t read;
|
||||||
while ((read = fread_orDie(buffIn, toRead, fin))) {
|
while ((read = fread_orDie(buffIn, toRead, fin))) {
|
||||||
|
/* Select the flush mode.
|
||||||
|
* If the read may not be finished (read == toRead) we use
|
||||||
|
* ZSTD_e_continue. If this is the last chunk, we use ZSTD_e_end.
|
||||||
|
* Zstd optimizes the case where the first flush mode is ZSTD_e_end,
|
||||||
|
* since it knows it is compressing the entire source in one pass.
|
||||||
|
*/
|
||||||
|
int const lastChunk = (read < toRead);
|
||||||
|
ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;
|
||||||
|
/* Set the input buffer to what we just read.
|
||||||
|
* We compress until the input buffer is empty, each time flushing the
|
||||||
|
* output.
|
||||||
|
*/
|
||||||
ZSTD_inBuffer input = { buffIn, read, 0 };
|
ZSTD_inBuffer input = { buffIn, read, 0 };
|
||||||
while (input.pos < input.size) {
|
int finished;
|
||||||
|
do {
|
||||||
|
/* Compress into the output buffer and write all of the output to
|
||||||
|
* the file so we can reuse the buffer next iteration.
|
||||||
|
*/
|
||||||
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
|
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
|
||||||
toRead = ZSTD_compressStream(cstream, &output , &input); /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */
|
size_t const remaining = ZSTD_compressStream2(cctx, &output , &input, mode);
|
||||||
if (ZSTD_isError(toRead)) {
|
CHECK_ZSTD(remaining);
|
||||||
fprintf(stderr, "ZSTD_compressStream() error : %s \n",
|
|
||||||
ZSTD_getErrorName(toRead));
|
|
||||||
exit(12);
|
|
||||||
}
|
|
||||||
if (toRead > buffInSize) toRead = buffInSize; /* Safely handle case when `buffInSize` is manually changed to a value < ZSTD_CStreamInSize()*/
|
|
||||||
fwrite_orDie(buffOut, output.pos, fout);
|
fwrite_orDie(buffOut, output.pos, fout);
|
||||||
}
|
/* If we're on the last chunk we're finished when zstd returns 0,
|
||||||
|
* which means its consumed all the input AND finished the frame.
|
||||||
|
* Otherwise, we're finished when we've consumed all the input.
|
||||||
|
*/
|
||||||
|
finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
|
||||||
|
} while (!finished);
|
||||||
|
CHECK(input.pos == input.size,
|
||||||
|
"Impossible: zstd only returns 0 when the input is completely consumed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
|
ZSTD_freeCCtx(cctx);
|
||||||
size_t const remainingToFlush = ZSTD_endStream(cstream, &output); /* close frame */
|
|
||||||
if (remainingToFlush) { fprintf(stderr, "not fully flushed"); exit(13); }
|
|
||||||
fwrite_orDie(buffOut, output.pos, fout);
|
|
||||||
|
|
||||||
ZSTD_freeCStream(cstream);
|
|
||||||
fclose_orDie(fout);
|
fclose_orDie(fout);
|
||||||
fclose_orDie(fin); free(buffIn);
|
fclose_orDie(fin);
|
||||||
|
free(buffIn);
|
||||||
free(buffOut);
|
free(buffOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,12 +9,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, exit
|
#include <stdio.h> // fprintf
|
||||||
#include <stdio.h> // fprintf, perror, feof
|
#include <stdlib.h> // free
|
||||||
#include <string.h> // strerror
|
|
||||||
#include <errno.h> // errno
|
|
||||||
#include <zstd.h> // presumes zstd library is installed
|
#include <zstd.h> // presumes zstd library is installed
|
||||||
#include "utils.h"
|
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||||
|
|
||||||
static void decompressFile_orDie(const char* fname)
|
static void decompressFile_orDie(const char* fname)
|
||||||
{
|
{
|
||||||
@ -25,26 +23,40 @@ static void decompressFile_orDie(const char* fname)
|
|||||||
size_t const buffOutSize = ZSTD_DStreamOutSize(); /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */
|
size_t const buffOutSize = ZSTD_DStreamOutSize(); /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */
|
||||||
void* const buffOut = malloc_orDie(buffOutSize);
|
void* const buffOut = malloc_orDie(buffOutSize);
|
||||||
|
|
||||||
ZSTD_DStream* const dstream = ZSTD_createDStream();
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||||
if (dstream==NULL) { fprintf(stderr, "ZSTD_createDStream() error \n"); exit(10); }
|
CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
|
||||||
|
|
||||||
/* In more complex scenarios, a file may consist of multiple appended frames (ex : pzstd).
|
/* This loop assumes that the input file is one or more concatenated zstd
|
||||||
* The following example decompresses only the first frame.
|
* streams. This example won't work if there is trailing non-zstd data at
|
||||||
* It is compatible with other provided streaming examples */
|
* the end, but streaming decompression in general handles this case.
|
||||||
size_t const initResult = ZSTD_initDStream(dstream);
|
* ZSTD_decompressStream() returns 0 exactly when the frame is completed,
|
||||||
if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initDStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); }
|
* and doesn't consume input after the frame.
|
||||||
size_t read, toRead = initResult;
|
*/
|
||||||
|
size_t const toRead = buffInSize;
|
||||||
|
size_t read;
|
||||||
while ( (read = fread_orDie(buffIn, toRead, fin)) ) {
|
while ( (read = fread_orDie(buffIn, toRead, fin)) ) {
|
||||||
ZSTD_inBuffer input = { buffIn, read, 0 };
|
ZSTD_inBuffer input = { buffIn, read, 0 };
|
||||||
|
/* Given a valid frame, zstd won't consume the last byte of the frame
|
||||||
|
* until it has flushed all of the decompressed data of the frame.
|
||||||
|
* Therefore, instead of checking if the return code is 0, we can
|
||||||
|
* decompress just check if input.pos < input.size.
|
||||||
|
*/
|
||||||
while (input.pos < input.size) {
|
while (input.pos < input.size) {
|
||||||
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
|
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
|
||||||
toRead = ZSTD_decompressStream(dstream, &output , &input); /* toRead : size of next compressed block */
|
/* The return code is zero if the frame is complete, but there may
|
||||||
if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_decompressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); }
|
* be multiple frames concatenated together. Zstd will automatically
|
||||||
|
* reset the context when a frame is complete. Still, calling
|
||||||
|
* ZSTD_DCtx_reset() can be useful to reset the context to a clean
|
||||||
|
* state, for instance if the last decompression call returned an
|
||||||
|
* error.
|
||||||
|
*/
|
||||||
|
size_t const ret = ZSTD_decompressStream(dctx, &output , &input);
|
||||||
|
CHECK_ZSTD(ret);
|
||||||
fwrite_orDie(buffOut, output.pos, fout);
|
fwrite_orDie(buffOut, output.pos, fout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZSTD_freeDStream(dstream);
|
ZSTD_freeDCtx(dctx);
|
||||||
fclose_orDie(fin);
|
fclose_orDie(fin);
|
||||||
fclose_orDie(fout);
|
fclose_orDie(fout);
|
||||||
free(buffIn);
|
free(buffIn);
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
|
|
||||||
/*=== Dependencies ===*/
|
/*=== Dependencies ===*/
|
||||||
#include <stdio.h> /* printf */
|
#include <stdio.h> // printf
|
||||||
#define ZSTD_STATIC_LINKING_ONLY
|
#define ZSTD_STATIC_LINKING_ONLY
|
||||||
#include "zstd.h"
|
#include <zstd.h> // presumes zstd library is installed
|
||||||
|
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
|
||||||
|
|
||||||
|
|
||||||
/*=== functions ===*/
|
/*=== functions ===*/
|
||||||
@ -61,90 +62,75 @@ int main(int argc, char const *argv[]) {
|
|||||||
char const dataToCompress[INPUT_SIZE] = "abcde";
|
char const dataToCompress[INPUT_SIZE] = "abcde";
|
||||||
char compressedData[COMPRESSED_SIZE];
|
char compressedData[COMPRESSED_SIZE];
|
||||||
char decompressedData[INPUT_SIZE];
|
char decompressedData[INPUT_SIZE];
|
||||||
ZSTD_CStream* const cstream = ZSTD_createCStream();
|
/* the ZSTD_CCtx_params structure is a way to save parameters and use
|
||||||
if (cstream==NULL) {
|
* them across multiple contexts. We use them here so we can call the
|
||||||
printf("Level %i : ZSTD_CStream Memory allocation failure \n", compressionLevel);
|
* function ZSTD_estimateCStreamSize_usingCCtxParams().
|
||||||
return 1;
|
*/
|
||||||
}
|
ZSTD_CCtx_params* const cctxParams = ZSTD_createCCtxParams();
|
||||||
|
CHECK(cctxParams != NULL, "ZSTD_createCCtxParams() failed!");
|
||||||
|
|
||||||
/* forces compressor to use maximum memory size for given compression level,
|
/* Set the compression level. */
|
||||||
* by not providing any information on input size */
|
CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_compressionLevel, compressionLevel) );
|
||||||
ZSTD_parameters params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
/* Set the window log.
|
||||||
if (wLog) { /* special mode : specific wLog */
|
* The value 0 means use the default window log, which is equivalent to
|
||||||
printf("Using custom compression parameter : level 1 + wLog=%u \n", wLog);
|
* not setting it.
|
||||||
params = ZSTD_getParams(1 /*compressionLevel*/,
|
*/
|
||||||
1 << wLog /*estimatedSrcSize*/,
|
CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, wLog) );
|
||||||
0 /*no dictionary*/);
|
|
||||||
size_t const error = ZSTD_initCStream_advanced(cstream, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN);
|
|
||||||
if (ZSTD_isError(error)) {
|
|
||||||
printf("ZSTD_initCStream_advanced error : %s \n", ZSTD_getErrorName(error));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
size_t const error = ZSTD_initCStream(cstream, compressionLevel);
|
|
||||||
if (ZSTD_isError(error)) {
|
|
||||||
printf("ZSTD_initCStream error : %s \n", ZSTD_getErrorName(error));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Force the compressor to allocate the maximum memory size for a given
|
||||||
|
* level by not providing the pledged source size, or calling
|
||||||
|
* ZSTD_compressStream2() with ZSTD_e_end.
|
||||||
|
*/
|
||||||
|
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||||
|
CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
|
||||||
|
CHECK_ZSTD( ZSTD_CCtx_setParametersUsingCCtxParams(cctx, cctxParams) );
|
||||||
size_t compressedSize;
|
size_t compressedSize;
|
||||||
{ ZSTD_inBuffer inBuff = { dataToCompress, sizeof(dataToCompress), 0 };
|
{
|
||||||
|
ZSTD_inBuffer inBuff = { dataToCompress, sizeof(dataToCompress), 0 };
|
||||||
ZSTD_outBuffer outBuff = { compressedData, sizeof(compressedData), 0 };
|
ZSTD_outBuffer outBuff = { compressedData, sizeof(compressedData), 0 };
|
||||||
size_t const cError = ZSTD_compressStream(cstream, &outBuff, &inBuff);
|
CHECK_ZSTD( ZSTD_compressStream(cctx, &outBuff, &inBuff) );
|
||||||
if (ZSTD_isError(cError)) {
|
size_t const remaining = ZSTD_endStream(cctx, &outBuff);
|
||||||
printf("ZSTD_compressStream error : %s \n", ZSTD_getErrorName(cError));
|
CHECK_ZSTD(remaining);
|
||||||
return 1;
|
CHECK(remaining == 0, "Frame not flushed!");
|
||||||
}
|
|
||||||
size_t const fError = ZSTD_endStream(cstream, &outBuff);
|
|
||||||
if (ZSTD_isError(fError)) {
|
|
||||||
printf("ZSTD_endStream error : %s \n", ZSTD_getErrorName(fError));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
compressedSize = outBuff.pos;
|
compressedSize = outBuff.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZSTD_DStream* dstream = ZSTD_createDStream();
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||||
if (dstream==NULL) {
|
CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
|
||||||
printf("Level %i : ZSTD_DStream Memory allocation failure \n", compressionLevel);
|
/* Set the maximum allowed window log.
|
||||||
return 1;
|
* The value 0 means use the default window log, which is equivalent to
|
||||||
}
|
* not setting it.
|
||||||
{ size_t const error = ZSTD_initDStream(dstream);
|
*/
|
||||||
if (ZSTD_isError(error)) {
|
CHECK_ZSTD( ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, wLog) );
|
||||||
printf("ZSTD_initDStream error : %s \n", ZSTD_getErrorName(error));
|
/* forces decompressor to use maximum memory size, since the
|
||||||
return 1;
|
* decompressed size is not stored in the frame header.
|
||||||
}
|
*/
|
||||||
}
|
|
||||||
/* forces decompressor to use maximum memory size, as decompressed size is not known */
|
|
||||||
{ ZSTD_inBuffer inBuff = { compressedData, compressedSize, 0 };
|
{ ZSTD_inBuffer inBuff = { compressedData, compressedSize, 0 };
|
||||||
ZSTD_outBuffer outBuff = { decompressedData, sizeof(decompressedData), 0 };
|
ZSTD_outBuffer outBuff = { decompressedData, sizeof(decompressedData), 0 };
|
||||||
size_t const dResult = ZSTD_decompressStream(dstream, &outBuff, &inBuff);
|
size_t const remaining = ZSTD_decompressStream(dctx, &outBuff, &inBuff);
|
||||||
if (ZSTD_isError(dResult)) {
|
CHECK_ZSTD(remaining);
|
||||||
printf("ZSTD_decompressStream error : %s \n", ZSTD_getErrorName(dResult));
|
CHECK(remaining == 0, "Frame not complete!");
|
||||||
return 1;
|
CHECK(outBuff.pos == sizeof(dataToCompress), "Bad decompression!");
|
||||||
}
|
|
||||||
if (dResult != 0) {
|
|
||||||
printf("ZSTD_decompressStream error : unfinished decompression \n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (outBuff.pos != sizeof(dataToCompress)) {
|
|
||||||
printf("ZSTD_decompressStream error : incorrect decompression \n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t const cstreamSize = ZSTD_sizeof_CStream(cstream);
|
size_t const cstreamSize = ZSTD_sizeof_CStream(cctx);
|
||||||
size_t const cstreamEstimatedSize = wLog ?
|
size_t const cstreamEstimatedSize = ZSTD_estimateCStreamSize_usingCCtxParams(cctxParams);
|
||||||
ZSTD_estimateCStreamSize_usingCParams(params.cParams) :
|
size_t const dstreamSize = ZSTD_sizeof_DStream(dctx);
|
||||||
ZSTD_estimateCStreamSize(compressionLevel);
|
size_t const dstreamEstimatedSize = ZSTD_estimateDStreamSize_fromFrame(compressedData, compressedSize);
|
||||||
size_t const dstreamSize = ZSTD_sizeof_DStream(dstream);
|
|
||||||
|
|
||||||
printf("Level %2i : Compression Mem = %5u KB (estimated : %5u KB) ; Decompression Mem = %4u KB \n",
|
CHECK(cstreamSize <= cstreamEstimatedSize, "Compression mem (%u) > estimated (%u)",
|
||||||
|
(unsigned)cstreamSize, (unsigned)cstreamEstimatedSize);
|
||||||
|
CHECK(dstreamSize <= dstreamEstimatedSize, "Decompression mem (%u) > estimated (%u)",
|
||||||
|
(unsigned)dstreamSize, (unsigned)dstreamEstimatedSize);
|
||||||
|
|
||||||
|
printf("Level %2i : Compression Mem = %5u KB (estimated : %5u KB) ; Decompression Mem = %4u KB (estimated : %5u KB)\n",
|
||||||
compressionLevel,
|
compressionLevel,
|
||||||
(unsigned)(cstreamSize>>10), (unsigned)(cstreamEstimatedSize>>10), (unsigned)(dstreamSize>>10));
|
(unsigned)(cstreamSize>>10), (unsigned)(cstreamEstimatedSize>>10),
|
||||||
|
(unsigned)(dstreamSize>>10), (unsigned)(dstreamEstimatedSize>>10));
|
||||||
|
|
||||||
ZSTD_freeDStream(dstream);
|
ZSTD_freeDCtx(dctx);
|
||||||
ZSTD_freeCStream(cstream);
|
ZSTD_freeCCtx(cctx);
|
||||||
|
ZSTD_freeCCtxParams(cctxParams);
|
||||||
if (wLog) break; /* single test */
|
if (wLog) break; /* single test */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
10
lib/Makefile
10
lib/Makefile
@ -25,7 +25,7 @@ endif
|
|||||||
CFLAGS ?= -O3
|
CFLAGS ?= -O3
|
||||||
DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||||
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \
|
-Wstrict-prototypes -Wundef -Wpointer-arith \
|
||||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||||
-Wredundant-decls -Wmissing-prototypes -Wc++-compat
|
-Wredundant-decls -Wmissing-prototypes -Wc++-compat
|
||||||
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||||
@ -56,6 +56,7 @@ ZSTD_FORCE_DECOMPRESS_SHORT ?= 0
|
|||||||
ZSTD_FORCE_DECOMPRESS_LONG ?= 0
|
ZSTD_FORCE_DECOMPRESS_LONG ?= 0
|
||||||
ZSTD_NO_INLINE ?= 0
|
ZSTD_NO_INLINE ?= 0
|
||||||
ZSTD_STRIP_ERROR_STRINGS ?= 0
|
ZSTD_STRIP_ERROR_STRINGS ?= 0
|
||||||
|
ZSTD_LEGACY_MULTITHREADED_API ?= 0
|
||||||
|
|
||||||
ifeq ($(ZSTD_LIB_COMPRESSION), 0)
|
ifeq ($(ZSTD_LIB_COMPRESSION), 0)
|
||||||
ZSTD_LIB_DICTBUILDER = 0
|
ZSTD_LIB_DICTBUILDER = 0
|
||||||
@ -107,6 +108,10 @@ ifneq ($(ZSTD_STRIP_ERROR_STRINGS), 0)
|
|||||||
CFLAGS += -DZSTD_STRIP_ERROR_STRINGS
|
CFLAGS += -DZSTD_STRIP_ERROR_STRINGS
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(ZSTD_LEGACY_MULTITHREADED_API), 0)
|
||||||
|
CFLAGS += -DZSTD_LEGACY_MULTITHREADED_API
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(ZSTD_LEGACY_SUPPORT), 0)
|
ifneq ($(ZSTD_LEGACY_SUPPORT), 0)
|
||||||
ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0)
|
ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0)
|
||||||
ZSTD_FILES += $(shell ls legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]')
|
ZSTD_FILES += $(shell ls legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]')
|
||||||
@ -151,8 +156,7 @@ ifneq (,$(filter Windows%,$(OS)))
|
|||||||
LIBZSTD = dll\libzstd.dll
|
LIBZSTD = dll\libzstd.dll
|
||||||
$(LIBZSTD): $(ZSTD_FILES)
|
$(LIBZSTD): $(ZSTD_FILES)
|
||||||
@echo compiling dynamic library $(LIBVER)
|
@echo compiling dynamic library $(LIBVER)
|
||||||
@$(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -shared $^ -o $@
|
$(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -Wl,--out-implib,dll\libzstd.lib -shared $^ -o $@
|
||||||
dlltool -D $@ -d dll\libzstd.def -l dll\libzstd.lib
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
@ -31,8 +31,6 @@ note that it's necessary to request the `-pthread` flag during link stage.
|
|||||||
|
|
||||||
Multithreading capabilities are exposed
|
Multithreading capabilities are exposed
|
||||||
via the [advanced API defined in `lib/zstd.h`](https://github.com/facebook/zstd/blob/v1.3.8/lib/zstd.h#L592).
|
via the [advanced API defined in `lib/zstd.h`](https://github.com/facebook/zstd/blob/v1.3.8/lib/zstd.h#L592).
|
||||||
This API is still labelled experimental,
|
|
||||||
but is expected to become "stable" in the near future.
|
|
||||||
|
|
||||||
|
|
||||||
#### API
|
#### API
|
||||||
@ -110,6 +108,10 @@ The file structure is designed to make this selection manually achievable for an
|
|||||||
which removes the error messages that are otherwise returned by
|
which removes the error messages that are otherwise returned by
|
||||||
`ZSTD_getErrorName`.
|
`ZSTD_getErrorName`.
|
||||||
|
|
||||||
|
- While invoking `make libzstd`, the build macro `ZSTD_LEGACY_MULTITHREADED_API=1`
|
||||||
|
will expose the deprecated `ZSTDMT` API exposed by `zstdmt_compress.h` in
|
||||||
|
the shared library, which is now hidden by default.
|
||||||
|
|
||||||
|
|
||||||
#### Windows : using MinGW+MSYS to create DLL
|
#### Windows : using MinGW+MSYS to create DLL
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
|
* FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
|
||||||
* parameters. They must be inlined for the compiler to elimininate the constant
|
* parameters. They must be inlined for the compiler to eliminate the constant
|
||||||
* branches.
|
* branches.
|
||||||
*/
|
*/
|
||||||
#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
||||||
|
@ -358,7 +358,7 @@ size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
FSE_repeat_none, /**< Cannot use the previous table */
|
FSE_repeat_none, /**< Cannot use the previous table */
|
||||||
FSE_repeat_check, /**< Can use the previous table but it must be checked */
|
FSE_repeat_check, /**< Can use the previous table but it must be checked */
|
||||||
FSE_repeat_valid /**< Can use the previous table and it is asumed to be valid */
|
FSE_repeat_valid /**< Can use the previous table and it is assumed to be valid */
|
||||||
} FSE_repeat;
|
} FSE_repeat;
|
||||||
|
|
||||||
/* *****************************************
|
/* *****************************************
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
* This file will hold wrapper for systems, which do not support pthreads
|
* This file will hold wrapper for systems, which do not support pthreads
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* create fake symbol to avoid empty trnaslation unit warning */
|
/* create fake symbol to avoid empty translation unit warning */
|
||||||
int g_ZSTD_threading_useles_symbol;
|
int g_ZSTD_threading_useless_symbol;
|
||||||
|
|
||||||
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
||||||
|
|
||||||
|
@ -66,10 +66,10 @@
|
|||||||
/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
|
/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
|
||||||
|
|
||||||
/*!XXH_FORCE_NATIVE_FORMAT :
|
/*!XXH_FORCE_NATIVE_FORMAT :
|
||||||
* By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
|
* By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
|
||||||
* Results are therefore identical for little-endian and big-endian CPU.
|
* 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.
|
* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
|
||||||
* Should endian-independance be of no importance for your application, you may set the #define below to 1,
|
* Should endian-independence be of no importance for your application, you may set the #define below to 1,
|
||||||
* to improve speed for Big-endian CPU.
|
* to improve speed for Big-endian CPU.
|
||||||
* This option has no impact on Little_Endian CPU.
|
* This option has no impact on Little_Endian CPU.
|
||||||
*/
|
*/
|
||||||
|
@ -53,8 +53,50 @@ extern "C" {
|
|||||||
#undef MAX
|
#undef MAX
|
||||||
#define MIN(a,b) ((a)<(b) ? (a) : (b))
|
#define MIN(a,b) ((a)<(b) ? (a) : (b))
|
||||||
#define MAX(a,b) ((a)>(b) ? (a) : (b))
|
#define MAX(a,b) ((a)>(b) ? (a) : (b))
|
||||||
#define CHECK_F(f) { size_t const errcod = f; if (ERR_isError(errcod)) return errcod; } /* check and Forward error code */
|
|
||||||
#define CHECK_E(f, e) { size_t const errcod = f; if (ERR_isError(errcod)) return ERROR(e); } /* check and send Error code */
|
/**
|
||||||
|
* Return the specified error if the condition evaluates to true.
|
||||||
|
*
|
||||||
|
* In debug modes, prints additional information. In order to do that
|
||||||
|
* (particularly, printing the conditional that failed), this can't just wrap
|
||||||
|
* RETURN_ERROR().
|
||||||
|
*/
|
||||||
|
#define RETURN_ERROR_IF(cond, err, ...) \
|
||||||
|
if (cond) { \
|
||||||
|
RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \
|
||||||
|
RAWLOG(3, ": " __VA_ARGS__); \
|
||||||
|
RAWLOG(3, "\n"); \
|
||||||
|
return ERROR(err); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unconditionally return the specified error.
|
||||||
|
*
|
||||||
|
* In debug modes, prints additional information.
|
||||||
|
*/
|
||||||
|
#define RETURN_ERROR(err, ...) \
|
||||||
|
do { \
|
||||||
|
RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \
|
||||||
|
RAWLOG(3, ": " __VA_ARGS__); \
|
||||||
|
RAWLOG(3, "\n"); \
|
||||||
|
return ERROR(err); \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the provided expression evaluates to an error code, returns that error code.
|
||||||
|
*
|
||||||
|
* In debug modes, prints additional information.
|
||||||
|
*/
|
||||||
|
#define FORWARD_IF_ERROR(err, ...) \
|
||||||
|
do { \
|
||||||
|
size_t const err_code = (err); \
|
||||||
|
if (ERR_isError(err_code)) { \
|
||||||
|
RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \
|
||||||
|
RAWLOG(3, ": " __VA_ARGS__); \
|
||||||
|
RAWLOG(3, "\n"); \
|
||||||
|
return err_code; \
|
||||||
|
} \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************
|
/*-*************************************
|
||||||
@ -200,6 +242,17 @@ typedef struct {
|
|||||||
U32 longLengthPos;
|
U32 longLengthPos;
|
||||||
} seqStore_t;
|
} seqStore_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the compressed frame size and an upper-bound for the decompressed frame size.
|
||||||
|
* Note: before using `compressedSize`, check for errors using ZSTD_isError().
|
||||||
|
* similarly, before using `decompressedBound`, check for errors using:
|
||||||
|
* `decompressedBound != ZSTD_CONTENTSIZE_ERROR`
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
size_t compressedSize;
|
||||||
|
unsigned long long decompressedBound;
|
||||||
|
} ZSTD_frameSizeInfo; /* decompress & legacy */
|
||||||
|
|
||||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */
|
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */
|
||||||
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
|
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
|
||||||
|
|
||||||
|
@ -129,9 +129,9 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
|
|||||||
{ U32 position = 0;
|
{ U32 position = 0;
|
||||||
U32 symbol;
|
U32 symbol;
|
||||||
for (symbol=0; symbol<=maxSymbolValue; symbol++) {
|
for (symbol=0; symbol<=maxSymbolValue; symbol++) {
|
||||||
int nbOccurences;
|
int nbOccurrences;
|
||||||
int const freq = normalizedCounter[symbol];
|
int const freq = normalizedCounter[symbol];
|
||||||
for (nbOccurences=0; nbOccurences<freq; nbOccurences++) {
|
for (nbOccurrences=0; nbOccurrences<freq; nbOccurrences++) {
|
||||||
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
||||||
position = (position + step) & tableMask;
|
position = (position + step) & tableMask;
|
||||||
while (position > highThreshold)
|
while (position > highThreshold)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -36,9 +36,9 @@ extern "C" {
|
|||||||
#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1 now means "unsorted".
|
#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1 now means "unsorted".
|
||||||
It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
|
It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
|
||||||
It's not a big deal though : candidate will just be sorted again.
|
It's not a big deal though : candidate will just be sorted again.
|
||||||
Additionnally, candidate position 1 will be lost.
|
Additionally, candidate position 1 will be lost.
|
||||||
But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
|
But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
|
||||||
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be misdhandled after table re-use with a different strategy
|
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy
|
||||||
Constant required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
|
Constant required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
|
||||||
|
|
||||||
|
|
||||||
@ -54,6 +54,14 @@ typedef struct ZSTD_prefixDict_s {
|
|||||||
ZSTD_dictContentType_e dictContentType;
|
ZSTD_dictContentType_e dictContentType;
|
||||||
} ZSTD_prefixDict;
|
} ZSTD_prefixDict;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* dictBuffer;
|
||||||
|
void const* dict;
|
||||||
|
size_t dictSize;
|
||||||
|
ZSTD_dictContentType_e dictContentType;
|
||||||
|
ZSTD_CDict* cdict;
|
||||||
|
} ZSTD_localDict;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
U32 CTable[HUF_CTABLE_SIZE_U32(255)];
|
U32 CTable[HUF_CTABLE_SIZE_U32(255)];
|
||||||
HUF_repeat repeatMode;
|
HUF_repeat repeatMode;
|
||||||
@ -107,6 +115,7 @@ typedef struct {
|
|||||||
U32 offCodeSumBasePrice; /* to compare to log2(offreq) */
|
U32 offCodeSumBasePrice; /* to compare to log2(offreq) */
|
||||||
ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */
|
ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */
|
||||||
const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */
|
const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */
|
||||||
|
ZSTD_literalCompressionMode_e literalCompressionMode;
|
||||||
} optState_t;
|
} optState_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -188,6 +197,7 @@ struct ZSTD_CCtx_params_s {
|
|||||||
* 1<<wLog, even for dictionary */
|
* 1<<wLog, even for dictionary */
|
||||||
|
|
||||||
ZSTD_dictAttachPref_e attachDictPref;
|
ZSTD_dictAttachPref_e attachDictPref;
|
||||||
|
ZSTD_literalCompressionMode_e literalCompressionMode;
|
||||||
|
|
||||||
/* Multithreading: used to pass parameters to mtctx */
|
/* Multithreading: used to pass parameters to mtctx */
|
||||||
int nbWorkers;
|
int nbWorkers;
|
||||||
@ -243,7 +253,7 @@ struct ZSTD_CCtx_s {
|
|||||||
U32 frameEnded;
|
U32 frameEnded;
|
||||||
|
|
||||||
/* Dictionary */
|
/* Dictionary */
|
||||||
ZSTD_CDict* cdictLocal;
|
ZSTD_localDict localDict;
|
||||||
const ZSTD_CDict* cdict;
|
const ZSTD_CDict* cdict;
|
||||||
ZSTD_prefixDict prefixDict; /* single-usage dictionary */
|
ZSTD_prefixDict prefixDict; /* single-usage dictionary */
|
||||||
|
|
||||||
@ -806,13 +816,6 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
|||||||
|
|
||||||
void ZSTD_resetSeqStore(seqStore_t* ssPtr);
|
void ZSTD_resetSeqStore(seqStore_t* ssPtr);
|
||||||
|
|
||||||
/*! ZSTD_compressStream_generic() :
|
|
||||||
* Private use only. To be called from zstdmt_compress.c in single-thread mode. */
|
|
||||||
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
||||||
ZSTD_outBuffer* output,
|
|
||||||
ZSTD_inBuffer* input,
|
|
||||||
ZSTD_EndDirective const flushMode);
|
|
||||||
|
|
||||||
/*! ZSTD_getCParamsFromCDict() :
|
/*! ZSTD_getCParamsFromCDict() :
|
||||||
* as the name implies */
|
* as the name implies */
|
||||||
ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
|
ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
|
||||||
@ -839,7 +842,7 @@ size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
|
|||||||
/* ZSTD_writeLastEmptyBlock() :
|
/* ZSTD_writeLastEmptyBlock() :
|
||||||
* output an empty Block with end-of-frame mark to complete a frame
|
* output an empty Block with end-of-frame mark to complete a frame
|
||||||
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
|
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
|
||||||
* or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
|
* or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
|
||||||
*/
|
*/
|
||||||
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
|
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
|
||||||
|
|
||||||
|
@ -45,7 +45,155 @@ FORCE_INLINE_TEMPLATE
|
|||||||
size_t ZSTD_compressBlock_fast_generic(
|
size_t ZSTD_compressBlock_fast_generic(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
void const* src, size_t srcSize,
|
void const* src, size_t srcSize,
|
||||||
U32 const mls, ZSTD_dictMode_e const dictMode)
|
U32 const mls)
|
||||||
|
{
|
||||||
|
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||||
|
U32* const hashTable = ms->hashTable;
|
||||||
|
U32 const hlog = cParams->hashLog;
|
||||||
|
/* support stepSize of 0 */
|
||||||
|
size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1;
|
||||||
|
const BYTE* const base = ms->window.base;
|
||||||
|
const BYTE* const istart = (const BYTE*)src;
|
||||||
|
/* We check ip0 (ip + 0) and ip1 (ip + 1) each loop */
|
||||||
|
const BYTE* ip0 = istart;
|
||||||
|
const BYTE* ip1;
|
||||||
|
const BYTE* anchor = istart;
|
||||||
|
const U32 prefixStartIndex = ms->window.dictLimit;
|
||||||
|
const BYTE* const prefixStart = base + prefixStartIndex;
|
||||||
|
const BYTE* const iend = istart + srcSize;
|
||||||
|
const BYTE* const ilimit = iend - HASH_READ_SIZE;
|
||||||
|
U32 offset_1=rep[0], offset_2=rep[1];
|
||||||
|
U32 offsetSaved = 0;
|
||||||
|
|
||||||
|
/* init */
|
||||||
|
ip0 += (ip0 == prefixStart);
|
||||||
|
ip1 = ip0 + 1;
|
||||||
|
{
|
||||||
|
U32 const maxRep = (U32)(ip0 - prefixStart);
|
||||||
|
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
|
||||||
|
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main Search Loop */
|
||||||
|
while (ip1 < ilimit) { /* < instead of <=, because check at ip0+2 */
|
||||||
|
size_t mLength;
|
||||||
|
BYTE const* ip2 = ip0 + 2;
|
||||||
|
size_t const h0 = ZSTD_hashPtr(ip0, hlog, mls);
|
||||||
|
U32 const val0 = MEM_read32(ip0);
|
||||||
|
size_t const h1 = ZSTD_hashPtr(ip1, hlog, mls);
|
||||||
|
U32 const val1 = MEM_read32(ip1);
|
||||||
|
U32 const current0 = (U32)(ip0-base);
|
||||||
|
U32 const current1 = (U32)(ip1-base);
|
||||||
|
U32 const matchIndex0 = hashTable[h0];
|
||||||
|
U32 const matchIndex1 = hashTable[h1];
|
||||||
|
BYTE const* repMatch = ip2-offset_1;
|
||||||
|
const BYTE* match0 = base + matchIndex0;
|
||||||
|
const BYTE* match1 = base + matchIndex1;
|
||||||
|
U32 offcode;
|
||||||
|
hashTable[h0] = current0; /* update hash table */
|
||||||
|
hashTable[h1] = current1; /* update hash table */
|
||||||
|
|
||||||
|
assert(ip0 + 1 == ip1);
|
||||||
|
|
||||||
|
if ((offset_1 > 0) & (MEM_read32(repMatch) == MEM_read32(ip2))) {
|
||||||
|
mLength = ip2[-1] == repMatch[-1] ? 1 : 0;
|
||||||
|
ip0 = ip2 - mLength;
|
||||||
|
match0 = repMatch - mLength;
|
||||||
|
offcode = 0;
|
||||||
|
goto _match;
|
||||||
|
}
|
||||||
|
if ((matchIndex0 > prefixStartIndex) && MEM_read32(match0) == val0) {
|
||||||
|
/* found a regular match */
|
||||||
|
goto _offset;
|
||||||
|
}
|
||||||
|
if ((matchIndex1 > prefixStartIndex) && MEM_read32(match1) == val1) {
|
||||||
|
/* found a regular match after one literal */
|
||||||
|
ip0 = ip1;
|
||||||
|
match0 = match1;
|
||||||
|
goto _offset;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
size_t const step = ((ip0-anchor) >> (kSearchStrength - 1)) + stepSize;
|
||||||
|
assert(step >= 2);
|
||||||
|
ip0 += step;
|
||||||
|
ip1 += step;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_offset: /* Requires: ip0, match0 */
|
||||||
|
/* Compute the offset code */
|
||||||
|
offset_2 = offset_1;
|
||||||
|
offset_1 = (U32)(ip0-match0);
|
||||||
|
offcode = offset_1 + ZSTD_REP_MOVE;
|
||||||
|
mLength = 0;
|
||||||
|
/* Count the backwards match length */
|
||||||
|
while (((ip0>anchor) & (match0>prefixStart))
|
||||||
|
&& (ip0[-1] == match0[-1])) { ip0--; match0--; mLength++; } /* catch up */
|
||||||
|
|
||||||
|
_match: /* Requires: ip0, match0, offcode */
|
||||||
|
/* Count the forward length */
|
||||||
|
mLength += ZSTD_count(ip0+mLength+4, match0+mLength+4, iend) + 4;
|
||||||
|
ZSTD_storeSeq(seqStore, ip0-anchor, anchor, offcode, mLength-MINMATCH);
|
||||||
|
/* match found */
|
||||||
|
ip0 += mLength;
|
||||||
|
anchor = ip0;
|
||||||
|
ip1 = ip0 + 1;
|
||||||
|
|
||||||
|
if (ip0 <= ilimit) {
|
||||||
|
/* Fill Table */
|
||||||
|
assert(base+current0+2 > istart); /* check base overflow */
|
||||||
|
hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */
|
||||||
|
hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);
|
||||||
|
|
||||||
|
while ( (ip0 <= ilimit)
|
||||||
|
&& ( (offset_2>0)
|
||||||
|
& (MEM_read32(ip0) == MEM_read32(ip0 - offset_2)) )) {
|
||||||
|
/* store sequence */
|
||||||
|
size_t const rLength = ZSTD_count(ip0+4, ip0+4-offset_2, iend) + 4;
|
||||||
|
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
|
||||||
|
hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);
|
||||||
|
ip0 += rLength;
|
||||||
|
ip1 = ip0 + 1;
|
||||||
|
ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
|
||||||
|
anchor = ip0;
|
||||||
|
continue; /* faster when present (confirmed on gcc-8) ... (?) */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save reps for next block */
|
||||||
|
rep[0] = offset_1 ? offset_1 : offsetSaved;
|
||||||
|
rep[1] = offset_2 ? offset_2 : offsetSaved;
|
||||||
|
|
||||||
|
/* Return the last literals size */
|
||||||
|
return iend - anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t ZSTD_compressBlock_fast(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize)
|
||||||
|
{
|
||||||
|
ZSTD_compressionParameters const* cParams = &ms->cParams;
|
||||||
|
U32 const mls = cParams->minMatch;
|
||||||
|
assert(ms->dictMatchState == NULL);
|
||||||
|
switch(mls)
|
||||||
|
{
|
||||||
|
default: /* includes case 3 */
|
||||||
|
case 4 :
|
||||||
|
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4);
|
||||||
|
case 5 :
|
||||||
|
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5);
|
||||||
|
case 6 :
|
||||||
|
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6);
|
||||||
|
case 7 :
|
||||||
|
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_TEMPLATE
|
||||||
|
size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize, U32 const mls)
|
||||||
{
|
{
|
||||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||||
U32* const hashTable = ms->hashTable;
|
U32* const hashTable = ms->hashTable;
|
||||||
@ -64,46 +212,26 @@ size_t ZSTD_compressBlock_fast_generic(
|
|||||||
U32 offsetSaved = 0;
|
U32 offsetSaved = 0;
|
||||||
|
|
||||||
const ZSTD_matchState_t* const dms = ms->dictMatchState;
|
const ZSTD_matchState_t* const dms = ms->dictMatchState;
|
||||||
const ZSTD_compressionParameters* const dictCParams =
|
const ZSTD_compressionParameters* const dictCParams = &dms->cParams ;
|
||||||
dictMode == ZSTD_dictMatchState ?
|
const U32* const dictHashTable = dms->hashTable;
|
||||||
&dms->cParams : NULL;
|
const U32 dictStartIndex = dms->window.dictLimit;
|
||||||
const U32* const dictHashTable = dictMode == ZSTD_dictMatchState ?
|
const BYTE* const dictBase = dms->window.base;
|
||||||
dms->hashTable : NULL;
|
const BYTE* const dictStart = dictBase + dictStartIndex;
|
||||||
const U32 dictStartIndex = dictMode == ZSTD_dictMatchState ?
|
const BYTE* const dictEnd = dms->window.nextSrc;
|
||||||
dms->window.dictLimit : 0;
|
const U32 dictIndexDelta = prefixStartIndex - (U32)(dictEnd - dictBase);
|
||||||
const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
|
|
||||||
dms->window.base : NULL;
|
|
||||||
const BYTE* const dictStart = dictMode == ZSTD_dictMatchState ?
|
|
||||||
dictBase + dictStartIndex : NULL;
|
|
||||||
const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
|
|
||||||
dms->window.nextSrc : NULL;
|
|
||||||
const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
|
|
||||||
prefixStartIndex - (U32)(dictEnd - dictBase) :
|
|
||||||
0;
|
|
||||||
const U32 dictAndPrefixLength = (U32)(ip - prefixStart + dictEnd - dictStart);
|
const U32 dictAndPrefixLength = (U32)(ip - prefixStart + dictEnd - dictStart);
|
||||||
const U32 dictHLog = dictMode == ZSTD_dictMatchState ?
|
const U32 dictHLog = dictCParams->hashLog;
|
||||||
dictCParams->hashLog : hlog;
|
|
||||||
|
|
||||||
assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
|
|
||||||
|
|
||||||
/* otherwise, we would get index underflow when translating a dict index
|
/* otherwise, we would get index underflow when translating a dict index
|
||||||
* into a local index */
|
* into a local index */
|
||||||
assert(dictMode != ZSTD_dictMatchState
|
assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
|
||||||
|| prefixStartIndex >= (U32)(dictEnd - dictBase));
|
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
ip += (dictAndPrefixLength == 0);
|
ip += (dictAndPrefixLength == 0);
|
||||||
if (dictMode == ZSTD_noDict) {
|
|
||||||
U32 const maxRep = (U32)(ip - prefixStart);
|
|
||||||
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
|
|
||||||
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
|
|
||||||
}
|
|
||||||
if (dictMode == ZSTD_dictMatchState) {
|
|
||||||
/* dictMatchState repCode checks don't currently handle repCode == 0
|
/* dictMatchState repCode checks don't currently handle repCode == 0
|
||||||
* disabling. */
|
* disabling. */
|
||||||
assert(offset_1 <= dictAndPrefixLength);
|
assert(offset_1 <= dictAndPrefixLength);
|
||||||
assert(offset_2 <= dictAndPrefixLength);
|
assert(offset_2 <= dictAndPrefixLength);
|
||||||
}
|
|
||||||
|
|
||||||
/* Main Search Loop */
|
/* Main Search Loop */
|
||||||
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
|
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
|
||||||
@ -113,26 +241,18 @@ size_t ZSTD_compressBlock_fast_generic(
|
|||||||
U32 const matchIndex = hashTable[h];
|
U32 const matchIndex = hashTable[h];
|
||||||
const BYTE* match = base + matchIndex;
|
const BYTE* match = base + matchIndex;
|
||||||
const U32 repIndex = current + 1 - offset_1;
|
const U32 repIndex = current + 1 - offset_1;
|
||||||
const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
|
const BYTE* repMatch = (repIndex < prefixStartIndex) ?
|
||||||
&& repIndex < prefixStartIndex) ?
|
|
||||||
dictBase + (repIndex - dictIndexDelta) :
|
dictBase + (repIndex - dictIndexDelta) :
|
||||||
base + repIndex;
|
base + repIndex;
|
||||||
hashTable[h] = current; /* update hash table */
|
hashTable[h] = current; /* update hash table */
|
||||||
|
|
||||||
if ( (dictMode == ZSTD_dictMatchState)
|
if ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */
|
||||||
&& ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */
|
|
||||||
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
||||||
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
||||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
||||||
ip++;
|
ip++;
|
||||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
||||||
} else if ( dictMode == ZSTD_noDict
|
|
||||||
&& ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
|
|
||||||
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
|
||||||
ip++;
|
|
||||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
|
||||||
} else if ( (matchIndex <= prefixStartIndex) ) {
|
} else if ( (matchIndex <= prefixStartIndex) ) {
|
||||||
if (dictMode == ZSTD_dictMatchState) {
|
|
||||||
size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls);
|
size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls);
|
||||||
U32 const dictMatchIndex = dictHashTable[dictHash];
|
U32 const dictMatchIndex = dictHashTable[dictHash];
|
||||||
const BYTE* dictMatch = dictBase + dictMatchIndex;
|
const BYTE* dictMatch = dictBase + dictMatchIndex;
|
||||||
@ -153,11 +273,6 @@ size_t ZSTD_compressBlock_fast_generic(
|
|||||||
offset_1 = offset;
|
offset_1 = offset;
|
||||||
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
assert(stepSize >= 1);
|
|
||||||
ip += ((ip-anchor) >> kSearchStrength) + stepSize;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (MEM_read32(match) != MEM_read32(ip)) {
|
} else if (MEM_read32(match) != MEM_read32(ip)) {
|
||||||
/* it's not a match, and we're not going to check the dictionary */
|
/* it's not a match, and we're not going to check the dictionary */
|
||||||
assert(stepSize >= 1);
|
assert(stepSize >= 1);
|
||||||
@ -185,7 +300,6 @@ size_t ZSTD_compressBlock_fast_generic(
|
|||||||
hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base);
|
hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base);
|
||||||
|
|
||||||
/* check immediate repcode */
|
/* check immediate repcode */
|
||||||
if (dictMode == ZSTD_dictMatchState) {
|
|
||||||
while (ip <= ilimit) {
|
while (ip <= ilimit) {
|
||||||
U32 const current2 = (U32)(ip-base);
|
U32 const current2 = (U32)(ip-base);
|
||||||
U32 const repIndex2 = current2 - offset_2;
|
U32 const repIndex2 = current2 - offset_2;
|
||||||
@ -206,20 +320,7 @@ size_t ZSTD_compressBlock_fast_generic(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (dictMode == ZSTD_noDict) {
|
|
||||||
while ( (ip <= ilimit)
|
|
||||||
&& ( (offset_2>0)
|
|
||||||
& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
|
|
||||||
/* store sequence */
|
|
||||||
size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
|
||||||
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
|
|
||||||
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = (U32)(ip-base);
|
|
||||||
ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
|
|
||||||
ip += rLength;
|
|
||||||
anchor = ip;
|
|
||||||
continue; /* faster when present ... (?) */
|
|
||||||
} } } }
|
|
||||||
|
|
||||||
/* save reps for next block */
|
/* save reps for next block */
|
||||||
rep[0] = offset_1 ? offset_1 : offsetSaved;
|
rep[0] = offset_1 ? offset_1 : offsetSaved;
|
||||||
@ -229,28 +330,6 @@ size_t ZSTD_compressBlock_fast_generic(
|
|||||||
return iend - anchor;
|
return iend - anchor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t ZSTD_compressBlock_fast(
|
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
||||||
void const* src, size_t srcSize)
|
|
||||||
{
|
|
||||||
ZSTD_compressionParameters const* cParams = &ms->cParams;
|
|
||||||
U32 const mls = cParams->minMatch;
|
|
||||||
assert(ms->dictMatchState == NULL);
|
|
||||||
switch(mls)
|
|
||||||
{
|
|
||||||
default: /* includes case 3 */
|
|
||||||
case 4 :
|
|
||||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_noDict);
|
|
||||||
case 5 :
|
|
||||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_noDict);
|
|
||||||
case 6 :
|
|
||||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_noDict);
|
|
||||||
case 7 :
|
|
||||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_noDict);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZSTD_compressBlock_fast_dictMatchState(
|
size_t ZSTD_compressBlock_fast_dictMatchState(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
void const* src, size_t srcSize)
|
void const* src, size_t srcSize)
|
||||||
@ -262,13 +341,13 @@ size_t ZSTD_compressBlock_fast_dictMatchState(
|
|||||||
{
|
{
|
||||||
default: /* includes case 3 */
|
default: /* includes case 3 */
|
||||||
case 4 :
|
case 4 :
|
||||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_dictMatchState);
|
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 4);
|
||||||
case 5 :
|
case 5 :
|
||||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_dictMatchState);
|
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 5);
|
||||||
case 6 :
|
case 6 :
|
||||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_dictMatchState);
|
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 6);
|
||||||
case 7 :
|
case 7 :
|
||||||
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_dictMatchState);
|
return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ extern "C" {
|
|||||||
|
|
||||||
U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
|
U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
|
||||||
|
|
||||||
void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). pre-emptively increase value of ZSTD_DUBT_UNSORTED_MARK */
|
void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */
|
||||||
|
|
||||||
size_t ZSTD_compressBlock_btlazy2(
|
size_t ZSTD_compressBlock_btlazy2(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
@ -429,7 +429,7 @@ size_t ZSTD_ldm_generateSequences(
|
|||||||
*/
|
*/
|
||||||
assert(ldmState->window.nextSrc >= (BYTE const*)src + srcSize);
|
assert(ldmState->window.nextSrc >= (BYTE const*)src + srcSize);
|
||||||
/* The input could be very large (in zstdmt), so it must be broken up into
|
/* The input could be very large (in zstdmt), so it must be broken up into
|
||||||
* chunks to enforce the maximmum distance and handle overflow correction.
|
* chunks to enforce the maximum distance and handle overflow correction.
|
||||||
*/
|
*/
|
||||||
assert(sequences->pos <= sequences->size);
|
assert(sequences->pos <= sequences->size);
|
||||||
assert(sequences->size <= sequences->capacity);
|
assert(sequences->size <= sequences->capacity);
|
||||||
|
@ -64,8 +64,14 @@ MEM_STATIC double ZSTD_fCost(U32 price)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int ZSTD_compressedLiterals(optState_t const* const optPtr)
|
||||||
|
{
|
||||||
|
return optPtr->literalCompressionMode != ZSTD_lcm_uncompressed;
|
||||||
|
}
|
||||||
|
|
||||||
static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
|
static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
|
||||||
{
|
{
|
||||||
|
if (ZSTD_compressedLiterals(optPtr))
|
||||||
optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
|
optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
|
||||||
optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);
|
optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);
|
||||||
optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);
|
optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);
|
||||||
@ -99,6 +105,7 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
|||||||
const BYTE* const src, size_t const srcSize,
|
const BYTE* const src, size_t const srcSize,
|
||||||
int const optLevel)
|
int const optLevel)
|
||||||
{
|
{
|
||||||
|
int const compressedLiterals = ZSTD_compressedLiterals(optPtr);
|
||||||
DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize);
|
DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize);
|
||||||
optPtr->priceType = zop_dynamic;
|
optPtr->priceType = zop_dynamic;
|
||||||
|
|
||||||
@ -113,9 +120,10 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
|||||||
/* huffman table presumed generated by dictionary */
|
/* huffman table presumed generated by dictionary */
|
||||||
optPtr->priceType = zop_dynamic;
|
optPtr->priceType = zop_dynamic;
|
||||||
|
|
||||||
|
if (compressedLiterals) {
|
||||||
|
unsigned lit;
|
||||||
assert(optPtr->litFreq != NULL);
|
assert(optPtr->litFreq != NULL);
|
||||||
optPtr->litSum = 0;
|
optPtr->litSum = 0;
|
||||||
{ unsigned lit;
|
|
||||||
for (lit=0; lit<=MaxLit; lit++) {
|
for (lit=0; lit<=MaxLit; lit++) {
|
||||||
U32 const scaleLog = 11; /* scale to 2K */
|
U32 const scaleLog = 11; /* scale to 2K */
|
||||||
U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit);
|
U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit);
|
||||||
@ -163,10 +171,11 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
|||||||
} else { /* not a dictionary */
|
} else { /* not a dictionary */
|
||||||
|
|
||||||
assert(optPtr->litFreq != NULL);
|
assert(optPtr->litFreq != NULL);
|
||||||
{ unsigned lit = MaxLit;
|
if (compressedLiterals) {
|
||||||
|
unsigned lit = MaxLit;
|
||||||
HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
|
HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
|
||||||
}
|
|
||||||
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
||||||
|
}
|
||||||
|
|
||||||
{ unsigned ll;
|
{ unsigned ll;
|
||||||
for (ll=0; ll<=MaxLL; ll++)
|
for (ll=0; ll<=MaxLL; ll++)
|
||||||
@ -190,6 +199,7 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
|||||||
|
|
||||||
} else { /* new block : re-use previous statistics, scaled down */
|
} else { /* new block : re-use previous statistics, scaled down */
|
||||||
|
|
||||||
|
if (compressedLiterals)
|
||||||
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
||||||
optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0);
|
optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0);
|
||||||
optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0);
|
optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0);
|
||||||
@ -207,6 +217,10 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
|
|||||||
int optLevel)
|
int optLevel)
|
||||||
{
|
{
|
||||||
if (litLength == 0) return 0;
|
if (litLength == 0) return 0;
|
||||||
|
|
||||||
|
if (!ZSTD_compressedLiterals(optPtr))
|
||||||
|
return (litLength << 3) * BITCOST_MULTIPLIER; /* Uncompressed - 8 bytes per literal. */
|
||||||
|
|
||||||
if (optPtr->priceType == zop_predef)
|
if (optPtr->priceType == zop_predef)
|
||||||
return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */
|
return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */
|
||||||
|
|
||||||
@ -310,7 +324,8 @@ static void ZSTD_updateStats(optState_t* const optPtr,
|
|||||||
U32 offsetCode, U32 matchLength)
|
U32 offsetCode, U32 matchLength)
|
||||||
{
|
{
|
||||||
/* literals */
|
/* literals */
|
||||||
{ U32 u;
|
if (ZSTD_compressedLiterals(optPtr)) {
|
||||||
|
U32 u;
|
||||||
for (u=0; u < litLength; u++)
|
for (u=0; u < litLength; u++)
|
||||||
optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
|
optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
|
||||||
optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
|
optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
|
||||||
@ -870,7 +885,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|||||||
/* large match -> immediate encoding */
|
/* large match -> immediate encoding */
|
||||||
{ U32 const maxML = matches[nbMatches-1].len;
|
{ U32 const maxML = matches[nbMatches-1].len;
|
||||||
U32 const maxOffset = matches[nbMatches-1].off;
|
U32 const maxOffset = matches[nbMatches-1].off;
|
||||||
DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new serie",
|
DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
|
||||||
nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
|
nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
|
||||||
|
|
||||||
if (maxML > sufficient_len) {
|
if (maxML > sufficient_len) {
|
||||||
@ -1108,6 +1123,7 @@ static U32 ZSTD_upscaleStat(unsigned* table, U32 lastEltIndex, int bonus)
|
|||||||
/* used in 2-pass strategy */
|
/* used in 2-pass strategy */
|
||||||
MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
|
MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
|
||||||
{
|
{
|
||||||
|
if (ZSTD_compressedLiterals(optPtr))
|
||||||
optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
|
optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
|
||||||
optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0);
|
optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0);
|
||||||
optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0);
|
optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0);
|
||||||
@ -1117,7 +1133,7 @@ MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
|
|||||||
/* ZSTD_initStats_ultra():
|
/* ZSTD_initStats_ultra():
|
||||||
* make a first compression pass, just to seed stats with more accurate starting values.
|
* 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.
|
* only works on first block, with no dictionary and no ldm.
|
||||||
* this function cannot error, hence its constract must be respected.
|
* this function cannot error, hence its contract must be respected.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
/* ====== Dependencies ====== */
|
/* ====== Dependencies ====== */
|
||||||
#include <string.h> /* memcpy, memset */
|
#include <string.h> /* memcpy, memset */
|
||||||
#include <limits.h> /* INT_MAX, UINT_MAX */
|
#include <limits.h> /* INT_MAX, UINT_MAX */
|
||||||
|
#include "mem.h" /* MEM_STATIC */
|
||||||
#include "pool.h" /* threadpool */
|
#include "pool.h" /* threadpool */
|
||||||
#include "threading.h" /* mutex */
|
#include "threading.h" /* mutex */
|
||||||
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
||||||
@ -456,7 +457,7 @@ typedef struct {
|
|||||||
* Must be acquired after the main mutex when acquiring both.
|
* Must be acquired after the main mutex when acquiring both.
|
||||||
*/
|
*/
|
||||||
ZSTD_pthread_mutex_t ldmWindowMutex;
|
ZSTD_pthread_mutex_t ldmWindowMutex;
|
||||||
ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is udpated */
|
ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is updated */
|
||||||
ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */
|
ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */
|
||||||
} serialState_t;
|
} serialState_t;
|
||||||
|
|
||||||
@ -647,7 +648,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
|||||||
buffer_t dstBuff = job->dstBuff;
|
buffer_t dstBuff = job->dstBuff;
|
||||||
size_t lastCBlockSize = 0;
|
size_t lastCBlockSize = 0;
|
||||||
|
|
||||||
/* ressources */
|
/* resources */
|
||||||
if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation));
|
if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation));
|
||||||
if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */
|
if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */
|
||||||
dstBuff = ZSTDMT_getBuffer(job->bufPool);
|
dstBuff = ZSTDMT_getBuffer(job->bufPool);
|
||||||
@ -672,7 +673,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
|||||||
if (ZSTD_isError(initError)) JOB_ERROR(initError);
|
if (ZSTD_isError(initError)) JOB_ERROR(initError);
|
||||||
} else { /* srcStart points at reloaded section */
|
} else { /* srcStart points at reloaded section */
|
||||||
U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
|
U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
|
||||||
{ size_t const forceWindowError = ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
|
{ size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
|
||||||
if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
|
if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
|
||||||
}
|
}
|
||||||
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
|
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
|
||||||
@ -864,14 +865,10 @@ static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {
|
|||||||
* Internal use only */
|
* Internal use only */
|
||||||
size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
|
size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
|
||||||
{
|
{
|
||||||
if (nbWorkers > ZSTDMT_NBWORKERS_MAX) nbWorkers = ZSTDMT_NBWORKERS_MAX;
|
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);
|
||||||
params->nbWorkers = nbWorkers;
|
|
||||||
params->overlapLog = ZSTDMT_OVERLAPLOG_DEFAULT;
|
|
||||||
params->jobSize = 0;
|
|
||||||
return nbWorkers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
|
MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem)
|
||||||
{
|
{
|
||||||
ZSTDMT_CCtx* mtctx;
|
ZSTDMT_CCtx* mtctx;
|
||||||
U32 nbJobs = nbWorkers + 2;
|
U32 nbJobs = nbWorkers + 2;
|
||||||
@ -906,6 +903,17 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
|
|||||||
return mtctx;
|
return mtctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
|
||||||
|
{
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem);
|
||||||
|
#else
|
||||||
|
(void)nbWorkers;
|
||||||
|
(void)cMem;
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
|
ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
|
||||||
{
|
{
|
||||||
return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
|
return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
|
||||||
@ -986,26 +994,13 @@ ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
|
|||||||
{
|
{
|
||||||
case ZSTDMT_p_jobSize :
|
case ZSTDMT_p_jobSize :
|
||||||
DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value);
|
DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value);
|
||||||
if ( value != 0 /* default */
|
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value);
|
||||||
&& value < ZSTDMT_JOBSIZE_MIN)
|
|
||||||
value = ZSTDMT_JOBSIZE_MIN;
|
|
||||||
assert(value >= 0);
|
|
||||||
if (value > ZSTDMT_JOBSIZE_MAX) value = ZSTDMT_JOBSIZE_MAX;
|
|
||||||
params->jobSize = value;
|
|
||||||
return value;
|
|
||||||
|
|
||||||
case ZSTDMT_p_overlapLog :
|
case ZSTDMT_p_overlapLog :
|
||||||
DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value);
|
DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value);
|
||||||
if (value < ZSTD_OVERLAPLOG_MIN) value = ZSTD_OVERLAPLOG_MIN;
|
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value);
|
||||||
if (value > ZSTD_OVERLAPLOG_MAX) value = ZSTD_OVERLAPLOG_MAX;
|
|
||||||
params->overlapLog = value;
|
|
||||||
return value;
|
|
||||||
|
|
||||||
case ZSTDMT_p_rsyncable :
|
case ZSTDMT_p_rsyncable :
|
||||||
value = (value != 0);
|
DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value);
|
||||||
params->rsyncable = value;
|
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value);
|
||||||
return value;
|
|
||||||
|
|
||||||
default :
|
default :
|
||||||
return ERROR(parameter_unsupported);
|
return ERROR(parameter_unsupported);
|
||||||
}
|
}
|
||||||
@ -1021,32 +1016,29 @@ size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter,
|
|||||||
{
|
{
|
||||||
switch (parameter) {
|
switch (parameter) {
|
||||||
case ZSTDMT_p_jobSize:
|
case ZSTDMT_p_jobSize:
|
||||||
assert(mtctx->params.jobSize <= INT_MAX);
|
return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value);
|
||||||
*value = (int)(mtctx->params.jobSize);
|
|
||||||
break;
|
|
||||||
case ZSTDMT_p_overlapLog:
|
case ZSTDMT_p_overlapLog:
|
||||||
*value = mtctx->params.overlapLog;
|
return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value);
|
||||||
break;
|
|
||||||
case ZSTDMT_p_rsyncable:
|
case ZSTDMT_p_rsyncable:
|
||||||
*value = mtctx->params.rsyncable;
|
return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value);
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return ERROR(parameter_unsupported);
|
return ERROR(parameter_unsupported);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets parameters relevant to the compression job,
|
/* Sets parameters relevant to the compression job,
|
||||||
* initializing others to default values. */
|
* initializing others to default values. */
|
||||||
static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
|
static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
|
||||||
{
|
{
|
||||||
ZSTD_CCtx_params jobParams;
|
ZSTD_CCtx_params jobParams = params;
|
||||||
memset(&jobParams, 0, sizeof(jobParams));
|
/* Clear parameters related to multithreading */
|
||||||
|
jobParams.forceWindow = 0;
|
||||||
jobParams.cParams = params.cParams;
|
jobParams.nbWorkers = 0;
|
||||||
jobParams.fParams = params.fParams;
|
jobParams.jobSize = 0;
|
||||||
jobParams.compressionLevel = params.compressionLevel;
|
jobParams.overlapLog = 0;
|
||||||
|
jobParams.rsyncable = 0;
|
||||||
|
memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t));
|
||||||
|
memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem));
|
||||||
return jobParams;
|
return jobParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1056,7 +1048,7 @@ static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
|
|||||||
static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
|
static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
|
||||||
{
|
{
|
||||||
if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);
|
if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);
|
||||||
CHECK_F( ZSTDMT_expandJobsTable(mtctx, nbWorkers) );
|
FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) );
|
||||||
mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers);
|
mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers);
|
||||||
if (mtctx->bufPool == NULL) return ERROR(memory_allocation);
|
if (mtctx->bufPool == NULL) return ERROR(memory_allocation);
|
||||||
mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);
|
mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);
|
||||||
@ -1263,7 +1255,7 @@ static size_t ZSTDMT_compress_advanced_internal(
|
|||||||
if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize))
|
if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize))
|
||||||
return ERROR(memory_allocation);
|
return ERROR(memory_allocation);
|
||||||
|
|
||||||
CHECK_F( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */
|
FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */
|
||||||
|
|
||||||
{ unsigned u;
|
{ unsigned u;
|
||||||
for (u=0; u<nbJobs; u++) {
|
for (u=0; u<nbJobs; u++) {
|
||||||
@ -1396,7 +1388,7 @@ size_t ZSTDMT_initCStream_internal(
|
|||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
if (params.nbWorkers != mtctx->params.nbWorkers)
|
if (params.nbWorkers != mtctx->params.nbWorkers)
|
||||||
CHECK_F( ZSTDMT_resize(mtctx, params.nbWorkers) );
|
FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) );
|
||||||
|
|
||||||
if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
|
if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
|
||||||
if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX;
|
if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX;
|
||||||
@ -1547,7 +1539,7 @@ size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) {
|
|||||||
/* ZSTDMT_writeLastEmptyBlock()
|
/* ZSTDMT_writeLastEmptyBlock()
|
||||||
* Write a single empty block with an end-of-frame to finish a frame.
|
* Write a single empty block with an end-of-frame to finish a frame.
|
||||||
* Job must be created from streaming variant.
|
* Job must be created from streaming variant.
|
||||||
* This function is always successfull if expected conditions are fulfilled.
|
* This function is always successful if expected conditions are fulfilled.
|
||||||
*/
|
*/
|
||||||
static void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job)
|
static void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job)
|
||||||
{
|
{
|
||||||
@ -1987,7 +1979,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|||||||
assert(input->pos <= input->size);
|
assert(input->pos <= input->size);
|
||||||
|
|
||||||
if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
|
if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
|
||||||
return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp);
|
return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
|
if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
|
||||||
@ -2051,7 +2043,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|||||||
|| ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */
|
|| ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */
|
||||||
size_t const jobSize = mtctx->inBuff.filled;
|
size_t const jobSize = mtctx->inBuff.filled;
|
||||||
assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);
|
assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);
|
||||||
CHECK_F( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
|
FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for potential compressed data ready to be flushed */
|
/* check for potential compressed data ready to be flushed */
|
||||||
@ -2065,7 +2057,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|||||||
|
|
||||||
size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
||||||
{
|
{
|
||||||
CHECK_F( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
|
FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
|
||||||
|
|
||||||
/* recommended next input size : fill current input buffer */
|
/* recommended next input size : fill current input buffer */
|
||||||
return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
|
return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
|
||||||
@ -2082,7 +2074,7 @@ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* ou
|
|||||||
|| ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
|
|| ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
|
||||||
DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
|
DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
|
||||||
(U32)srcSize, (U32)endFrame);
|
(U32)srcSize, (U32)endFrame);
|
||||||
CHECK_F( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
|
FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if there is any data available to flush */
|
/* check if there is any data available to flush */
|
||||||
|
@ -17,10 +17,25 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Note : This is an internal API.
|
/* Note : This is an internal API.
|
||||||
* Some methods are still exposed (ZSTDLIB_API),
|
* These APIs used to be exposed with ZSTDLIB_API,
|
||||||
* because it used to be the only way to invoke MT compression.
|
* because it used to be the only way to invoke MT compression.
|
||||||
* Now, it's recommended to use ZSTD_compress_generic() instead.
|
* Now, it's recommended to use ZSTD_compress2 and ZSTD_compressStream2()
|
||||||
* These methods will stop being exposed in a future version */
|
* instead.
|
||||||
|
*
|
||||||
|
* If you depend on these APIs and can't switch, then define
|
||||||
|
* ZSTD_LEGACY_MULTITHREADED_API when making the dynamic library.
|
||||||
|
* However, we may completely remove these functions in a future
|
||||||
|
* release, so please switch soon.
|
||||||
|
*
|
||||||
|
* This API requires ZSTD_MULTITHREAD to be defined during compilation,
|
||||||
|
* otherwise ZSTDMT_createCCtx*() will fail.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef ZSTD_LEGACY_MULTITHREADED_API
|
||||||
|
# define ZSTDMT_API ZSTDLIB_API
|
||||||
|
#else
|
||||||
|
# define ZSTDMT_API
|
||||||
|
#endif
|
||||||
|
|
||||||
/* === Dependencies === */
|
/* === Dependencies === */
|
||||||
#include <stddef.h> /* size_t */
|
#include <stddef.h> /* size_t */
|
||||||
@ -40,17 +55,19 @@
|
|||||||
|
|
||||||
/* === Memory management === */
|
/* === Memory management === */
|
||||||
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
|
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
|
||||||
ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
|
/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
|
||||||
ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
|
ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
|
||||||
|
/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
|
||||||
|
ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
|
||||||
ZSTD_customMem cMem);
|
ZSTD_customMem cMem);
|
||||||
ZSTDLIB_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
|
ZSTDMT_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
|
||||||
|
|
||||||
ZSTDLIB_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
|
ZSTDMT_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
|
||||||
|
|
||||||
|
|
||||||
/* === Simple one-pass compression function === */
|
/* === Simple one-pass compression function === */
|
||||||
|
|
||||||
ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
ZSTDMT_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||||
void* dst, size_t dstCapacity,
|
void* dst, size_t dstCapacity,
|
||||||
const void* src, size_t srcSize,
|
const void* src, size_t srcSize,
|
||||||
int compressionLevel);
|
int compressionLevel);
|
||||||
@ -59,31 +76,31 @@ ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
|||||||
|
|
||||||
/* === Streaming functions === */
|
/* === Streaming functions === */
|
||||||
|
|
||||||
ZSTDLIB_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
|
ZSTDMT_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
|
||||||
ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
|
ZSTDMT_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
|
||||||
|
|
||||||
ZSTDLIB_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
|
ZSTDMT_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
|
||||||
ZSTDLIB_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
ZSTDMT_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||||
|
|
||||||
ZSTDLIB_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
ZSTDMT_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
||||||
ZSTDLIB_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
ZSTDMT_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
||||||
|
|
||||||
|
|
||||||
/* === Advanced functions and parameters === */
|
/* === Advanced functions and parameters === */
|
||||||
|
|
||||||
ZSTDLIB_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
|
ZSTDMT_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
|
||||||
void* dst, size_t dstCapacity,
|
void* dst, size_t dstCapacity,
|
||||||
const void* src, size_t srcSize,
|
const void* src, size_t srcSize,
|
||||||
const ZSTD_CDict* cdict,
|
const ZSTD_CDict* cdict,
|
||||||
ZSTD_parameters params,
|
ZSTD_parameters params,
|
||||||
int overlapLog);
|
int overlapLog);
|
||||||
|
|
||||||
ZSTDLIB_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
|
ZSTDMT_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
|
||||||
const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */
|
const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */
|
||||||
ZSTD_parameters params,
|
ZSTD_parameters params,
|
||||||
unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */
|
unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */
|
||||||
|
|
||||||
ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
ZSTDMT_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
||||||
const ZSTD_CDict* cdict,
|
const ZSTD_CDict* cdict,
|
||||||
ZSTD_frameParameters fparams,
|
ZSTD_frameParameters fparams,
|
||||||
unsigned long long pledgedSrcSize); /* note : zero means empty */
|
unsigned long long pledgedSrcSize); /* note : zero means empty */
|
||||||
@ -92,7 +109,7 @@ ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
|||||||
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
|
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
|
ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
|
||||||
ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compressionr ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
|
ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compression ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
|
||||||
ZSTDMT_p_rsyncable /* Enables rsyncable mode. */
|
ZSTDMT_p_rsyncable /* Enables rsyncable mode. */
|
||||||
} ZSTDMT_parameter;
|
} ZSTDMT_parameter;
|
||||||
|
|
||||||
@ -101,12 +118,12 @@ typedef enum {
|
|||||||
* The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__
|
* The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__
|
||||||
* Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
|
* Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
|
||||||
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
||||||
ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
|
ZSTDMT_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
|
||||||
|
|
||||||
/* ZSTDMT_getMTCtxParameter() :
|
/* ZSTDMT_getMTCtxParameter() :
|
||||||
* Query the ZSTDMT_CCtx for a parameter value.
|
* Query the ZSTDMT_CCtx for a parameter value.
|
||||||
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
||||||
ZSTDLIB_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
|
ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
|
||||||
|
|
||||||
|
|
||||||
/*! ZSTDMT_compressStream_generic() :
|
/*! ZSTDMT_compressStream_generic() :
|
||||||
@ -116,7 +133,7 @@ ZSTDLIB_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter
|
|||||||
* 0 if fully flushed
|
* 0 if fully flushed
|
||||||
* or an error code
|
* or an error code
|
||||||
* note : needs to be init using any ZSTD_initCStream*() variant */
|
* note : needs to be init using any ZSTD_initCStream*() variant */
|
||||||
ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
||||||
ZSTD_outBuffer* output,
|
ZSTD_outBuffer* output,
|
||||||
ZSTD_inBuffer* input,
|
ZSTD_inBuffer* input,
|
||||||
ZSTD_EndDirective endOp);
|
ZSTD_EndDirective endOp);
|
||||||
|
@ -105,8 +105,8 @@ ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
|
|||||||
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
|
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
|
||||||
|
|
||||||
/* load entropy tables */
|
/* load entropy tables */
|
||||||
CHECK_E( ZSTD_loadDEntropy(&ddict->entropy,
|
RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
|
||||||
ddict->dictContent, ddict->dictSize),
|
&ddict->entropy, ddict->dictContent, ddict->dictSize)),
|
||||||
dictionary_corrupted);
|
dictionary_corrupted);
|
||||||
ddict->entropyPresent = 1;
|
ddict->entropyPresent = 1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -133,7 +133,7 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
|
|||||||
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
||||||
|
|
||||||
/* parse dictionary content */
|
/* parse dictionary content */
|
||||||
CHECK_F( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
|
FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|||||||
dctx->ddictLocal = NULL;
|
dctx->ddictLocal = NULL;
|
||||||
dctx->dictEnd = NULL;
|
dctx->dictEnd = NULL;
|
||||||
dctx->ddictIsCold = 0;
|
dctx->ddictIsCold = 0;
|
||||||
|
dctx->dictUses = ZSTD_dont_use;
|
||||||
dctx->inBuff = NULL;
|
dctx->inBuff = NULL;
|
||||||
dctx->inBuffSize = 0;
|
dctx->inBuffSize = 0;
|
||||||
dctx->outBuffSize = 0;
|
dctx->outBuffSize = 0;
|
||||||
@ -147,13 +148,20 @@ ZSTD_DCtx* ZSTD_createDCtx(void)
|
|||||||
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
|
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
|
||||||
|
{
|
||||||
|
ZSTD_freeDDict(dctx->ddictLocal);
|
||||||
|
dctx->ddictLocal = NULL;
|
||||||
|
dctx->ddict = NULL;
|
||||||
|
dctx->dictUses = ZSTD_dont_use;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
||||||
{
|
{
|
||||||
if (dctx==NULL) return 0; /* support free on NULL */
|
if (dctx==NULL) return 0; /* support free on NULL */
|
||||||
if (dctx->staticSize) return ERROR(memory_allocation); /* not compatible with static DCtx */
|
RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
|
||||||
{ ZSTD_customMem const cMem = dctx->customMem;
|
{ ZSTD_customMem const cMem = dctx->customMem;
|
||||||
ZSTD_freeDDict(dctx->ddictLocal);
|
ZSTD_clearDict(dctx);
|
||||||
dctx->ddictLocal = NULL;
|
|
||||||
ZSTD_free(dctx->inBuff, cMem);
|
ZSTD_free(dctx->inBuff, cMem);
|
||||||
dctx->inBuff = NULL;
|
dctx->inBuff = NULL;
|
||||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||||
@ -203,7 +211,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|||||||
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
|
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
|
||||||
{
|
{
|
||||||
size_t const minInputSize = ZSTD_startingInputLength(format);
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
||||||
if (srcSize < minInputSize) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
|
||||||
|
|
||||||
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
|
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
|
||||||
U32 const dictID= fhd & 3;
|
U32 const dictID= fhd & 3;
|
||||||
@ -238,7 +246,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|||||||
|
|
||||||
memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
|
memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
|
||||||
if (srcSize < minInputSize) return minInputSize;
|
if (srcSize < minInputSize) return minInputSize;
|
||||||
if (src==NULL) return ERROR(GENERIC); /* invalid parameter */
|
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
|
||||||
|
|
||||||
if ( (format != ZSTD_f_zstd1_magicless)
|
if ( (format != ZSTD_f_zstd1_magicless)
|
||||||
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
||||||
@ -251,7 +259,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|||||||
zfhPtr->frameType = ZSTD_skippableFrame;
|
zfhPtr->frameType = ZSTD_skippableFrame;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return ERROR(prefix_unknown);
|
RETURN_ERROR(prefix_unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ensure there is enough `srcSize` to fully read/decode frame header */
|
/* ensure there is enough `srcSize` to fully read/decode frame header */
|
||||||
@ -269,14 +277,13 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|||||||
U64 windowSize = 0;
|
U64 windowSize = 0;
|
||||||
U32 dictID = 0;
|
U32 dictID = 0;
|
||||||
U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
||||||
if ((fhdByte & 0x08) != 0)
|
RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
|
||||||
return ERROR(frameParameter_unsupported); /* reserved bits, must be zero */
|
"reserved bits, must be zero");
|
||||||
|
|
||||||
if (!singleSegment) {
|
if (!singleSegment) {
|
||||||
BYTE const wlByte = ip[pos++];
|
BYTE const wlByte = ip[pos++];
|
||||||
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
||||||
if (windowLog > ZSTD_WINDOWLOG_MAX)
|
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
|
||||||
return ERROR(frameParameter_windowTooLarge);
|
|
||||||
windowSize = (1ULL << windowLog);
|
windowSize = (1ULL << windowLog);
|
||||||
windowSize += (windowSize >> 3) * (wlByte&7);
|
windowSize += (windowSize >> 3) * (wlByte&7);
|
||||||
}
|
}
|
||||||
@ -348,12 +355,11 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|||||||
size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
|
size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
|
||||||
U32 sizeU32;
|
U32 sizeU32;
|
||||||
|
|
||||||
if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
|
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
|
||||||
return ERROR(srcSize_wrong);
|
|
||||||
|
|
||||||
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
||||||
if ((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32)
|
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
||||||
return ERROR(frameParameter_unsupported);
|
frameParameter_unsupported);
|
||||||
|
|
||||||
return skippableHeaderSize + sizeU32;
|
return skippableHeaderSize + sizeU32;
|
||||||
}
|
}
|
||||||
@ -428,13 +434,89 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
|||||||
{
|
{
|
||||||
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
||||||
if (ZSTD_isError(result)) return result; /* invalid header */
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
||||||
if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */
|
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
||||||
if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
|
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||||
return ERROR(dictionary_wrong);
|
/* Skip the dictID check in fuzzing mode, because it makes the search
|
||||||
|
* harder.
|
||||||
|
*/
|
||||||
|
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
||||||
|
dictionary_wrong);
|
||||||
|
#endif
|
||||||
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
|
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
||||||
|
{
|
||||||
|
ZSTD_frameSizeInfo frameSizeInfo;
|
||||||
|
frameSizeInfo.compressedSize = ret;
|
||||||
|
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
return frameSizeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
||||||
|
{
|
||||||
|
ZSTD_frameSizeInfo frameSizeInfo;
|
||||||
|
memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
||||||
|
|
||||||
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||||
|
if (ZSTD_isLegacy(src, srcSize))
|
||||||
|
return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
||||||
|
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||||
|
frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
|
||||||
|
return frameSizeInfo;
|
||||||
|
} else {
|
||||||
|
const BYTE* ip = (const BYTE*)src;
|
||||||
|
const BYTE* const ipstart = ip;
|
||||||
|
size_t remainingSize = srcSize;
|
||||||
|
size_t nbBlocks = 0;
|
||||||
|
ZSTD_frameHeader zfh;
|
||||||
|
|
||||||
|
/* Extract Frame Header */
|
||||||
|
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
||||||
|
if (ZSTD_isError(ret))
|
||||||
|
return ZSTD_errorFrameSizeInfo(ret);
|
||||||
|
if (ret > 0)
|
||||||
|
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
||||||
|
}
|
||||||
|
|
||||||
|
ip += zfh.headerSize;
|
||||||
|
remainingSize -= zfh.headerSize;
|
||||||
|
|
||||||
|
/* Iterate over each block */
|
||||||
|
while (1) {
|
||||||
|
blockProperties_t blockProperties;
|
||||||
|
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||||
|
if (ZSTD_isError(cBlockSize))
|
||||||
|
return ZSTD_errorFrameSizeInfo(cBlockSize);
|
||||||
|
|
||||||
|
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
|
||||||
|
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
||||||
|
|
||||||
|
ip += ZSTD_blockHeaderSize + cBlockSize;
|
||||||
|
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
|
||||||
|
nbBlocks++;
|
||||||
|
|
||||||
|
if (blockProperties.lastBlock) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Final frame content checksum */
|
||||||
|
if (zfh.checksumFlag) {
|
||||||
|
if (remainingSize < 4)
|
||||||
|
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
||||||
|
ip += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
frameSizeInfo.compressedSize = ip - ipstart;
|
||||||
|
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
||||||
|
? zfh.frameContentSize
|
||||||
|
: nbBlocks * zfh.blockSizeMax;
|
||||||
|
return frameSizeInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** ZSTD_findFrameCompressedSize() :
|
/** ZSTD_findFrameCompressedSize() :
|
||||||
* compatible with legacy mode
|
* compatible with legacy mode
|
||||||
@ -443,53 +525,34 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
|||||||
* @return : the compressed size of the frame starting at `src` */
|
* @return : the compressed size of the frame starting at `src` */
|
||||||
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
||||||
{
|
{
|
||||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
||||||
if (ZSTD_isLegacy(src, srcSize))
|
return frameSizeInfo.compressedSize;
|
||||||
return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
|
||||||
#endif
|
|
||||||
if ( (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
|
||||||
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START ) {
|
|
||||||
return readSkippableFrameSize(src, srcSize);
|
|
||||||
} else {
|
|
||||||
const BYTE* ip = (const BYTE*)src;
|
|
||||||
const BYTE* const ipstart = ip;
|
|
||||||
size_t remainingSize = srcSize;
|
|
||||||
ZSTD_frameHeader zfh;
|
|
||||||
|
|
||||||
/* Extract Frame Header */
|
|
||||||
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
||||||
if (ZSTD_isError(ret)) return ret;
|
|
||||||
if (ret > 0) return ERROR(srcSize_wrong);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ip += zfh.headerSize;
|
|
||||||
remainingSize -= zfh.headerSize;
|
|
||||||
|
|
||||||
/* Loop on each block */
|
/** ZSTD_decompressBound() :
|
||||||
while (1) {
|
* compatible with legacy mode
|
||||||
blockProperties_t blockProperties;
|
* `src` must point to the start of a ZSTD frame or a skippeable frame
|
||||||
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
* `srcSize` must be at least as large as the frame contained
|
||||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
* @return : the maximum decompressed size of the compressed source
|
||||||
|
*/
|
||||||
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
|
unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
||||||
return ERROR(srcSize_wrong);
|
{
|
||||||
|
unsigned long long bound = 0;
|
||||||
ip += ZSTD_blockHeaderSize + cBlockSize;
|
/* Iterate over each frame */
|
||||||
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
|
while (srcSize > 0) {
|
||||||
|
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
||||||
if (blockProperties.lastBlock) break;
|
size_t const compressedSize = frameSizeInfo.compressedSize;
|
||||||
|
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
||||||
|
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
||||||
|
return ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
src = (const BYTE*)src + compressedSize;
|
||||||
|
srcSize -= compressedSize;
|
||||||
|
bound += decompressedBound;
|
||||||
}
|
}
|
||||||
|
return bound;
|
||||||
if (zfh.checksumFlag) { /* Final frame content checksum */
|
|
||||||
if (remainingSize < 4) return ERROR(srcSize_wrong);
|
|
||||||
ip += 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip - ipstart;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************************************
|
/*-*************************************************************
|
||||||
* Frame decoding
|
* Frame decoding
|
||||||
@ -522,9 +585,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|||||||
DEBUGLOG(5, "ZSTD_copyRawBlock");
|
DEBUGLOG(5, "ZSTD_copyRawBlock");
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
if (srcSize == 0) return 0;
|
if (srcSize == 0) return 0;
|
||||||
return ERROR(dstBuffer_null);
|
RETURN_ERROR(dstBuffer_null);
|
||||||
}
|
}
|
||||||
if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall);
|
||||||
memcpy(dst, src, srcSize);
|
memcpy(dst, src, srcSize);
|
||||||
return srcSize;
|
return srcSize;
|
||||||
}
|
}
|
||||||
@ -535,9 +598,9 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|||||||
{
|
{
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
if (regenSize == 0) return 0;
|
if (regenSize == 0) return 0;
|
||||||
return ERROR(dstBuffer_null);
|
RETURN_ERROR(dstBuffer_null);
|
||||||
}
|
}
|
||||||
if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall);
|
||||||
memset(dst, b, regenSize);
|
memset(dst, b, regenSize);
|
||||||
return regenSize;
|
return regenSize;
|
||||||
}
|
}
|
||||||
@ -560,15 +623,16 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|||||||
DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
|
DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
|
||||||
|
|
||||||
/* check */
|
/* check */
|
||||||
if (remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize)
|
RETURN_ERROR_IF(
|
||||||
return ERROR(srcSize_wrong);
|
remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize,
|
||||||
|
srcSize_wrong);
|
||||||
|
|
||||||
/* Frame Header */
|
/* Frame Header */
|
||||||
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_FRAMEHEADERSIZE_PREFIX);
|
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_FRAMEHEADERSIZE_PREFIX);
|
||||||
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
||||||
if (remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize)
|
RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
|
||||||
return ERROR(srcSize_wrong);
|
srcSize_wrong);
|
||||||
CHECK_F( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
|
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
|
||||||
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
|
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,7 +645,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|||||||
|
|
||||||
ip += ZSTD_blockHeaderSize;
|
ip += ZSTD_blockHeaderSize;
|
||||||
remainingSrcSize -= ZSTD_blockHeaderSize;
|
remainingSrcSize -= ZSTD_blockHeaderSize;
|
||||||
if (cBlockSize > remainingSrcSize) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
|
||||||
|
|
||||||
switch(blockProperties.blockType)
|
switch(blockProperties.blockType)
|
||||||
{
|
{
|
||||||
@ -596,7 +660,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|||||||
break;
|
break;
|
||||||
case bt_reserved :
|
case bt_reserved :
|
||||||
default:
|
default:
|
||||||
return ERROR(corruption_detected);
|
RETURN_ERROR(corruption_detected);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||||
@ -609,15 +673,15 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
||||||
if ((U64)(op-ostart) != dctx->fParams.frameContentSize) {
|
RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
|
||||||
return ERROR(corruption_detected);
|
corruption_detected);
|
||||||
} }
|
}
|
||||||
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
||||||
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
||||||
U32 checkRead;
|
U32 checkRead;
|
||||||
if (remainingSrcSize<4) return ERROR(checksum_wrong);
|
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong);
|
||||||
checkRead = MEM_readLE32(ip);
|
checkRead = MEM_readLE32(ip);
|
||||||
if (checkRead != checkCalc) return ERROR(checksum_wrong);
|
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong);
|
||||||
ip += 4;
|
ip += 4;
|
||||||
remainingSrcSize -= 4;
|
remainingSrcSize -= 4;
|
||||||
}
|
}
|
||||||
@ -652,8 +716,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|||||||
size_t decodedSize;
|
size_t decodedSize;
|
||||||
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
||||||
if (ZSTD_isError(frameSize)) return frameSize;
|
if (ZSTD_isError(frameSize)) return frameSize;
|
||||||
/* legacy support is not compatible with static dctx */
|
RETURN_ERROR_IF(dctx->staticSize, memory_allocation,
|
||||||
if (dctx->staticSize) return ERROR(memory_allocation);
|
"legacy support is not compatible with static dctx");
|
||||||
|
|
||||||
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
||||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||||
@ -676,7 +740,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|||||||
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
||||||
if (ZSTD_isError(skippableSize))
|
if (ZSTD_isError(skippableSize))
|
||||||
return skippableSize;
|
return skippableSize;
|
||||||
if (srcSize < skippableSize) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(srcSize < skippableSize, srcSize_wrong);
|
||||||
|
|
||||||
src = (const BYTE *)src + skippableSize;
|
src = (const BYTE *)src + skippableSize;
|
||||||
srcSize -= skippableSize;
|
srcSize -= skippableSize;
|
||||||
@ -685,29 +749,29 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|||||||
|
|
||||||
if (ddict) {
|
if (ddict) {
|
||||||
/* we were called from ZSTD_decompress_usingDDict */
|
/* we were called from ZSTD_decompress_usingDDict */
|
||||||
CHECK_F(ZSTD_decompressBegin_usingDDict(dctx, ddict));
|
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
|
||||||
} else {
|
} else {
|
||||||
/* this will initialize correctly with no dict if dict == NULL, so
|
/* this will initialize correctly with no dict if dict == NULL, so
|
||||||
* use this in all cases but ddict */
|
* use this in all cases but ddict */
|
||||||
CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
||||||
}
|
}
|
||||||
ZSTD_checkContinuity(dctx, dst);
|
ZSTD_checkContinuity(dctx, dst);
|
||||||
|
|
||||||
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
||||||
&src, &srcSize);
|
&src, &srcSize);
|
||||||
if ( (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
RETURN_ERROR_IF(
|
||||||
&& (moreThan1Frame==1) ) {
|
(ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
||||||
/* at least one frame successfully completed,
|
&& (moreThan1Frame==1),
|
||||||
* but following bytes are garbage :
|
srcSize_wrong,
|
||||||
* it's more likely to be a srcSize error,
|
"at least one frame successfully completed, but following "
|
||||||
* specifying more bytes than compressed size of frame(s).
|
"bytes are garbage: it's more likely to be a srcSize error, "
|
||||||
* This error message replaces ERROR(prefix_unknown),
|
"specifying more bytes than compressed size of frame(s). This "
|
||||||
* which would be confusing, as the first header is actually correct.
|
"error message replaces ERROR(prefix_unknown), which would be "
|
||||||
* Note that one could be unlucky, it might be a corruption error instead,
|
"confusing, as the first header is actually correct. Note that "
|
||||||
* happening right at the place where we expect zstd magic bytes.
|
"one could be unlucky, it might be a corruption error instead, "
|
||||||
* But this is _much_ less likely than a srcSize field error. */
|
"happening right at the place where we expect zstd magic "
|
||||||
return ERROR(srcSize_wrong);
|
"bytes. But this is _much_ less likely than a srcSize field "
|
||||||
}
|
"error.");
|
||||||
if (ZSTD_isError(res)) return res;
|
if (ZSTD_isError(res)) return res;
|
||||||
assert(res <= dstCapacity);
|
assert(res <= dstCapacity);
|
||||||
dst = (BYTE*)dst + res;
|
dst = (BYTE*)dst + res;
|
||||||
@ -716,7 +780,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|||||||
moreThan1Frame = 1;
|
moreThan1Frame = 1;
|
||||||
} /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
|
} /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
|
||||||
|
|
||||||
if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */
|
RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
|
||||||
|
|
||||||
return (BYTE*)dst - (BYTE*)dststart;
|
return (BYTE*)dst - (BYTE*)dststart;
|
||||||
}
|
}
|
||||||
@ -730,9 +794,26 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
|
||||||
|
{
|
||||||
|
switch (dctx->dictUses) {
|
||||||
|
default:
|
||||||
|
assert(0 /* Impossible */);
|
||||||
|
/* fall-through */
|
||||||
|
case ZSTD_dont_use:
|
||||||
|
ZSTD_clearDict(dctx);
|
||||||
|
return NULL;
|
||||||
|
case ZSTD_use_indefinitely:
|
||||||
|
return dctx->ddict;
|
||||||
|
case ZSTD_use_once:
|
||||||
|
dctx->dictUses = ZSTD_dont_use;
|
||||||
|
return dctx->ddict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
|
return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -741,7 +822,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|||||||
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
||||||
size_t regenSize;
|
size_t regenSize;
|
||||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||||
if (dctx==NULL) return ERROR(memory_allocation);
|
RETURN_ERROR_IF(dctx==NULL, memory_allocation);
|
||||||
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
||||||
ZSTD_freeDCtx(dctx);
|
ZSTD_freeDCtx(dctx);
|
||||||
return regenSize;
|
return regenSize;
|
||||||
@ -791,8 +872,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|||||||
{
|
{
|
||||||
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if (srcSize != dctx->expected)
|
RETURN_ERROR_IF(srcSize != dctx->expected, srcSize_wrong, "not allowed");
|
||||||
return ERROR(srcSize_wrong); /* not allowed */
|
|
||||||
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
||||||
|
|
||||||
switch (dctx->stage)
|
switch (dctx->stage)
|
||||||
@ -817,7 +897,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|||||||
case ZSTDds_decodeFrameHeader:
|
case ZSTDds_decodeFrameHeader:
|
||||||
assert(src != NULL);
|
assert(src != NULL);
|
||||||
memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
||||||
CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
|
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
|
||||||
dctx->expected = ZSTD_blockHeaderSize;
|
dctx->expected = ZSTD_blockHeaderSize;
|
||||||
dctx->stage = ZSTDds_decodeBlockHeader;
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
||||||
return 0;
|
return 0;
|
||||||
@ -867,7 +947,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|||||||
break;
|
break;
|
||||||
case bt_reserved : /* should never happen */
|
case bt_reserved : /* should never happen */
|
||||||
default:
|
default:
|
||||||
return ERROR(corruption_detected);
|
RETURN_ERROR(corruption_detected);
|
||||||
}
|
}
|
||||||
if (ZSTD_isError(rSize)) return rSize;
|
if (ZSTD_isError(rSize)) return rSize;
|
||||||
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
||||||
@ -876,10 +956,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|||||||
|
|
||||||
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
||||||
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
|
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
|
||||||
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
RETURN_ERROR_IF(
|
||||||
if (dctx->decodedSize != dctx->fParams.frameContentSize) {
|
dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
||||||
return ERROR(corruption_detected);
|
&& dctx->decodedSize != dctx->fParams.frameContentSize,
|
||||||
} }
|
corruption_detected);
|
||||||
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
||||||
dctx->expected = 4;
|
dctx->expected = 4;
|
||||||
dctx->stage = ZSTDds_checkChecksum;
|
dctx->stage = ZSTDds_checkChecksum;
|
||||||
@ -900,7 +980,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|||||||
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
||||||
U32 const check32 = MEM_readLE32(src);
|
U32 const check32 = MEM_readLE32(src);
|
||||||
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
||||||
if (check32 != h32) return ERROR(checksum_wrong);
|
RETURN_ERROR_IF(check32 != h32, checksum_wrong);
|
||||||
dctx->expected = 0;
|
dctx->expected = 0;
|
||||||
dctx->stage = ZSTDds_getFrameHeaderSize;
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
||||||
return 0;
|
return 0;
|
||||||
@ -921,7 +1001,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0); /* impossible */
|
assert(0); /* impossible */
|
||||||
return ERROR(GENERIC); /* some compiler require default to do something */
|
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -945,7 +1025,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|||||||
const BYTE* dictPtr = (const BYTE*)dict;
|
const BYTE* dictPtr = (const BYTE*)dict;
|
||||||
const BYTE* const dictEnd = dictPtr + dictSize;
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
||||||
|
|
||||||
if (dictSize <= 8) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
|
||||||
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
|
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
|
||||||
dictPtr += 8; /* skip header = magic + dictID */
|
dictPtr += 8; /* skip header = magic + dictID */
|
||||||
|
|
||||||
@ -964,16 +1044,16 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|||||||
dictPtr, dictEnd - dictPtr,
|
dictPtr, dictEnd - dictPtr,
|
||||||
workspace, workspaceSize);
|
workspace, workspaceSize);
|
||||||
#endif
|
#endif
|
||||||
if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
|
||||||
dictPtr += hSize;
|
dictPtr += hSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ short offcodeNCount[MaxOff+1];
|
{ short offcodeNCount[MaxOff+1];
|
||||||
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
||||||
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
||||||
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
|
||||||
if (offcodeMaxValue > MaxOff) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
|
||||||
if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
|
||||||
ZSTD_buildFSETable( entropy->OFTable,
|
ZSTD_buildFSETable( entropy->OFTable,
|
||||||
offcodeNCount, offcodeMaxValue,
|
offcodeNCount, offcodeMaxValue,
|
||||||
OF_base, OF_bits,
|
OF_base, OF_bits,
|
||||||
@ -984,9 +1064,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|||||||
{ short matchlengthNCount[MaxML+1];
|
{ short matchlengthNCount[MaxML+1];
|
||||||
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
||||||
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
||||||
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
|
||||||
if (matchlengthMaxValue > MaxML) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
|
||||||
if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
|
||||||
ZSTD_buildFSETable( entropy->MLTable,
|
ZSTD_buildFSETable( entropy->MLTable,
|
||||||
matchlengthNCount, matchlengthMaxValue,
|
matchlengthNCount, matchlengthMaxValue,
|
||||||
ML_base, ML_bits,
|
ML_base, ML_bits,
|
||||||
@ -997,9 +1077,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|||||||
{ short litlengthNCount[MaxLL+1];
|
{ short litlengthNCount[MaxLL+1];
|
||||||
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
||||||
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
||||||
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
|
||||||
if (litlengthMaxValue > MaxLL) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
|
||||||
if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
|
||||||
ZSTD_buildFSETable( entropy->LLTable,
|
ZSTD_buildFSETable( entropy->LLTable,
|
||||||
litlengthNCount, litlengthMaxValue,
|
litlengthNCount, litlengthMaxValue,
|
||||||
LL_base, LL_bits,
|
LL_base, LL_bits,
|
||||||
@ -1007,12 +1087,13 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|||||||
dictPtr += litlengthHeaderSize;
|
dictPtr += litlengthHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
|
||||||
{ int i;
|
{ int i;
|
||||||
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
||||||
for (i=0; i<3; i++) {
|
for (i=0; i<3; i++) {
|
||||||
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
||||||
if (rep==0 || rep >= dictContentSize) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(rep==0 || rep >= dictContentSize,
|
||||||
|
dictionary_corrupted);
|
||||||
entropy->rep[i] = rep;
|
entropy->rep[i] = rep;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
@ -1030,7 +1111,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|||||||
|
|
||||||
/* load entropy tables */
|
/* load entropy tables */
|
||||||
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
|
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
|
||||||
if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
|
||||||
dict = (const char*)dict + eSize;
|
dict = (const char*)dict + eSize;
|
||||||
dictSize -= eSize;
|
dictSize -= eSize;
|
||||||
}
|
}
|
||||||
@ -1064,9 +1145,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|||||||
|
|
||||||
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
||||||
{
|
{
|
||||||
CHECK_F( ZSTD_decompressBegin(dctx) );
|
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
||||||
if (dict && dictSize)
|
if (dict && dictSize)
|
||||||
CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
|
RETURN_ERROR_IF(
|
||||||
|
ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
|
||||||
|
dictionary_corrupted);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1085,7 +1168,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|||||||
DEBUGLOG(4, "DDict is %s",
|
DEBUGLOG(4, "DDict is %s",
|
||||||
dctx->ddictIsCold ? "~cold~" : "hot!");
|
dctx->ddictIsCold ? "~cold~" : "hot!");
|
||||||
}
|
}
|
||||||
CHECK_F( ZSTD_decompressBegin(dctx) );
|
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
||||||
if (ddict) { /* NULL ddict is equivalent to no dictionary */
|
if (ddict) { /* NULL ddict is equivalent to no dictionary */
|
||||||
ZSTD_copyDDictParameters(dctx, ddict);
|
ZSTD_copyDDictParameters(dctx, ddict);
|
||||||
}
|
}
|
||||||
@ -1104,7 +1187,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*! ZSTD_getDictID_fromFrame() :
|
/*! ZSTD_getDictID_fromFrame() :
|
||||||
* Provides the dictID required to decompresse frame stored within `src`.
|
* Provides the dictID required to decompress frame stored within `src`.
|
||||||
* If @return == 0, the dictID could not be decoded.
|
* If @return == 0, the dictID could not be decoded.
|
||||||
* This could for one of the following reasons :
|
* This could for one of the following reasons :
|
||||||
* - The frame does not require a dictionary (most common case).
|
* - The frame does not require a dictionary (most common case).
|
||||||
@ -1176,15 +1259,14 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
|
|||||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||||
ZSTD_dictContentType_e dictContentType)
|
ZSTD_dictContentType_e dictContentType)
|
||||||
{
|
{
|
||||||
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
|
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||||
ZSTD_freeDDict(dctx->ddictLocal);
|
ZSTD_clearDict(dctx);
|
||||||
if (dict && dictSize >= 8) {
|
if (dict && dictSize >= 8) {
|
||||||
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
|
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
|
||||||
if (dctx->ddictLocal == NULL) return ERROR(memory_allocation);
|
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
|
||||||
} else {
|
|
||||||
dctx->ddictLocal = NULL;
|
|
||||||
}
|
|
||||||
dctx->ddict = dctx->ddictLocal;
|
dctx->ddict = dctx->ddictLocal;
|
||||||
|
dctx->dictUses = ZSTD_use_indefinitely;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1200,7 +1282,9 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
|
|||||||
|
|
||||||
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
||||||
{
|
{
|
||||||
return ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType);
|
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
|
||||||
|
dctx->dictUses = ZSTD_use_once;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
|
size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
|
||||||
@ -1215,9 +1299,8 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
|
|||||||
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
||||||
{
|
{
|
||||||
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
|
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
|
||||||
zds->streamStage = zdss_init;
|
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
|
||||||
zds->noForwardProgress = 0;
|
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
|
||||||
CHECK_F( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
|
|
||||||
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1225,7 +1308,7 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
|||||||
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
||||||
{
|
{
|
||||||
DEBUGLOG(4, "ZSTD_initDStream");
|
DEBUGLOG(4, "ZSTD_initDStream");
|
||||||
return ZSTD_initDStream_usingDict(zds, NULL, 0);
|
return ZSTD_initDStream_usingDDict(zds, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ZSTD_initDStream_usingDDict() :
|
/* ZSTD_initDStream_usingDDict() :
|
||||||
@ -1233,9 +1316,9 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|||||||
* this function cannot fail */
|
* this function cannot fail */
|
||||||
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
||||||
{
|
{
|
||||||
size_t const initResult = ZSTD_initDStream(dctx);
|
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
|
||||||
dctx->ddict = ddict;
|
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
|
||||||
return initResult;
|
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ZSTD_resetDStream() :
|
/* ZSTD_resetDStream() :
|
||||||
@ -1243,19 +1326,19 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|||||||
* this function cannot fail */
|
* this function cannot fail */
|
||||||
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
||||||
{
|
{
|
||||||
DEBUGLOG(4, "ZSTD_resetDStream");
|
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
|
||||||
dctx->streamStage = zdss_loadHeader;
|
|
||||||
dctx->lhSize = dctx->inPos = dctx->outStart = dctx->outEnd = 0;
|
|
||||||
dctx->legacyVersion = 0;
|
|
||||||
dctx->hostageByte = 0;
|
|
||||||
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
||||||
{
|
{
|
||||||
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
|
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||||
|
ZSTD_clearDict(dctx);
|
||||||
|
if (ddict) {
|
||||||
dctx->ddict = ddict;
|
dctx->ddict = ddict;
|
||||||
|
dctx->dictUses = ZSTD_use_indefinitely;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1267,9 +1350,9 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
|||||||
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
|
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
|
||||||
size_t const min = (size_t)1 << bounds.lowerBound;
|
size_t const min = (size_t)1 << bounds.lowerBound;
|
||||||
size_t const max = (size_t)1 << bounds.upperBound;
|
size_t const max = (size_t)1 << bounds.upperBound;
|
||||||
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
|
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||||
if (maxWindowSize < min) return ERROR(parameter_outOfBound);
|
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
|
||||||
if (maxWindowSize > max) return ERROR(parameter_outOfBound);
|
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
|
||||||
dctx->maxWindowSize = maxWindowSize;
|
dctx->maxWindowSize = maxWindowSize;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1311,15 +1394,15 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_DBOUNDS(p,v) { \
|
#define CHECK_DBOUNDS(p,v) { \
|
||||||
if (!ZSTD_dParam_withinBounds(p, v)) \
|
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
|
||||||
return ERROR(parameter_outOfBound); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
||||||
{
|
{
|
||||||
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
|
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||||
switch(dParam) {
|
switch(dParam) {
|
||||||
case ZSTD_d_windowLogMax:
|
case ZSTD_d_windowLogMax:
|
||||||
|
if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
|
||||||
CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
|
CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
|
||||||
dctx->maxWindowSize = ((size_t)1) << value;
|
dctx->maxWindowSize = ((size_t)1) << value;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1329,19 +1412,20 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|||||||
return 0;
|
return 0;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
return ERROR(parameter_unsupported);
|
RETURN_ERROR(parameter_unsupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
||||||
{
|
{
|
||||||
if ( (reset == ZSTD_reset_session_only)
|
if ( (reset == ZSTD_reset_session_only)
|
||||||
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
||||||
(void)ZSTD_initDStream(dctx);
|
dctx->streamStage = zdss_init;
|
||||||
|
dctx->noForwardProgress = 0;
|
||||||
}
|
}
|
||||||
if ( (reset == ZSTD_reset_parameters)
|
if ( (reset == ZSTD_reset_parameters)
|
||||||
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
||||||
if (dctx->streamStage != zdss_init)
|
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
||||||
return ERROR(stage_wrong);
|
ZSTD_clearDict(dctx);
|
||||||
dctx->format = ZSTD_f_zstd1;
|
dctx->format = ZSTD_f_zstd1;
|
||||||
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
||||||
}
|
}
|
||||||
@ -1360,7 +1444,8 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
|
|||||||
unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
|
unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
|
||||||
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
||||||
size_t const minRBSize = (size_t) neededSize;
|
size_t const minRBSize = (size_t) neededSize;
|
||||||
if ((unsigned long long)minRBSize != neededSize) return ERROR(frameParameter_windowTooLarge);
|
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
||||||
|
frameParameter_windowTooLarge);
|
||||||
return minRBSize;
|
return minRBSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1378,9 +1463,9 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
|||||||
ZSTD_frameHeader zfh;
|
ZSTD_frameHeader zfh;
|
||||||
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
||||||
if (ZSTD_isError(err)) return err;
|
if (ZSTD_isError(err)) return err;
|
||||||
if (err>0) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(err>0, srcSize_wrong);
|
||||||
if (zfh.windowSize > windowSizeMax)
|
RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
|
||||||
return ERROR(frameParameter_windowTooLarge);
|
frameParameter_windowTooLarge);
|
||||||
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1406,16 +1491,16 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
U32 someMoreWork = 1;
|
U32 someMoreWork = 1;
|
||||||
|
|
||||||
DEBUGLOG(5, "ZSTD_decompressStream");
|
DEBUGLOG(5, "ZSTD_decompressStream");
|
||||||
if (input->pos > input->size) { /* forbidden */
|
RETURN_ERROR_IF(
|
||||||
DEBUGLOG(5, "in: pos: %u vs size: %u",
|
input->pos > input->size,
|
||||||
|
srcSize_wrong,
|
||||||
|
"forbidden. in: pos: %u vs size: %u",
|
||||||
(U32)input->pos, (U32)input->size);
|
(U32)input->pos, (U32)input->size);
|
||||||
return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(
|
||||||
}
|
output->pos > output->size,
|
||||||
if (output->pos > output->size) { /* forbidden */
|
dstSize_tooSmall,
|
||||||
DEBUGLOG(5, "out: pos: %u vs size: %u",
|
"forbidden. out: pos: %u vs size: %u",
|
||||||
(U32)output->pos, (U32)output->size);
|
(U32)output->pos, (U32)output->size);
|
||||||
return ERROR(dstSize_tooSmall);
|
|
||||||
}
|
|
||||||
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
||||||
|
|
||||||
while (someMoreWork) {
|
while (someMoreWork) {
|
||||||
@ -1423,15 +1508,18 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
{
|
{
|
||||||
case zdss_init :
|
case zdss_init :
|
||||||
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
||||||
ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
|
zds->streamStage = zdss_loadHeader;
|
||||||
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
||||||
|
zds->legacyVersion = 0;
|
||||||
|
zds->hostageByte = 0;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
|
|
||||||
case zdss_loadHeader :
|
case zdss_loadHeader :
|
||||||
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
||||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
||||||
if (zds->legacyVersion) {
|
if (zds->legacyVersion) {
|
||||||
/* legacy support is incompatible with static dctx */
|
RETURN_ERROR_IF(zds->staticSize, memory_allocation,
|
||||||
if (zds->staticSize) return ERROR(memory_allocation);
|
"legacy support is incompatible with static dctx");
|
||||||
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
|
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
|
||||||
if (hint==0) zds->streamStage = zdss_init;
|
if (hint==0) zds->streamStage = zdss_init;
|
||||||
return hint;
|
return hint;
|
||||||
@ -1443,12 +1531,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
||||||
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
||||||
if (legacyVersion) {
|
if (legacyVersion) {
|
||||||
const void* const dict = zds->ddict ? ZSTD_DDict_dictContent(zds->ddict) : NULL;
|
ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);
|
||||||
size_t const dictSize = zds->ddict ? ZSTD_DDict_dictSize(zds->ddict) : 0;
|
const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;
|
||||||
|
size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;
|
||||||
DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
|
DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
|
||||||
/* legacy support is incompatible with static dctx */
|
RETURN_ERROR_IF(zds->staticSize, memory_allocation,
|
||||||
if (zds->staticSize) return ERROR(memory_allocation);
|
"legacy support is incompatible with static dctx");
|
||||||
CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext,
|
FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
|
||||||
zds->previousLegacyVersion, legacyVersion,
|
zds->previousLegacyVersion, legacyVersion,
|
||||||
dict, dictSize));
|
dict, dictSize));
|
||||||
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
||||||
@ -1482,7 +1571,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
||||||
if (cSize <= (size_t)(iend-istart)) {
|
if (cSize <= (size_t)(iend-istart)) {
|
||||||
/* shortcut : using single-pass mode */
|
/* shortcut : using single-pass mode */
|
||||||
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds->ddict);
|
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
|
||||||
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
||||||
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
||||||
ip = istart + cSize;
|
ip = istart + cSize;
|
||||||
@ -1495,13 +1584,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
|
|
||||||
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
||||||
DEBUGLOG(4, "Consume header");
|
DEBUGLOG(4, "Consume header");
|
||||||
CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
|
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
|
||||||
|
|
||||||
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
||||||
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
||||||
zds->stage = ZSTDds_skipFrame;
|
zds->stage = ZSTDds_skipFrame;
|
||||||
} else {
|
} else {
|
||||||
CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
||||||
zds->expected = ZSTD_blockHeaderSize;
|
zds->expected = ZSTD_blockHeaderSize;
|
||||||
zds->stage = ZSTDds_decodeBlockHeader;
|
zds->stage = ZSTDds_decodeBlockHeader;
|
||||||
}
|
}
|
||||||
@ -1511,7 +1600,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
(U32)(zds->fParams.windowSize >>10),
|
(U32)(zds->fParams.windowSize >>10),
|
||||||
(U32)(zds->maxWindowSize >> 10) );
|
(U32)(zds->maxWindowSize >> 10) );
|
||||||
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
||||||
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
|
RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
|
||||||
|
frameParameter_windowTooLarge);
|
||||||
|
|
||||||
/* Adapt buffer sizes to frame header instructions */
|
/* Adapt buffer sizes to frame header instructions */
|
||||||
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
||||||
@ -1525,14 +1615,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
if (zds->staticSize) { /* static DCtx */
|
if (zds->staticSize) { /* static DCtx */
|
||||||
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
||||||
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
||||||
if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx))
|
RETURN_ERROR_IF(
|
||||||
return ERROR(memory_allocation);
|
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
||||||
|
memory_allocation);
|
||||||
} else {
|
} else {
|
||||||
ZSTD_free(zds->inBuff, zds->customMem);
|
ZSTD_free(zds->inBuff, zds->customMem);
|
||||||
zds->inBuffSize = 0;
|
zds->inBuffSize = 0;
|
||||||
zds->outBuffSize = 0;
|
zds->outBuffSize = 0;
|
||||||
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
|
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
|
||||||
if (zds->inBuff == NULL) return ERROR(memory_allocation);
|
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
|
||||||
}
|
}
|
||||||
zds->inBuffSize = neededInBuffSize;
|
zds->inBuffSize = neededInBuffSize;
|
||||||
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
||||||
@ -1574,7 +1665,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
if (isSkipFrame) {
|
if (isSkipFrame) {
|
||||||
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
||||||
} else {
|
} else {
|
||||||
if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */
|
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
|
||||||
|
corruption_detected,
|
||||||
|
"should never happen");
|
||||||
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
||||||
}
|
}
|
||||||
ip += loadedSize;
|
ip += loadedSize;
|
||||||
@ -1615,7 +1708,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0); /* impossible */
|
assert(0); /* impossible */
|
||||||
return ERROR(GENERIC); /* some compiler require default to do something */
|
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
||||||
} }
|
} }
|
||||||
|
|
||||||
/* result */
|
/* result */
|
||||||
@ -1624,8 +1717,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
||||||
zds->noForwardProgress ++;
|
zds->noForwardProgress ++;
|
||||||
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
||||||
if (op==oend) return ERROR(dstSize_tooSmall);
|
RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
|
||||||
if (ip==iend) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(ip==iend, srcSize_wrong);
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,14 +56,15 @@ static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
|
|||||||
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
|
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
|
||||||
blockProperties_t* bpPtr)
|
blockProperties_t* bpPtr)
|
||||||
{
|
{
|
||||||
if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong);
|
||||||
|
|
||||||
{ U32 const cBlockHeader = MEM_readLE24(src);
|
{ U32 const cBlockHeader = MEM_readLE24(src);
|
||||||
U32 const cSize = cBlockHeader >> 3;
|
U32 const cSize = cBlockHeader >> 3;
|
||||||
bpPtr->lastBlock = cBlockHeader & 1;
|
bpPtr->lastBlock = cBlockHeader & 1;
|
||||||
bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
|
bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
|
||||||
bpPtr->origSize = cSize; /* only useful for RLE */
|
bpPtr->origSize = cSize; /* only useful for RLE */
|
||||||
if (bpPtr->blockType == bt_rle) return 1;
|
if (bpPtr->blockType == bt_rle) return 1;
|
||||||
if (bpPtr->blockType == bt_reserved) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected);
|
||||||
return cSize;
|
return cSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,7 +79,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|||||||
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||||
const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
|
const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
|
||||||
{
|
{
|
||||||
if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected);
|
||||||
|
|
||||||
{ const BYTE* const istart = (const BYTE*) src;
|
{ const BYTE* const istart = (const BYTE*) src;
|
||||||
symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
|
symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
|
||||||
@ -86,11 +87,11 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|||||||
switch(litEncType)
|
switch(litEncType)
|
||||||
{
|
{
|
||||||
case set_repeat:
|
case set_repeat:
|
||||||
if (dctx->litEntropy==0) return ERROR(dictionary_corrupted);
|
RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted);
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
|
|
||||||
case set_compressed:
|
case set_compressed:
|
||||||
if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
|
RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3");
|
||||||
{ size_t lhSize, litSize, litCSize;
|
{ size_t lhSize, litSize, litCSize;
|
||||||
U32 singleStream=0;
|
U32 singleStream=0;
|
||||||
U32 const lhlCode = (istart[0] >> 2) & 3;
|
U32 const lhlCode = (istart[0] >> 2) & 3;
|
||||||
@ -118,8 +119,8 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|||||||
litCSize = (lhc >> 22) + (istart[4] << 10);
|
litCSize = (lhc >> 22) + (istart[4] << 10);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected);
|
||||||
if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected);
|
||||||
|
|
||||||
/* prefetch huffman table if cold */
|
/* prefetch huffman table if cold */
|
||||||
if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {
|
if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {
|
||||||
@ -157,7 +158,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HUF_isError(hufSuccess)) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected);
|
||||||
|
|
||||||
dctx->litPtr = dctx->litBuffer;
|
dctx->litPtr = dctx->litBuffer;
|
||||||
dctx->litSize = litSize;
|
dctx->litSize = litSize;
|
||||||
@ -187,7 +188,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
|
if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
|
||||||
if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected);
|
||||||
memcpy(dctx->litBuffer, istart+lhSize, litSize);
|
memcpy(dctx->litBuffer, istart+lhSize, litSize);
|
||||||
dctx->litPtr = dctx->litBuffer;
|
dctx->litPtr = dctx->litBuffer;
|
||||||
dctx->litSize = litSize;
|
dctx->litSize = litSize;
|
||||||
@ -216,17 +217,17 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|||||||
case 3:
|
case 3:
|
||||||
lhSize = 3;
|
lhSize = 3;
|
||||||
litSize = MEM_readLE24(istart) >> 4;
|
litSize = MEM_readLE24(istart) >> 4;
|
||||||
if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
|
RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected);
|
||||||
memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
|
memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
|
||||||
dctx->litPtr = dctx->litBuffer;
|
dctx->litPtr = dctx->litBuffer;
|
||||||
dctx->litSize = litSize;
|
dctx->litSize = litSize;
|
||||||
return lhSize+1;
|
return lhSize+1;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return ERROR(corruption_detected); /* impossible */
|
RETURN_ERROR(corruption_detected, "impossible");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,8 +437,8 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
|
|||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case set_rle :
|
case set_rle :
|
||||||
if (!srcSize) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(!srcSize, srcSize_wrong);
|
||||||
if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);
|
RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected);
|
||||||
{ U32 const symbol = *(const BYTE*)src;
|
{ U32 const symbol = *(const BYTE*)src;
|
||||||
U32 const baseline = baseValue[symbol];
|
U32 const baseline = baseValue[symbol];
|
||||||
U32 const nbBits = nbAdditionalBits[symbol];
|
U32 const nbBits = nbAdditionalBits[symbol];
|
||||||
@ -449,7 +450,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
|
|||||||
*DTablePtr = defaultTable;
|
*DTablePtr = defaultTable;
|
||||||
return 0;
|
return 0;
|
||||||
case set_repeat:
|
case set_repeat:
|
||||||
if (!flagRepeatTable) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(!flagRepeatTable, corruption_detected);
|
||||||
/* prefetch FSE table if used */
|
/* prefetch FSE table if used */
|
||||||
if (ddictIsCold && (nbSeq > 24 /* heuristic */)) {
|
if (ddictIsCold && (nbSeq > 24 /* heuristic */)) {
|
||||||
const void* const pStart = *DTablePtr;
|
const void* const pStart = *DTablePtr;
|
||||||
@ -461,15 +462,15 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
|
|||||||
{ unsigned tableLog;
|
{ unsigned tableLog;
|
||||||
S16 norm[MaxSeq+1];
|
S16 norm[MaxSeq+1];
|
||||||
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
|
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
|
||||||
if (FSE_isError(headerSize)) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected);
|
||||||
if (tableLog > maxLog) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(tableLog > maxLog, corruption_detected);
|
||||||
ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog);
|
ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog);
|
||||||
*DTablePtr = DTableSpace;
|
*DTablePtr = DTableSpace;
|
||||||
return headerSize;
|
return headerSize;
|
||||||
}
|
}
|
||||||
default : /* impossible */
|
default :
|
||||||
assert(0);
|
assert(0);
|
||||||
return ERROR(GENERIC);
|
RETURN_ERROR(GENERIC, "impossible");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,28 +484,28 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|||||||
DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
|
DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
|
||||||
|
|
||||||
/* check */
|
/* check */
|
||||||
if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong);
|
||||||
|
|
||||||
/* SeqHead */
|
/* SeqHead */
|
||||||
nbSeq = *ip++;
|
nbSeq = *ip++;
|
||||||
if (!nbSeq) {
|
if (!nbSeq) {
|
||||||
*nbSeqPtr=0;
|
*nbSeqPtr=0;
|
||||||
if (srcSize != 1) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(srcSize != 1, srcSize_wrong);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (nbSeq > 0x7F) {
|
if (nbSeq > 0x7F) {
|
||||||
if (nbSeq == 0xFF) {
|
if (nbSeq == 0xFF) {
|
||||||
if (ip+2 > iend) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong);
|
||||||
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
||||||
} else {
|
} else {
|
||||||
if (ip >= iend) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(ip >= iend, srcSize_wrong);
|
||||||
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*nbSeqPtr = nbSeq;
|
*nbSeqPtr = nbSeq;
|
||||||
|
|
||||||
/* FSE table descriptors */
|
/* FSE table descriptors */
|
||||||
if (ip+4 > iend) return ERROR(srcSize_wrong); /* minimum possible size */
|
RETURN_ERROR_IF(ip+4 > iend, srcSize_wrong); /* minimum possible size */
|
||||||
{ symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
|
{ symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
|
||||||
symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
|
symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
|
||||||
symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
|
symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
|
||||||
@ -517,7 +518,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|||||||
LL_base, LL_bits,
|
LL_base, LL_bits,
|
||||||
LL_defaultDTable, dctx->fseEntropy,
|
LL_defaultDTable, dctx->fseEntropy,
|
||||||
dctx->ddictIsCold, nbSeq);
|
dctx->ddictIsCold, nbSeq);
|
||||||
if (ZSTD_isError(llhSize)) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected);
|
||||||
ip += llhSize;
|
ip += llhSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +528,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|||||||
OF_base, OF_bits,
|
OF_base, OF_bits,
|
||||||
OF_defaultDTable, dctx->fseEntropy,
|
OF_defaultDTable, dctx->fseEntropy,
|
||||||
dctx->ddictIsCold, nbSeq);
|
dctx->ddictIsCold, nbSeq);
|
||||||
if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected);
|
||||||
ip += ofhSize;
|
ip += ofhSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,7 +538,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|||||||
ML_base, ML_bits,
|
ML_base, ML_bits,
|
||||||
ML_defaultDTable, dctx->fseEntropy,
|
ML_defaultDTable, dctx->fseEntropy,
|
||||||
dctx->ddictIsCold, nbSeq);
|
dctx->ddictIsCold, nbSeq);
|
||||||
if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected);
|
||||||
ip += mlhSize;
|
ip += mlhSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,8 +591,8 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
|
|||||||
const BYTE* match = oLitEnd - sequence.offset;
|
const BYTE* match = oLitEnd - sequence.offset;
|
||||||
|
|
||||||
/* check */
|
/* check */
|
||||||
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must fit within dstBuffer */
|
RETURN_ERROR_IF(oMatchEnd>oend, dstSize_tooSmall, "last match must fit within dstBuffer");
|
||||||
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* try to read beyond literal buffer */
|
RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "try to read beyond literal buffer");
|
||||||
|
|
||||||
/* copy literals */
|
/* copy literals */
|
||||||
while (op < oLitEnd) *op++ = *(*litPtr)++;
|
while (op < oLitEnd) *op++ = *(*litPtr)++;
|
||||||
@ -599,7 +600,7 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
|
|||||||
/* copy Match */
|
/* copy Match */
|
||||||
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
||||||
/* offset beyond prefix */
|
/* offset beyond prefix */
|
||||||
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - vBase),corruption_detected);
|
||||||
match = dictEnd - (base-match);
|
match = dictEnd - (base-match);
|
||||||
if (match + sequence.matchLength <= dictEnd) {
|
if (match + sequence.matchLength <= dictEnd) {
|
||||||
memmove(oLitEnd, match, sequence.matchLength);
|
memmove(oLitEnd, match, sequence.matchLength);
|
||||||
@ -631,8 +632,8 @@ size_t ZSTD_execSequence(BYTE* op,
|
|||||||
const BYTE* match = oLitEnd - sequence.offset;
|
const BYTE* match = oLitEnd - sequence.offset;
|
||||||
|
|
||||||
/* check */
|
/* check */
|
||||||
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
RETURN_ERROR_IF(oMatchEnd>oend, dstSize_tooSmall, "last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend");
|
||||||
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "over-read beyond lit buffer");
|
||||||
if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
|
if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
|
||||||
|
|
||||||
/* copy Literals */
|
/* copy Literals */
|
||||||
@ -645,8 +646,7 @@ size_t ZSTD_execSequence(BYTE* op,
|
|||||||
/* copy Match */
|
/* copy Match */
|
||||||
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
|
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
|
||||||
/* offset beyond prefix -> go into extDict */
|
/* offset beyond prefix -> go into extDict */
|
||||||
if (sequence.offset > (size_t)(oLitEnd - virtualStart))
|
RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected);
|
||||||
return ERROR(corruption_detected);
|
|
||||||
match = dictEnd + (match - prefixStart);
|
match = dictEnd + (match - prefixStart);
|
||||||
if (match + sequence.matchLength <= dictEnd) {
|
if (match + sequence.matchLength <= dictEnd) {
|
||||||
memmove(oLitEnd, match, sequence.matchLength);
|
memmove(oLitEnd, match, sequence.matchLength);
|
||||||
@ -712,8 +712,8 @@ size_t ZSTD_execSequenceLong(BYTE* op,
|
|||||||
const BYTE* match = sequence.match;
|
const BYTE* match = sequence.match;
|
||||||
|
|
||||||
/* check */
|
/* check */
|
||||||
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
RETURN_ERROR_IF(oMatchEnd > oend, dstSize_tooSmall, "last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend");
|
||||||
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "over-read beyond lit buffer");
|
||||||
if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
|
if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
|
||||||
|
|
||||||
/* copy Literals */
|
/* copy Literals */
|
||||||
@ -726,7 +726,7 @@ size_t ZSTD_execSequenceLong(BYTE* op,
|
|||||||
/* copy Match */
|
/* copy Match */
|
||||||
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
|
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
|
||||||
/* offset beyond prefix */
|
/* offset beyond prefix */
|
||||||
if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - dictStart), corruption_detected);
|
||||||
if (match + sequence.matchLength <= dictEnd) {
|
if (match + sequence.matchLength <= dictEnd) {
|
||||||
memmove(oLitEnd, match, sequence.matchLength);
|
memmove(oLitEnd, match, sequence.matchLength);
|
||||||
return sequenceLength;
|
return sequenceLength;
|
||||||
@ -801,7 +801,7 @@ ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD)
|
|||||||
/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
|
/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
|
||||||
* offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
|
* offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
|
||||||
* bits before reloading. This value is the maximum number of bytes we read
|
* bits before reloading. This value is the maximum number of bytes we read
|
||||||
* after reloading when we are decoding long offets.
|
* after reloading when we are decoding long offsets.
|
||||||
*/
|
*/
|
||||||
#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
|
#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
|
||||||
(ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
|
(ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
|
||||||
@ -911,7 +911,9 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
|||||||
seqState_t seqState;
|
seqState_t seqState;
|
||||||
dctx->fseEntropy = 1;
|
dctx->fseEntropy = 1;
|
||||||
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
||||||
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
RETURN_ERROR_IF(
|
||||||
|
ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
|
||||||
|
corruption_detected);
|
||||||
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
||||||
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
||||||
ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
||||||
@ -927,14 +929,14 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
|||||||
|
|
||||||
/* check if reached exact end */
|
/* check if reached exact end */
|
||||||
DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
|
DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
|
||||||
if (nbSeq) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(nbSeq, corruption_detected);
|
||||||
/* save reps for next block */
|
/* save reps for next block */
|
||||||
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* last literal segment */
|
/* last literal segment */
|
||||||
{ size_t const lastLLSize = litEnd - litPtr;
|
{ size_t const lastLLSize = litEnd - litPtr;
|
||||||
if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);
|
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall);
|
||||||
memcpy(op, litPtr, lastLLSize);
|
memcpy(op, litPtr, lastLLSize);
|
||||||
op += lastLLSize;
|
op += lastLLSize;
|
||||||
}
|
}
|
||||||
@ -1066,7 +1068,9 @@ ZSTD_decompressSequencesLong_body(
|
|||||||
seqState.pos = (size_t)(op-prefixStart);
|
seqState.pos = (size_t)(op-prefixStart);
|
||||||
seqState.dictEnd = dictEnd;
|
seqState.dictEnd = dictEnd;
|
||||||
assert(iend >= ip);
|
assert(iend >= ip);
|
||||||
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
RETURN_ERROR_IF(
|
||||||
|
ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
|
||||||
|
corruption_detected);
|
||||||
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
||||||
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
||||||
ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
||||||
@ -1076,7 +1080,7 @@ ZSTD_decompressSequencesLong_body(
|
|||||||
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
|
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
|
||||||
PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
||||||
}
|
}
|
||||||
if (seqNb<seqAdvance) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected);
|
||||||
|
|
||||||
/* decode and decompress */
|
/* decode and decompress */
|
||||||
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
|
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
|
||||||
@ -1087,7 +1091,7 @@ ZSTD_decompressSequencesLong_body(
|
|||||||
sequences[seqNb & STORED_SEQS_MASK] = sequence;
|
sequences[seqNb & STORED_SEQS_MASK] = sequence;
|
||||||
op += oneSeqSize;
|
op += oneSeqSize;
|
||||||
}
|
}
|
||||||
if (seqNb<nbSeq) return ERROR(corruption_detected);
|
RETURN_ERROR_IF(seqNb<nbSeq, corruption_detected);
|
||||||
|
|
||||||
/* finish queue */
|
/* finish queue */
|
||||||
seqNb -= seqAdvance;
|
seqNb -= seqAdvance;
|
||||||
@ -1103,7 +1107,7 @@ ZSTD_decompressSequencesLong_body(
|
|||||||
|
|
||||||
/* last literal segment */
|
/* last literal segment */
|
||||||
{ size_t const lastLLSize = litEnd - litPtr;
|
{ size_t const lastLLSize = litEnd - litPtr;
|
||||||
if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);
|
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall);
|
||||||
memcpy(op, litPtr, lastLLSize);
|
memcpy(op, litPtr, lastLLSize);
|
||||||
op += lastLLSize;
|
op += lastLLSize;
|
||||||
}
|
}
|
||||||
@ -1176,7 +1180,7 @@ ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
|
|||||||
/* ZSTD_decompressSequencesLong() :
|
/* ZSTD_decompressSequencesLong() :
|
||||||
* decompression function triggered when a minimum share of offsets is considered "long",
|
* decompression function triggered when a minimum share of offsets is considered "long",
|
||||||
* aka out of cache.
|
* aka out of cache.
|
||||||
* note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes mearning "farther than memory cache distance".
|
* note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes meaning "farther than memory cache distance".
|
||||||
* This function will try to mitigate main memory latency through the use of prefetching */
|
* This function will try to mitigate main memory latency through the use of prefetching */
|
||||||
static size_t
|
static size_t
|
||||||
ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
|
ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
|
||||||
@ -1240,7 +1244,7 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
|||||||
ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN))));
|
ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN))));
|
||||||
DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
|
DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
|
||||||
|
|
||||||
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
|
RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong);
|
||||||
|
|
||||||
/* Decode literals section */
|
/* Decode literals section */
|
||||||
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
||||||
|
@ -89,6 +89,12 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
|
|||||||
typedef enum { zdss_init=0, zdss_loadHeader,
|
typedef enum { zdss_init=0, zdss_loadHeader,
|
||||||
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
|
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ZSTD_use_indefinitely = -1, /* Use the dictionary indefinitely */
|
||||||
|
ZSTD_dont_use = 0, /* Do not use the dictionary (if one exists free it) */
|
||||||
|
ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
|
||||||
|
} ZSTD_dictUses_e;
|
||||||
|
|
||||||
struct ZSTD_DCtx_s
|
struct ZSTD_DCtx_s
|
||||||
{
|
{
|
||||||
const ZSTD_seqSymbol* LLTptr;
|
const ZSTD_seqSymbol* LLTptr;
|
||||||
@ -123,6 +129,7 @@ struct ZSTD_DCtx_s
|
|||||||
const ZSTD_DDict* ddict; /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */
|
const ZSTD_DDict* ddict; /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */
|
||||||
U32 dictID;
|
U32 dictID;
|
||||||
int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
|
int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
|
||||||
|
ZSTD_dictUses_e dictUses;
|
||||||
|
|
||||||
/* streaming */
|
/* streaming */
|
||||||
ZSTD_dStreamStage streamStage;
|
ZSTD_dStreamStage streamStage;
|
||||||
|
@ -391,7 +391,7 @@ static void COVER_group(COVER_ctx_t *ctx, const void *group,
|
|||||||
*
|
*
|
||||||
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
|
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
|
||||||
*
|
*
|
||||||
* Once the dmer d is in the dictionay we set F(d) = 0.
|
* Once the dmer d is in the dictionary we set F(d) = 0.
|
||||||
*/
|
*/
|
||||||
static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs,
|
static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs,
|
||||||
COVER_map_t *activeDmers, U32 begin,
|
COVER_map_t *activeDmers, U32 begin,
|
||||||
@ -435,7 +435,7 @@ static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs,
|
|||||||
U32 *delDmerOcc = COVER_map_at(activeDmers, delDmer);
|
U32 *delDmerOcc = COVER_map_at(activeDmers, delDmer);
|
||||||
activeSegment.begin += 1;
|
activeSegment.begin += 1;
|
||||||
*delDmerOcc -= 1;
|
*delDmerOcc -= 1;
|
||||||
/* If this is the last occurence of the dmer, subtract its score */
|
/* If this is the last occurrence of the dmer, subtract its score */
|
||||||
if (*delDmerOcc == 0) {
|
if (*delDmerOcc == 0) {
|
||||||
COVER_map_remove(activeDmers, delDmer);
|
COVER_map_remove(activeDmers, delDmer);
|
||||||
activeSegment.score -= freqs[delDmer];
|
activeSegment.score -= freqs[delDmer];
|
||||||
@ -627,6 +627,39 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel)
|
||||||
|
{
|
||||||
|
const double ratio = (double)nbDmers / maxDictSize;
|
||||||
|
if (ratio >= 10) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOCALDISPLAYLEVEL(displayLevel, 1,
|
||||||
|
"WARNING: The maximum dictionary size %u is too large "
|
||||||
|
"compared to the source size %u! "
|
||||||
|
"size(source)/size(dictionary) = %f, but it should be >= "
|
||||||
|
"10! This may lead to a subpar dictionary! We recommend "
|
||||||
|
"training on sources at least 10x, and up to 100x the "
|
||||||
|
"size of the dictionary!\n", (U32)maxDictSize,
|
||||||
|
(U32)nbDmers, ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
COVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize,
|
||||||
|
U32 nbDmers, U32 k, U32 passes)
|
||||||
|
{
|
||||||
|
const U32 minEpochSize = k * 10;
|
||||||
|
COVER_epoch_info_t epochs;
|
||||||
|
epochs.num = MAX(1, maxDictSize / k / passes);
|
||||||
|
epochs.size = nbDmers / epochs.num;
|
||||||
|
if (epochs.size >= minEpochSize) {
|
||||||
|
assert(epochs.size * epochs.num <= nbDmers);
|
||||||
|
return epochs;
|
||||||
|
}
|
||||||
|
epochs.size = MIN(minEpochSize, nbDmers);
|
||||||
|
epochs.num = nbDmers / epochs.size;
|
||||||
|
assert(epochs.size * epochs.num <= nbDmers);
|
||||||
|
return epochs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the prepared context build the dictionary.
|
* Given the prepared context build the dictionary.
|
||||||
*/
|
*/
|
||||||
@ -636,28 +669,34 @@ static size_t COVER_buildDictionary(const COVER_ctx_t *ctx, U32 *freqs,
|
|||||||
ZDICT_cover_params_t parameters) {
|
ZDICT_cover_params_t parameters) {
|
||||||
BYTE *const dict = (BYTE *)dictBuffer;
|
BYTE *const dict = (BYTE *)dictBuffer;
|
||||||
size_t tail = dictBufferCapacity;
|
size_t tail = dictBufferCapacity;
|
||||||
/* Divide the data up into epochs of equal size.
|
/* Divide the data into epochs. We will select one segment from each epoch. */
|
||||||
* We will select at least one segment from each epoch.
|
const COVER_epoch_info_t epochs = COVER_computeEpochs(
|
||||||
*/
|
(U32)dictBufferCapacity, (U32)ctx->suffixSize, parameters.k, 4);
|
||||||
const unsigned epochs = MAX(1, (U32)(dictBufferCapacity / parameters.k / 4));
|
const size_t maxZeroScoreRun = MAX(10, MIN(100, epochs.num >> 3));
|
||||||
const unsigned epochSize = (U32)(ctx->suffixSize / epochs);
|
size_t zeroScoreRun = 0;
|
||||||
size_t epoch;
|
size_t epoch;
|
||||||
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
|
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
|
||||||
epochs, epochSize);
|
(U32)epochs.num, (U32)epochs.size);
|
||||||
/* Loop through the epochs until there are no more segments or the dictionary
|
/* Loop through the epochs until there are no more segments or the dictionary
|
||||||
* is full.
|
* is full.
|
||||||
*/
|
*/
|
||||||
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs) {
|
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) {
|
||||||
const U32 epochBegin = (U32)(epoch * epochSize);
|
const U32 epochBegin = (U32)(epoch * epochs.size);
|
||||||
const U32 epochEnd = epochBegin + epochSize;
|
const U32 epochEnd = epochBegin + epochs.size;
|
||||||
size_t segmentSize;
|
size_t segmentSize;
|
||||||
/* Select a segment */
|
/* Select a segment */
|
||||||
COVER_segment_t segment = COVER_selectSegment(
|
COVER_segment_t segment = COVER_selectSegment(
|
||||||
ctx, freqs, activeDmers, epochBegin, epochEnd, parameters);
|
ctx, freqs, activeDmers, epochBegin, epochEnd, parameters);
|
||||||
/* If the segment covers no dmers, then we are out of content */
|
/* If the segment covers no dmers, then we are out of content.
|
||||||
|
* There may be new content in other epochs, for continue for some time.
|
||||||
|
*/
|
||||||
if (segment.score == 0) {
|
if (segment.score == 0) {
|
||||||
|
if (++zeroScoreRun >= maxZeroScoreRun) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
zeroScoreRun = 0;
|
||||||
/* Trim the segment if necessary and if it is too small then we are done */
|
/* Trim the segment if necessary and if it is too small then we are done */
|
||||||
segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);
|
segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);
|
||||||
if (segmentSize < parameters.d) {
|
if (segmentSize < parameters.d) {
|
||||||
@ -706,6 +745,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_cover(
|
|||||||
parameters.d, parameters.splitPoint)) {
|
parameters.d, parameters.splitPoint)) {
|
||||||
return ERROR(GENERIC);
|
return ERROR(GENERIC);
|
||||||
}
|
}
|
||||||
|
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, g_displayLevel);
|
||||||
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
|
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
|
||||||
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
|
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
|
||||||
COVER_ctx_destroy(&ctx);
|
COVER_ctx_destroy(&ctx);
|
||||||
@ -977,6 +1017,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
|||||||
unsigned k;
|
unsigned k;
|
||||||
COVER_best_t best;
|
COVER_best_t best;
|
||||||
POOL_ctx *pool = NULL;
|
POOL_ctx *pool = NULL;
|
||||||
|
int warned = 0;
|
||||||
|
|
||||||
/* Checks */
|
/* Checks */
|
||||||
if (splitPoint <= 0 || splitPoint > 1) {
|
if (splitPoint <= 0 || splitPoint > 1) {
|
||||||
@ -1019,6 +1060,10 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
|||||||
POOL_free(pool);
|
POOL_free(pool);
|
||||||
return ERROR(GENERIC);
|
return ERROR(GENERIC);
|
||||||
}
|
}
|
||||||
|
if (!warned) {
|
||||||
|
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, displayLevel);
|
||||||
|
warned = 1;
|
||||||
|
}
|
||||||
/* Loop through k reusing the same context */
|
/* Loop through k reusing the same context */
|
||||||
for (k = kMinK; k <= kMaxK; k += kStepSize) {
|
for (k = kMinK; k <= kMaxK; k += kStepSize) {
|
||||||
/* Prepare the arguments */
|
/* Prepare the arguments */
|
||||||
|
@ -38,6 +38,35 @@ typedef struct {
|
|||||||
U32 score;
|
U32 score;
|
||||||
} COVER_segment_t;
|
} COVER_segment_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Number of epochs and size of each epoch.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
U32 num;
|
||||||
|
U32 size;
|
||||||
|
} COVER_epoch_info_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the number of epochs and the size of each epoch.
|
||||||
|
* We will make sure that each epoch gets at least 10 * k bytes.
|
||||||
|
*
|
||||||
|
* The COVER algorithms divide the data up into epochs of equal size and
|
||||||
|
* select one segment from each epoch.
|
||||||
|
*
|
||||||
|
* @param maxDictSize The maximum allowed dictionary size.
|
||||||
|
* @param nbDmers The number of dmers we are training on.
|
||||||
|
* @param k The parameter k (segment size).
|
||||||
|
* @param passes The target number of passes over the dmer corpus.
|
||||||
|
* More passes means a better dictionary.
|
||||||
|
*/
|
||||||
|
COVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize, U32 nbDmers,
|
||||||
|
U32 k, U32 passes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warns the user when their corpus is too small.
|
||||||
|
*/
|
||||||
|
void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks total compressed size of a dictionary
|
* Checks total compressed size of a dictionary
|
||||||
*/
|
*/
|
||||||
|
@ -132,7 +132,7 @@ typedef struct {
|
|||||||
*
|
*
|
||||||
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
|
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
|
||||||
*
|
*
|
||||||
* Once the dmer with hash value d is in the dictionay we set F(d) = 0.
|
* Once the dmer with hash value d is in the dictionary we set F(d) = 0.
|
||||||
*/
|
*/
|
||||||
static COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
static COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
||||||
U32 *freqs, U32 begin, U32 end,
|
U32 *freqs, U32 begin, U32 end,
|
||||||
@ -161,7 +161,7 @@ static COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
|
|||||||
/* Get hash value of current dmer */
|
/* Get hash value of current dmer */
|
||||||
const size_t idx = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, f, d);
|
const size_t idx = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, f, d);
|
||||||
|
|
||||||
/* Add frequency of this index to score if this is the first occurence of index in active segment */
|
/* Add frequency of this index to score if this is the first occurrence of index in active segment */
|
||||||
if (segmentFreqs[idx] == 0) {
|
if (segmentFreqs[idx] == 0) {
|
||||||
activeSegment.score += freqs[idx];
|
activeSegment.score += freqs[idx];
|
||||||
}
|
}
|
||||||
@ -386,29 +386,35 @@ FASTCOVER_buildDictionary(const FASTCOVER_ctx_t* ctx,
|
|||||||
{
|
{
|
||||||
BYTE *const dict = (BYTE *)dictBuffer;
|
BYTE *const dict = (BYTE *)dictBuffer;
|
||||||
size_t tail = dictBufferCapacity;
|
size_t tail = dictBufferCapacity;
|
||||||
/* Divide the data up into epochs of equal size.
|
/* Divide the data into epochs. We will select one segment from each epoch. */
|
||||||
* We will select at least one segment from each epoch.
|
const COVER_epoch_info_t epochs = COVER_computeEpochs(
|
||||||
*/
|
(U32)dictBufferCapacity, (U32)ctx->nbDmers, parameters.k, 1);
|
||||||
const unsigned epochs = MAX(1, (U32)(dictBufferCapacity / parameters.k));
|
const size_t maxZeroScoreRun = 10;
|
||||||
const unsigned epochSize = (U32)(ctx->nbDmers / epochs);
|
size_t zeroScoreRun = 0;
|
||||||
size_t epoch;
|
size_t epoch;
|
||||||
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
|
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
|
||||||
epochs, epochSize);
|
(U32)epochs.num, (U32)epochs.size);
|
||||||
/* Loop through the epochs until there are no more segments or the dictionary
|
/* Loop through the epochs until there are no more segments or the dictionary
|
||||||
* is full.
|
* is full.
|
||||||
*/
|
*/
|
||||||
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs) {
|
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) {
|
||||||
const U32 epochBegin = (U32)(epoch * epochSize);
|
const U32 epochBegin = (U32)(epoch * epochs.size);
|
||||||
const U32 epochEnd = epochBegin + epochSize;
|
const U32 epochEnd = epochBegin + epochs.size;
|
||||||
size_t segmentSize;
|
size_t segmentSize;
|
||||||
/* Select a segment */
|
/* Select a segment */
|
||||||
COVER_segment_t segment = FASTCOVER_selectSegment(
|
COVER_segment_t segment = FASTCOVER_selectSegment(
|
||||||
ctx, freqs, epochBegin, epochEnd, parameters, segmentFreqs);
|
ctx, freqs, epochBegin, epochEnd, parameters, segmentFreqs);
|
||||||
|
|
||||||
/* If the segment covers no dmers, then we are out of content */
|
/* If the segment covers no dmers, then we are out of content.
|
||||||
|
* There may be new content in other epochs, for continue for some time.
|
||||||
|
*/
|
||||||
if (segment.score == 0) {
|
if (segment.score == 0) {
|
||||||
|
if (++zeroScoreRun >= maxZeroScoreRun) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
zeroScoreRun = 0;
|
||||||
|
|
||||||
/* Trim the segment if necessary and if it is too small then we are done */
|
/* Trim the segment if necessary and if it is too small then we are done */
|
||||||
segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);
|
segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);
|
||||||
@ -564,6 +570,7 @@ ZDICT_trainFromBuffer_fastCover(void* dictBuffer, size_t dictBufferCapacity,
|
|||||||
DISPLAYLEVEL(1, "Failed to initialize context\n");
|
DISPLAYLEVEL(1, "Failed to initialize context\n");
|
||||||
return ERROR(GENERIC);
|
return ERROR(GENERIC);
|
||||||
}
|
}
|
||||||
|
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, g_displayLevel);
|
||||||
/* Build the dictionary */
|
/* Build the dictionary */
|
||||||
DISPLAYLEVEL(2, "Building dictionary\n");
|
DISPLAYLEVEL(2, "Building dictionary\n");
|
||||||
{
|
{
|
||||||
@ -616,6 +623,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
|
|||||||
unsigned k;
|
unsigned k;
|
||||||
COVER_best_t best;
|
COVER_best_t best;
|
||||||
POOL_ctx *pool = NULL;
|
POOL_ctx *pool = NULL;
|
||||||
|
int warned = 0;
|
||||||
/* Checks */
|
/* Checks */
|
||||||
if (splitPoint <= 0 || splitPoint > 1) {
|
if (splitPoint <= 0 || splitPoint > 1) {
|
||||||
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect splitPoint\n");
|
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect splitPoint\n");
|
||||||
@ -664,6 +672,10 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
|
|||||||
POOL_free(pool);
|
POOL_free(pool);
|
||||||
return ERROR(GENERIC);
|
return ERROR(GENERIC);
|
||||||
}
|
}
|
||||||
|
if (!warned) {
|
||||||
|
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, displayLevel);
|
||||||
|
warned = 1;
|
||||||
|
}
|
||||||
/* Loop through k reusing the same context */
|
/* Loop through k reusing the same context */
|
||||||
for (k = kMinK; k <= kMaxK; k += kStepSize) {
|
for (k = kMinK; k <= kMaxK; k += kStepSize) {
|
||||||
/* Prepare the arguments */
|
/* Prepare the arguments */
|
||||||
|
@ -46,7 +46,12 @@ extern "C" {
|
|||||||
* The resulting dictionary will be saved into `dictBuffer`.
|
* The resulting dictionary will be saved into `dictBuffer`.
|
||||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||||
* or an error code, which can be tested with ZDICT_isError().
|
* or an error code, which can be tested with ZDICT_isError().
|
||||||
* Note: ZDICT_trainFromBuffer() requires about 9 bytes of memory for each input byte.
|
* Note: Dictionary training will fail if there are not enough samples to construct a
|
||||||
|
* dictionary, or if most of the samples are too small (< 8 bytes being the lower limit).
|
||||||
|
* If dictionary training fails, you should use zstd without a dictionary, as the dictionary
|
||||||
|
* would've been ineffective anyways. If you believe your samples would benefit from a dictionary
|
||||||
|
* please open an issue with details, and we can look into it.
|
||||||
|
* Note: ZDICT_trainFromBuffer()'s memory usage is about 6 MB.
|
||||||
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
||||||
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
||||||
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
||||||
@ -110,6 +115,7 @@ typedef struct {
|
|||||||
* The resulting dictionary will be saved into `dictBuffer`.
|
* The resulting dictionary will be saved into `dictBuffer`.
|
||||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||||
* or an error code, which can be tested with ZDICT_isError().
|
* or an error code, which can be tested with ZDICT_isError().
|
||||||
|
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||||
* Note: ZDICT_trainFromBuffer_cover() requires about 9 bytes of memory for each input byte.
|
* Note: ZDICT_trainFromBuffer_cover() requires about 9 bytes of memory for each input byte.
|
||||||
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
||||||
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
||||||
@ -135,6 +141,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_cover(
|
|||||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||||
* or an error code, which can be tested with ZDICT_isError().
|
* or an error code, which can be tested with ZDICT_isError().
|
||||||
* On success `*parameters` contains the parameters selected.
|
* On success `*parameters` contains the parameters selected.
|
||||||
|
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||||
* Note: ZDICT_optimizeTrainFromBuffer_cover() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread.
|
* Note: ZDICT_optimizeTrainFromBuffer_cover() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread.
|
||||||
*/
|
*/
|
||||||
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||||
@ -151,7 +158,8 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
|||||||
* The resulting dictionary will be saved into `dictBuffer`.
|
* The resulting dictionary will be saved into `dictBuffer`.
|
||||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||||
* or an error code, which can be tested with ZDICT_isError().
|
* or an error code, which can be tested with ZDICT_isError().
|
||||||
* Note: ZDICT_trainFromBuffer_fastCover() requires about 1 bytes of memory for each input byte and additionally another 6 * 2^f bytes of memory .
|
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||||
|
* Note: ZDICT_trainFromBuffer_fastCover() requires 6 * 2^f bytes of memory.
|
||||||
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
||||||
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
||||||
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
||||||
@ -177,7 +185,8 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_fastCover(void *dictBuffer,
|
|||||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||||
* or an error code, which can be tested with ZDICT_isError().
|
* or an error code, which can be tested with ZDICT_isError().
|
||||||
* On success `*parameters` contains the parameters selected.
|
* On success `*parameters` contains the parameters selected.
|
||||||
* Note: ZDICT_optimizeTrainFromBuffer_fastCover() requires about 1 byte of memory for each input byte and additionally another 6 * 2^f bytes of memory for each thread.
|
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||||
|
* Note: ZDICT_optimizeTrainFromBuffer_fastCover() requires about 6 * 2^f bytes of memory for each thread.
|
||||||
*/
|
*/
|
||||||
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer,
|
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer,
|
||||||
size_t dictBufferCapacity, const void* samplesBuffer,
|
size_t dictBufferCapacity, const void* samplesBuffer,
|
||||||
@ -219,6 +228,7 @@ typedef struct {
|
|||||||
* `parameters` is optional and can be provided with values set to 0 to mean "default".
|
* `parameters` is optional and can be provided with values set to 0 to mean "default".
|
||||||
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||||
* or an error code, which can be tested with ZDICT_isError().
|
* or an error code, which can be tested with ZDICT_isError().
|
||||||
|
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||||
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
|
||||||
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
|
||||||
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
||||||
|
@ -6,14 +6,15 @@ COPY programs\datagen.h bin\example\
|
|||||||
COPY programs\util.h bin\example\
|
COPY programs\util.h bin\example\
|
||||||
COPY programs\platform.h bin\example\
|
COPY programs\platform.h bin\example\
|
||||||
COPY lib\common\mem.h bin\example\
|
COPY lib\common\mem.h bin\example\
|
||||||
COPY lib\common\zstd_errors.h bin\example\
|
|
||||||
COPY lib\common\zstd_internal.h bin\example\
|
COPY lib\common\zstd_internal.h bin\example\
|
||||||
COPY lib\common\error_private.h bin\example\
|
COPY lib\common\error_private.h bin\example\
|
||||||
COPY lib\common\xxhash.h bin\example\
|
COPY lib\common\xxhash.h bin\example\
|
||||||
COPY lib\zstd.h bin\include\
|
|
||||||
COPY lib\libzstd.a bin\static\libzstd_static.lib
|
COPY lib\libzstd.a bin\static\libzstd_static.lib
|
||||||
COPY lib\dll\libzstd.* bin\dll\
|
COPY lib\dll\libzstd.* bin\dll\
|
||||||
COPY lib\dll\example\Makefile bin\example\
|
COPY lib\dll\example\Makefile bin\example\
|
||||||
COPY lib\dll\example\fullbench-dll.* bin\example\
|
COPY lib\dll\example\fullbench-dll.* bin\example\
|
||||||
COPY lib\dll\example\README.md bin\
|
COPY lib\dll\example\README.md bin\
|
||||||
|
COPY lib\zstd.h bin\include\
|
||||||
|
COPY lib\common\zstd_errors.h bin\include\
|
||||||
|
COPY lib\dictBuilder\zdict.h bin\include\
|
||||||
COPY programs\zstd.exe bin\zstd.exe
|
COPY programs\zstd.exe bin\zstd.exe
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
LIBRARY libzstd.dll
|
|
||||||
EXPORTS
|
|
||||||
ZDICT_getDictID
|
|
||||||
ZDICT_getErrorName
|
|
||||||
ZDICT_isError
|
|
||||||
ZDICT_trainFromBuffer
|
|
||||||
ZSTD_CStreamInSize
|
|
||||||
ZSTD_CStreamOutSize
|
|
||||||
ZSTD_DStreamInSize
|
|
||||||
ZSTD_DStreamOutSize
|
|
||||||
ZSTD_adjustCParams
|
|
||||||
ZSTD_checkCParams
|
|
||||||
ZSTD_compress
|
|
||||||
ZSTD_compressBegin
|
|
||||||
ZSTD_compressBegin_advanced
|
|
||||||
ZSTD_compressBegin_usingDict
|
|
||||||
ZSTD_compressBlock
|
|
||||||
ZSTD_compressBound
|
|
||||||
ZSTD_compressCCtx
|
|
||||||
ZSTD_compressContinue
|
|
||||||
ZSTD_compressEnd
|
|
||||||
ZSTD_compressStream
|
|
||||||
ZSTD_compress_advanced
|
|
||||||
ZSTD_compress_usingCDict
|
|
||||||
ZSTD_compress_usingDict
|
|
||||||
ZSTD_copyCCtx
|
|
||||||
ZSTD_copyDCtx
|
|
||||||
ZSTD_createCCtx
|
|
||||||
ZSTD_createCCtx_advanced
|
|
||||||
ZSTD_createCDict
|
|
||||||
ZSTD_createCDict_advanced
|
|
||||||
ZSTD_createCStream
|
|
||||||
ZSTD_createCStream_advanced
|
|
||||||
ZSTD_createDCtx
|
|
||||||
ZSTD_createDCtx_advanced
|
|
||||||
ZSTD_createDDict
|
|
||||||
ZSTD_createDStream
|
|
||||||
ZSTD_createDStream_advanced
|
|
||||||
ZSTD_decompress
|
|
||||||
ZSTD_decompressBegin
|
|
||||||
ZSTD_decompressBegin_usingDict
|
|
||||||
ZSTD_decompressBlock
|
|
||||||
ZSTD_decompressContinue
|
|
||||||
ZSTD_decompressDCtx
|
|
||||||
ZSTD_decompressStream
|
|
||||||
ZSTD_decompress_usingDDict
|
|
||||||
ZSTD_decompress_usingDict
|
|
||||||
ZSTD_endStream
|
|
||||||
ZSTD_estimateCCtxSize
|
|
||||||
ZSTD_estimateDCtxSize
|
|
||||||
ZSTD_flushStream
|
|
||||||
ZSTD_freeCCtx
|
|
||||||
ZSTD_freeCDict
|
|
||||||
ZSTD_freeCStream
|
|
||||||
ZSTD_freeDCtx
|
|
||||||
ZSTD_freeDDict
|
|
||||||
ZSTD_freeDStream
|
|
||||||
ZSTD_getBlockSizeMax
|
|
||||||
ZSTD_getCParams
|
|
||||||
ZSTD_getDecompressedSize
|
|
||||||
ZSTD_findDecompressedSize
|
|
||||||
ZSTD_getFrameContentSize
|
|
||||||
ZSTD_getErrorName
|
|
||||||
ZSTD_getFrameParams
|
|
||||||
ZSTD_getParams
|
|
||||||
ZSTD_initCStream
|
|
||||||
ZSTD_initCStream_advanced
|
|
||||||
ZSTD_initCStream_usingCDict
|
|
||||||
ZSTD_initCStream_usingDict
|
|
||||||
ZSTD_initDStream
|
|
||||||
ZSTD_initDStream_usingDDict
|
|
||||||
ZSTD_initDStream_usingDict
|
|
||||||
ZSTD_insertBlock
|
|
||||||
ZSTD_isError
|
|
||||||
ZSTD_isFrame
|
|
||||||
ZSTD_maxCLevel
|
|
||||||
ZSTD_nextInputType
|
|
||||||
ZSTD_nextSrcSizeToDecompress
|
|
||||||
ZSTD_resetCStream
|
|
||||||
ZSTD_resetDStream
|
|
||||||
ZSTD_sizeof_CCtx
|
|
||||||
ZSTD_sizeof_CDict
|
|
||||||
ZSTD_sizeof_CStream
|
|
||||||
ZSTD_sizeof_DCtx
|
|
||||||
ZSTD_sizeof_DDict
|
|
||||||
ZSTD_sizeof_DStream
|
|
||||||
ZSTD_versionNumber
|
|
@ -20,7 +20,7 @@ extern "C" {
|
|||||||
***************************************/
|
***************************************/
|
||||||
#include "mem.h" /* MEM_STATIC */
|
#include "mem.h" /* MEM_STATIC */
|
||||||
#include "error_private.h" /* ERROR */
|
#include "error_private.h" /* ERROR */
|
||||||
#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer */
|
#include "zstd_internal.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */
|
||||||
|
|
||||||
#if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0)
|
#if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0)
|
||||||
# undef ZSTD_LEGACY_SUPPORT
|
# undef ZSTD_LEGACY_SUPPORT
|
||||||
@ -178,43 +178,73 @@ MEM_STATIC size_t ZSTD_decompressLegacy(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src,
|
MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize)
|
||||||
size_t compressedSize)
|
|
||||||
{
|
{
|
||||||
U32 const version = ZSTD_isLegacy(src, compressedSize);
|
ZSTD_frameSizeInfo frameSizeInfo;
|
||||||
|
U32 const version = ZSTD_isLegacy(src, srcSize);
|
||||||
switch(version)
|
switch(version)
|
||||||
{
|
{
|
||||||
#if (ZSTD_LEGACY_SUPPORT <= 1)
|
#if (ZSTD_LEGACY_SUPPORT <= 1)
|
||||||
case 1 :
|
case 1 :
|
||||||
return ZSTDv01_findFrameCompressedSize(src, compressedSize);
|
ZSTDv01_findFrameSizeInfoLegacy(src, srcSize,
|
||||||
|
&frameSizeInfo.compressedSize,
|
||||||
|
&frameSizeInfo.decompressedBound);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if (ZSTD_LEGACY_SUPPORT <= 2)
|
#if (ZSTD_LEGACY_SUPPORT <= 2)
|
||||||
case 2 :
|
case 2 :
|
||||||
return ZSTDv02_findFrameCompressedSize(src, compressedSize);
|
ZSTDv02_findFrameSizeInfoLegacy(src, srcSize,
|
||||||
|
&frameSizeInfo.compressedSize,
|
||||||
|
&frameSizeInfo.decompressedBound);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if (ZSTD_LEGACY_SUPPORT <= 3)
|
#if (ZSTD_LEGACY_SUPPORT <= 3)
|
||||||
case 3 :
|
case 3 :
|
||||||
return ZSTDv03_findFrameCompressedSize(src, compressedSize);
|
ZSTDv03_findFrameSizeInfoLegacy(src, srcSize,
|
||||||
|
&frameSizeInfo.compressedSize,
|
||||||
|
&frameSizeInfo.decompressedBound);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if (ZSTD_LEGACY_SUPPORT <= 4)
|
#if (ZSTD_LEGACY_SUPPORT <= 4)
|
||||||
case 4 :
|
case 4 :
|
||||||
return ZSTDv04_findFrameCompressedSize(src, compressedSize);
|
ZSTDv04_findFrameSizeInfoLegacy(src, srcSize,
|
||||||
|
&frameSizeInfo.compressedSize,
|
||||||
|
&frameSizeInfo.decompressedBound);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if (ZSTD_LEGACY_SUPPORT <= 5)
|
#if (ZSTD_LEGACY_SUPPORT <= 5)
|
||||||
case 5 :
|
case 5 :
|
||||||
return ZSTDv05_findFrameCompressedSize(src, compressedSize);
|
ZSTDv05_findFrameSizeInfoLegacy(src, srcSize,
|
||||||
|
&frameSizeInfo.compressedSize,
|
||||||
|
&frameSizeInfo.decompressedBound);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if (ZSTD_LEGACY_SUPPORT <= 6)
|
#if (ZSTD_LEGACY_SUPPORT <= 6)
|
||||||
case 6 :
|
case 6 :
|
||||||
return ZSTDv06_findFrameCompressedSize(src, compressedSize);
|
ZSTDv06_findFrameSizeInfoLegacy(src, srcSize,
|
||||||
|
&frameSizeInfo.compressedSize,
|
||||||
|
&frameSizeInfo.decompressedBound);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if (ZSTD_LEGACY_SUPPORT <= 7)
|
#if (ZSTD_LEGACY_SUPPORT <= 7)
|
||||||
case 7 :
|
case 7 :
|
||||||
return ZSTDv07_findFrameCompressedSize(src, compressedSize);
|
ZSTDv07_findFrameSizeInfoLegacy(src, srcSize,
|
||||||
|
&frameSizeInfo.compressedSize,
|
||||||
|
&frameSizeInfo.decompressedBound);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default :
|
default :
|
||||||
return ERROR(prefix_unknown);
|
frameSizeInfo.compressedSize = ERROR(prefix_unknown);
|
||||||
|
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return frameSizeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize)
|
||||||
|
{
|
||||||
|
ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize);
|
||||||
|
return frameSizeInfo.compressedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)
|
MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)
|
||||||
|
@ -1336,6 +1336,8 @@ static const U32 ZSTD_magicNumber = 0xFD2FB51E; /* 3rd version : seqNb header
|
|||||||
#define LITERAL_NOENTROPY 63
|
#define LITERAL_NOENTROPY 63
|
||||||
#define COMMAND_NOENTROPY 7 /* to remove */
|
#define COMMAND_NOENTROPY 7 /* to remove */
|
||||||
|
|
||||||
|
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||||
|
|
||||||
static const size_t ZSTD_blockHeaderSize = 3;
|
static const size_t ZSTD_blockHeaderSize = 3;
|
||||||
static const size_t ZSTD_frameHeaderSize = 4;
|
static const size_t ZSTD_frameHeaderSize = 4;
|
||||||
|
|
||||||
@ -1757,7 +1759,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
|||||||
BYTE* const base, BYTE* const oend)
|
BYTE* const base, BYTE* const oend)
|
||||||
{
|
{
|
||||||
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
||||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */
|
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
|
||||||
const BYTE* const ostart = op;
|
const BYTE* const ostart = op;
|
||||||
const size_t litLength = sequence.litLength;
|
const size_t litLength = sequence.litLength;
|
||||||
BYTE* const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
BYTE* const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
||||||
@ -1999,36 +2001,59 @@ size_t ZSTDv01_decompress(void* dst, size_t maxDstSize, const void* src, size_t
|
|||||||
return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
|
return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTDv01_findFrameCompressedSize(const void* src, size_t srcSize)
|
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||||
|
assumes `cSize` and `dBound` are _not_ NULL */
|
||||||
|
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||||
|
{
|
||||||
|
*cSize = ret;
|
||||||
|
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||||
{
|
{
|
||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
size_t remainingSize = srcSize;
|
size_t remainingSize = srcSize;
|
||||||
|
size_t nbBlocks = 0;
|
||||||
U32 magicNumber;
|
U32 magicNumber;
|
||||||
blockProperties_t blockProperties;
|
blockProperties_t blockProperties;
|
||||||
|
|
||||||
/* Frame Header */
|
/* Frame Header */
|
||||||
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
magicNumber = ZSTD_readBE32(src);
|
magicNumber = ZSTD_readBE32(src);
|
||||||
if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
|
if (magicNumber != ZSTD_magicNumber) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||||
|
return;
|
||||||
|
}
|
||||||
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
|
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
|
||||||
|
|
||||||
/* Loop on each block */
|
/* Loop on each block */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties);
|
size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||||
if (ZSTDv01_isError(blockSize)) return blockSize;
|
if (ZSTDv01_isError(blockSize)) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, blockSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ip += ZSTD_blockHeaderSize;
|
ip += ZSTD_blockHeaderSize;
|
||||||
remainingSize -= ZSTD_blockHeaderSize;
|
remainingSize -= ZSTD_blockHeaderSize;
|
||||||
if (blockSize > remainingSize) return ERROR(srcSize_wrong);
|
if (blockSize > remainingSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (blockSize == 0) break; /* bt_end */
|
if (blockSize == 0) break; /* bt_end */
|
||||||
|
|
||||||
ip += blockSize;
|
ip += blockSize;
|
||||||
remainingSize -= blockSize;
|
remainingSize -= blockSize;
|
||||||
|
nbBlocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip - (const BYTE*)src;
|
*cSize = ip - (const BYTE*)src;
|
||||||
|
*dBound = nbBlocks * BLOCKSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************
|
/*******************************
|
||||||
|
@ -36,12 +36,17 @@ size_t ZSTDv01_decompress( void* dst, size_t maxOriginalSize,
|
|||||||
const void* src, size_t compressedSize);
|
const void* src, size_t compressedSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv01_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.1.x format
|
ZSTDv01_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.1.x format
|
||||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||||
return : the number of bytes that would be read to decompress this frame
|
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||||
or an errorCode if it fails (which can be tested using ZSTDv01_isError())
|
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||||
|
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||||
|
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||||
|
|
||||||
|
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||||
*/
|
*/
|
||||||
size_t ZSTDv01_findFrameCompressedSize(const void* src, size_t compressedSize);
|
void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||||
|
size_t* cSize, unsigned long long* dBound);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error
|
ZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error
|
||||||
|
@ -2728,6 +2728,8 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
|
|||||||
#define LITERAL_NOENTROPY 63
|
#define LITERAL_NOENTROPY 63
|
||||||
#define COMMAND_NOENTROPY 7 /* to remove */
|
#define COMMAND_NOENTROPY 7 /* to remove */
|
||||||
|
|
||||||
|
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||||
|
|
||||||
static const size_t ZSTD_blockHeaderSize = 3;
|
static const size_t ZSTD_blockHeaderSize = 3;
|
||||||
static const size_t ZSTD_frameHeaderSize = 4;
|
static const size_t ZSTD_frameHeaderSize = 4;
|
||||||
|
|
||||||
@ -3096,7 +3098,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
|||||||
BYTE* const base, BYTE* const oend)
|
BYTE* const base, BYTE* const oend)
|
||||||
{
|
{
|
||||||
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
||||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */
|
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
|
||||||
const BYTE* const ostart = op;
|
const BYTE* const ostart = op;
|
||||||
BYTE* const oLitEnd = op + sequence.litLength;
|
BYTE* const oLitEnd = op + sequence.litLength;
|
||||||
BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
||||||
@ -3312,37 +3314,59 @@ static size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, siz
|
|||||||
return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
|
return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||||
|
assumes `cSize` and `dBound` are _not_ NULL */
|
||||||
|
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||||
{
|
{
|
||||||
|
*cSize = ret;
|
||||||
|
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||||
|
{
|
||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
size_t remainingSize = srcSize;
|
size_t remainingSize = srcSize;
|
||||||
|
size_t nbBlocks = 0;
|
||||||
U32 magicNumber;
|
U32 magicNumber;
|
||||||
blockProperties_t blockProperties;
|
blockProperties_t blockProperties;
|
||||||
|
|
||||||
/* Frame Header */
|
/* Frame Header */
|
||||||
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
magicNumber = MEM_readLE32(src);
|
magicNumber = MEM_readLE32(src);
|
||||||
if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
|
if (magicNumber != ZSTD_magicNumber) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||||
|
return;
|
||||||
|
}
|
||||||
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
|
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
|
||||||
|
|
||||||
/* Loop on each block */
|
/* Loop on each block */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
if (ZSTD_isError(cBlockSize)) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ip += ZSTD_blockHeaderSize;
|
ip += ZSTD_blockHeaderSize;
|
||||||
remainingSize -= ZSTD_blockHeaderSize;
|
remainingSize -= ZSTD_blockHeaderSize;
|
||||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
if (cBlockSize > remainingSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cBlockSize == 0) break; /* bt_end */
|
if (cBlockSize == 0) break; /* bt_end */
|
||||||
|
|
||||||
ip += cBlockSize;
|
ip += cBlockSize;
|
||||||
remainingSize -= cBlockSize;
|
remainingSize -= cBlockSize;
|
||||||
|
nbBlocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip - (const BYTE*)src;
|
*cSize = ip - (const BYTE*)src;
|
||||||
|
*dBound = nbBlocks * BLOCKSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************
|
/*******************************
|
||||||
@ -3458,11 +3482,6 @@ size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,
|
|||||||
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTDv02_findFrameCompressedSize(const void *src, size_t compressedSize)
|
|
||||||
{
|
|
||||||
return ZSTD_findFrameCompressedSize(src, compressedSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZSTDv02_Dctx* ZSTDv02_createDCtx(void)
|
ZSTDv02_Dctx* ZSTDv02_createDCtx(void)
|
||||||
{
|
{
|
||||||
return (ZSTDv02_Dctx*)ZSTD_createDCtx();
|
return (ZSTDv02_Dctx*)ZSTD_createDCtx();
|
||||||
|
@ -36,12 +36,17 @@ size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,
|
|||||||
const void* src, size_t compressedSize);
|
const void* src, size_t compressedSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv02_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.2.x format
|
ZSTDv02_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.2.x format
|
||||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||||
return : the number of bytes that would be read to decompress this frame
|
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||||
or an errorCode if it fails (which can be tested using ZSTDv02_isError())
|
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||||
|
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||||
|
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||||
|
|
||||||
|
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||||
*/
|
*/
|
||||||
size_t ZSTDv02_findFrameCompressedSize(const void* src, size_t compressedSize);
|
void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||||
|
size_t* cSize, unsigned long long* dBound);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv02_isError() : tells if the result of ZSTDv02_decompress() is an error
|
ZSTDv02_isError() : tells if the result of ZSTDv02_decompress() is an error
|
||||||
|
@ -2369,6 +2369,8 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
|
|||||||
#define LITERAL_NOENTROPY 63
|
#define LITERAL_NOENTROPY 63
|
||||||
#define COMMAND_NOENTROPY 7 /* to remove */
|
#define COMMAND_NOENTROPY 7 /* to remove */
|
||||||
|
|
||||||
|
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||||
|
|
||||||
static const size_t ZSTD_blockHeaderSize = 3;
|
static const size_t ZSTD_blockHeaderSize = 3;
|
||||||
static const size_t ZSTD_frameHeaderSize = 4;
|
static const size_t ZSTD_frameHeaderSize = 4;
|
||||||
|
|
||||||
@ -2737,7 +2739,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
|||||||
BYTE* const base, BYTE* const oend)
|
BYTE* const base, BYTE* const oend)
|
||||||
{
|
{
|
||||||
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
||||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */
|
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
|
||||||
const BYTE* const ostart = op;
|
const BYTE* const ostart = op;
|
||||||
BYTE* const oLitEnd = op + sequence.litLength;
|
BYTE* const oLitEnd = op + sequence.litLength;
|
||||||
BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
||||||
@ -2953,36 +2955,59 @@ static size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, siz
|
|||||||
return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
|
return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
|
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||||
|
assumes `cSize` and `dBound` are _not_ NULL */
|
||||||
|
MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||||
|
{
|
||||||
|
*cSize = ret;
|
||||||
|
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||||
{
|
{
|
||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
size_t remainingSize = srcSize;
|
size_t remainingSize = srcSize;
|
||||||
|
size_t nbBlocks = 0;
|
||||||
U32 magicNumber;
|
U32 magicNumber;
|
||||||
blockProperties_t blockProperties;
|
blockProperties_t blockProperties;
|
||||||
|
|
||||||
/* Frame Header */
|
/* Frame Header */
|
||||||
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
magicNumber = MEM_readLE32(src);
|
magicNumber = MEM_readLE32(src);
|
||||||
if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
|
if (magicNumber != ZSTD_magicNumber) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||||
|
return;
|
||||||
|
}
|
||||||
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
|
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
|
||||||
|
|
||||||
/* Loop on each block */
|
/* Loop on each block */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
if (ZSTD_isError(cBlockSize)) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ip += ZSTD_blockHeaderSize;
|
ip += ZSTD_blockHeaderSize;
|
||||||
remainingSize -= ZSTD_blockHeaderSize;
|
remainingSize -= ZSTD_blockHeaderSize;
|
||||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
if (cBlockSize > remainingSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cBlockSize == 0) break; /* bt_end */
|
if (cBlockSize == 0) break; /* bt_end */
|
||||||
|
|
||||||
ip += cBlockSize;
|
ip += cBlockSize;
|
||||||
remainingSize -= cBlockSize;
|
remainingSize -= cBlockSize;
|
||||||
|
nbBlocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip - (const BYTE*)src;
|
*cSize = ip - (const BYTE*)src;
|
||||||
|
*dBound = nbBlocks * BLOCKSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3099,11 +3124,6 @@ size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,
|
|||||||
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t srcSize)
|
|
||||||
{
|
|
||||||
return ZSTD_findFrameCompressedSize(src, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZSTDv03_Dctx* ZSTDv03_createDCtx(void)
|
ZSTDv03_Dctx* ZSTDv03_createDCtx(void)
|
||||||
{
|
{
|
||||||
return (ZSTDv03_Dctx*)ZSTD_createDCtx();
|
return (ZSTDv03_Dctx*)ZSTD_createDCtx();
|
||||||
|
@ -36,12 +36,17 @@ size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,
|
|||||||
const void* src, size_t compressedSize);
|
const void* src, size_t compressedSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv03_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.3.x format
|
ZSTDv03_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.3.x format
|
||||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||||
return : the number of bytes that would be read to decompress this frame
|
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||||
or an errorCode if it fails (which can be tested using ZSTDv03_isError())
|
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||||
|
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||||
|
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||||
|
|
||||||
|
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||||
*/
|
*/
|
||||||
size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t compressedSize);
|
void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||||
|
size_t* cSize, unsigned long long* dBound);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv03_isError() : tells if the result of ZSTDv03_decompress() is an error
|
ZSTDv03_isError() : tells if the result of ZSTDv03_decompress() is an error
|
||||||
|
@ -373,6 +373,8 @@ static const size_t ZSTD_frameHeaderSize_min = 5;
|
|||||||
#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)
|
#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)
|
||||||
#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)
|
#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)
|
||||||
|
|
||||||
|
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||||
|
|
||||||
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
||||||
|
|
||||||
|
|
||||||
@ -2860,7 +2862,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
|||||||
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
||||||
{
|
{
|
||||||
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
||||||
BYTE* const oLitEnd = op + sequence.litLength;
|
BYTE* const oLitEnd = op + sequence.litLength;
|
||||||
const size_t sequenceLength = sequence.litLength + sequence.matchLength;
|
const size_t sequenceLength = sequence.litLength + sequence.matchLength;
|
||||||
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
||||||
@ -3119,34 +3121,57 @@ static size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx,
|
|||||||
return op-ostart;
|
return op-ostart;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
|
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||||
|
assumes `cSize` and `dBound` are _not_ NULL */
|
||||||
|
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||||
|
{
|
||||||
|
*cSize = ret;
|
||||||
|
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||||
{
|
{
|
||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
size_t remainingSize = srcSize;
|
size_t remainingSize = srcSize;
|
||||||
|
size_t nbBlocks = 0;
|
||||||
blockProperties_t blockProperties;
|
blockProperties_t blockProperties;
|
||||||
|
|
||||||
/* Frame Header */
|
/* Frame Header */
|
||||||
if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);
|
if (srcSize < ZSTD_frameHeaderSize_min) {
|
||||||
if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||||
|
return;
|
||||||
|
}
|
||||||
ip += ZSTD_frameHeaderSize_min; remainingSize -= ZSTD_frameHeaderSize_min;
|
ip += ZSTD_frameHeaderSize_min; remainingSize -= ZSTD_frameHeaderSize_min;
|
||||||
|
|
||||||
/* Loop on each block */
|
/* Loop on each block */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
if (ZSTD_isError(cBlockSize)) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ip += ZSTD_blockHeaderSize;
|
ip += ZSTD_blockHeaderSize;
|
||||||
remainingSize -= ZSTD_blockHeaderSize;
|
remainingSize -= ZSTD_blockHeaderSize;
|
||||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
if (cBlockSize > remainingSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cBlockSize == 0) break; /* bt_end */
|
if (cBlockSize == 0) break; /* bt_end */
|
||||||
|
|
||||||
ip += cBlockSize;
|
ip += cBlockSize;
|
||||||
remainingSize -= cBlockSize;
|
remainingSize -= cBlockSize;
|
||||||
|
nbBlocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip - (const BYTE*)src;
|
*cSize = ip - (const BYTE*)src;
|
||||||
|
*dBound = nbBlocks * BLOCKSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ******************************
|
/* ******************************
|
||||||
@ -3578,11 +3603,6 @@ size_t ZSTDv04_decompress(void* dst, size_t maxDstSize, const void* src, size_t
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTDv04_findFrameCompressedSize(const void* src, size_t srcSize)
|
|
||||||
{
|
|
||||||
return ZSTD_findFrameCompressedSize(src, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx) { return ZSTD_resetDCtx(dctx); }
|
size_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx) { return ZSTD_resetDCtx(dctx); }
|
||||||
|
|
||||||
size_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx)
|
size_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx)
|
||||||
|
@ -36,12 +36,17 @@ size_t ZSTDv04_decompress( void* dst, size_t maxOriginalSize,
|
|||||||
const void* src, size_t compressedSize);
|
const void* src, size_t compressedSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv04_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.4.x format
|
ZSTDv04_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.4.x format
|
||||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||||
return : the number of bytes that would be read to decompress this frame
|
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||||
or an errorCode if it fails (which can be tested using ZSTDv04_isError())
|
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||||
|
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||||
|
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||||
|
|
||||||
|
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||||
*/
|
*/
|
||||||
size_t ZSTDv04_findFrameCompressedSize(const void* src, size_t compressedSize);
|
void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||||
|
size_t* cSize, unsigned long long* dBound);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv04_isError() : tells if the result of ZSTDv04_decompress() is an error
|
ZSTDv04_isError() : tells if the result of ZSTDv04_decompress() is an error
|
||||||
|
@ -491,6 +491,8 @@ static const size_t ZSTDv05_frameHeaderSize_min = 5;
|
|||||||
|
|
||||||
#define WILDCOPY_OVERLENGTH 8
|
#define WILDCOPY_OVERLENGTH 8
|
||||||
|
|
||||||
|
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||||
|
|
||||||
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
||||||
|
|
||||||
|
|
||||||
@ -3217,7 +3219,7 @@ static size_t ZSTDv05_execSequence(BYTE* op,
|
|||||||
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
||||||
{
|
{
|
||||||
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
||||||
BYTE* const oLitEnd = op + sequence.litLength;
|
BYTE* const oLitEnd = op + sequence.litLength;
|
||||||
const size_t sequenceLength = sequence.litLength + sequence.matchLength;
|
const size_t sequenceLength = sequence.litLength + sequence.matchLength;
|
||||||
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
||||||
@ -3508,34 +3510,57 @@ size_t ZSTDv05_decompress(void* dst, size_t maxDstSize, const void* src, size_t
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTDv05_findFrameCompressedSize(const void *src, size_t srcSize)
|
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||||
|
assumes `cSize` and `dBound` are _not_ NULL */
|
||||||
|
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||||
|
{
|
||||||
|
*cSize = ret;
|
||||||
|
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||||
{
|
{
|
||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
size_t remainingSize = srcSize;
|
size_t remainingSize = srcSize;
|
||||||
|
size_t nbBlocks = 0;
|
||||||
blockProperties_t blockProperties;
|
blockProperties_t blockProperties;
|
||||||
|
|
||||||
/* Frame Header */
|
/* Frame Header */
|
||||||
if (srcSize < ZSTDv05_frameHeaderSize_min) return ERROR(srcSize_wrong);
|
if (srcSize < ZSTDv05_frameHeaderSize_min) {
|
||||||
if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||||
|
return;
|
||||||
|
}
|
||||||
ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min;
|
ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min;
|
||||||
|
|
||||||
/* Loop on each block */
|
/* Loop on each block */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties);
|
size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||||
if (ZSTDv05_isError(cBlockSize)) return cBlockSize;
|
if (ZSTDv05_isError(cBlockSize)) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ip += ZSTDv05_blockHeaderSize;
|
ip += ZSTDv05_blockHeaderSize;
|
||||||
remainingSize -= ZSTDv05_blockHeaderSize;
|
remainingSize -= ZSTDv05_blockHeaderSize;
|
||||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
if (cBlockSize > remainingSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cBlockSize == 0) break; /* bt_end */
|
if (cBlockSize == 0) break; /* bt_end */
|
||||||
|
|
||||||
ip += cBlockSize;
|
ip += cBlockSize;
|
||||||
remainingSize -= cBlockSize;
|
remainingSize -= cBlockSize;
|
||||||
|
nbBlocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip - (const BYTE*)src;
|
*cSize = ip - (const BYTE*)src;
|
||||||
|
*dBound = nbBlocks * BLOCKSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ******************************
|
/* ******************************
|
||||||
|
@ -34,12 +34,17 @@ size_t ZSTDv05_decompress( void* dst, size_t dstCapacity,
|
|||||||
const void* src, size_t compressedSize);
|
const void* src, size_t compressedSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv05_getFrameSrcSize() : get the source length of a ZSTD frame
|
ZSTDv05_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.5.x format
|
||||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||||
return : the number of bytes that would be read to decompress this frame
|
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||||
or an errorCode if it fails (which can be tested using ZSTDv05_isError())
|
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||||
|
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||||
|
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||||
|
|
||||||
|
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||||
*/
|
*/
|
||||||
size_t ZSTDv05_findFrameCompressedSize(const void* src, size_t compressedSize);
|
void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||||
|
size_t* cSize, unsigned long long* dBound);
|
||||||
|
|
||||||
/* *************************************
|
/* *************************************
|
||||||
* Helper functions
|
* Helper functions
|
||||||
|
@ -506,6 +506,8 @@ typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
|||||||
#define FSEv06_ENCODING_STATIC 2
|
#define FSEv06_ENCODING_STATIC 2
|
||||||
#define FSEv06_ENCODING_DYNAMIC 3
|
#define FSEv06_ENCODING_DYNAMIC 3
|
||||||
|
|
||||||
|
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||||
|
|
||||||
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
|
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
|
||||||
13,14,15,16 };
|
13,14,15,16 };
|
||||||
@ -3406,7 +3408,7 @@ static size_t ZSTDv06_execSequence(BYTE* op,
|
|||||||
if (sequence.offset < 8) {
|
if (sequence.offset < 8) {
|
||||||
/* close range match, overlap */
|
/* close range match, overlap */
|
||||||
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
||||||
int const sub2 = dec64table[sequence.offset];
|
int const sub2 = dec64table[sequence.offset];
|
||||||
op[0] = match[0];
|
op[0] = match[0];
|
||||||
op[1] = match[1];
|
op[1] = match[1];
|
||||||
@ -3654,36 +3656,62 @@ size_t ZSTDv06_decompress(void* dst, size_t dstCapacity, const void* src, size_t
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTDv06_findFrameCompressedSize(const void* src, size_t srcSize)
|
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||||
|
assumes `cSize` and `dBound` are _not_ NULL */
|
||||||
|
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||||
|
{
|
||||||
|
*cSize = ret;
|
||||||
|
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||||
{
|
{
|
||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
size_t remainingSize = srcSize;
|
size_t remainingSize = srcSize;
|
||||||
|
size_t nbBlocks = 0;
|
||||||
blockProperties_t blockProperties = { bt_compressed, 0 };
|
blockProperties_t blockProperties = { bt_compressed, 0 };
|
||||||
|
|
||||||
/* Frame Header */
|
/* Frame Header */
|
||||||
{ size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);
|
{ size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);
|
||||||
if (ZSTDv06_isError(frameHeaderSize)) return frameHeaderSize;
|
if (ZSTDv06_isError(frameHeaderSize)) {
|
||||||
if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) return ERROR(prefix_unknown);
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);
|
||||||
if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);
|
return;
|
||||||
|
}
|
||||||
|
if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop on each block */
|
/* Loop on each block */
|
||||||
while (1) {
|
while (1) {
|
||||||
size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, remainingSize, &blockProperties);
|
size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||||
if (ZSTDv06_isError(cBlockSize)) return cBlockSize;
|
if (ZSTDv06_isError(cBlockSize)) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ip += ZSTDv06_blockHeaderSize;
|
ip += ZSTDv06_blockHeaderSize;
|
||||||
remainingSize -= ZSTDv06_blockHeaderSize;
|
remainingSize -= ZSTDv06_blockHeaderSize;
|
||||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
if (cBlockSize > remainingSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cBlockSize == 0) break; /* bt_end */
|
if (cBlockSize == 0) break; /* bt_end */
|
||||||
|
|
||||||
ip += cBlockSize;
|
ip += cBlockSize;
|
||||||
remainingSize -= cBlockSize;
|
remainingSize -= cBlockSize;
|
||||||
|
nbBlocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip - (const BYTE*)src;
|
*cSize = ip - (const BYTE*)src;
|
||||||
|
*dBound = nbBlocks * ZSTDv06_BLOCKSIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*_******************************
|
/*_******************************
|
||||||
|
@ -43,12 +43,17 @@ ZSTDLIBv06_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity,
|
|||||||
const void* src, size_t compressedSize);
|
const void* src, size_t compressedSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv06_getFrameSrcSize() : get the source length of a ZSTD frame
|
ZSTDv06_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.6.x format
|
||||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||||
return : the number of bytes that would be read to decompress this frame
|
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||||
or an errorCode if it fails (which can be tested using ZSTDv06_isError())
|
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||||
|
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||||
|
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||||
|
|
||||||
|
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||||
*/
|
*/
|
||||||
size_t ZSTDv06_findFrameCompressedSize(const void* src, size_t compressedSize);
|
void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||||
|
size_t* cSize, unsigned long long* dBound);
|
||||||
|
|
||||||
/* *************************************
|
/* *************************************
|
||||||
* Helper functions
|
* Helper functions
|
||||||
|
@ -2740,6 +2740,8 @@ typedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t;
|
|||||||
#define FSEv07_ENCODING_STATIC 2
|
#define FSEv07_ENCODING_STATIC 2
|
||||||
#define FSEv07_ENCODING_DYNAMIC 3
|
#define FSEv07_ENCODING_DYNAMIC 3
|
||||||
|
|
||||||
|
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||||
|
|
||||||
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
|
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
|
||||||
13,14,15,16 };
|
13,14,15,16 };
|
||||||
@ -3631,7 +3633,7 @@ size_t ZSTDv07_execSequence(BYTE* op,
|
|||||||
if (sequence.offset < 8) {
|
if (sequence.offset < 8) {
|
||||||
/* close range match, overlap */
|
/* close range match, overlap */
|
||||||
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
||||||
int const sub2 = dec64table[sequence.offset];
|
int const sub2 = dec64table[sequence.offset];
|
||||||
op[0] = match[0];
|
op[0] = match[0];
|
||||||
op[1] = match[1];
|
op[1] = match[1];
|
||||||
@ -3895,19 +3897,40 @@ size_t ZSTDv07_decompress(void* dst, size_t dstCapacity, const void* src, size_t
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t srcSize)
|
/* ZSTD_errorFrameSizeInfoLegacy() :
|
||||||
|
assumes `cSize` and `dBound` are _not_ NULL */
|
||||||
|
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
|
||||||
|
{
|
||||||
|
*cSize = ret;
|
||||||
|
*dBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
|
||||||
{
|
{
|
||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
size_t remainingSize = srcSize;
|
size_t remainingSize = srcSize;
|
||||||
|
size_t nbBlocks = 0;
|
||||||
|
|
||||||
/* check */
|
/* check */
|
||||||
if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
|
if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Frame Header */
|
/* Frame Header */
|
||||||
{ size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);
|
{ size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);
|
||||||
if (ZSTDv07_isError(frameHeaderSize)) return frameHeaderSize;
|
if (ZSTDv07_isError(frameHeaderSize)) {
|
||||||
if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) return ERROR(prefix_unknown);
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);
|
||||||
if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
|
return;
|
||||||
|
}
|
||||||
|
if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3915,20 +3938,28 @@ size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t srcSize)
|
|||||||
while (1) {
|
while (1) {
|
||||||
blockProperties_t blockProperties;
|
blockProperties_t blockProperties;
|
||||||
size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties);
|
size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties);
|
||||||
if (ZSTDv07_isError(cBlockSize)) return cBlockSize;
|
if (ZSTDv07_isError(cBlockSize)) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ip += ZSTDv07_blockHeaderSize;
|
ip += ZSTDv07_blockHeaderSize;
|
||||||
remainingSize -= ZSTDv07_blockHeaderSize;
|
remainingSize -= ZSTDv07_blockHeaderSize;
|
||||||
|
|
||||||
if (blockProperties.blockType == bt_end) break;
|
if (blockProperties.blockType == bt_end) break;
|
||||||
|
|
||||||
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
if (cBlockSize > remainingSize) {
|
||||||
|
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ip += cBlockSize;
|
ip += cBlockSize;
|
||||||
remainingSize -= cBlockSize;
|
remainingSize -= cBlockSize;
|
||||||
|
nbBlocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip - (const BYTE*)src;
|
*cSize = ip - (const BYTE*)src;
|
||||||
|
*dBound = nbBlocks * ZSTDv07_BLOCKSIZE_ABSOLUTEMAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*_******************************
|
/*_******************************
|
||||||
|
@ -50,12 +50,17 @@ ZSTDLIBv07_API size_t ZSTDv07_decompress( void* dst, size_t dstCapacity,
|
|||||||
const void* src, size_t compressedSize);
|
const void* src, size_t compressedSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ZSTDv07_getFrameSrcSize() : get the source length of a ZSTD frame
|
ZSTDv07_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.7.x format
|
||||||
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
|
||||||
return : the number of bytes that would be read to decompress this frame
|
cSize (output parameter) : the number of bytes that would be read to decompress this frame
|
||||||
or an errorCode if it fails (which can be tested using ZSTDv07_isError())
|
or an error code if it fails (which can be tested using ZSTDv01_isError())
|
||||||
|
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
|
||||||
|
or ZSTD_CONTENTSIZE_ERROR if an error occurs
|
||||||
|
|
||||||
|
note : assumes `cSize` and `dBound` are _not_ NULL.
|
||||||
*/
|
*/
|
||||||
size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t compressedSize);
|
void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
|
||||||
|
size_t* cSize, unsigned long long* dBound);
|
||||||
|
|
||||||
/*====== Helper functions ======*/
|
/*====== Helper functions ======*/
|
||||||
ZSTDLIBv07_API unsigned ZSTDv07_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
|
ZSTDLIBv07_API unsigned ZSTDv07_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
|
||||||
|
1071
lib/zstd.h
1071
lib/zstd.h
File diff suppressed because it is too large
Load Diff
@ -51,7 +51,7 @@ endif
|
|||||||
CFLAGS ?= -O3
|
CFLAGS ?= -O3
|
||||||
DEBUGFLAGS+=-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
DEBUGFLAGS+=-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||||
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \
|
-Wstrict-prototypes -Wundef -Wpointer-arith \
|
||||||
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
|
||||||
-Wredundant-decls -Wmissing-prototypes -Wc++-compat
|
-Wredundant-decls -Wmissing-prototypes -Wc++-compat
|
||||||
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||||
@ -165,7 +165,7 @@ $(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP)
|
|||||||
zstd : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) $(LZ4CPP)
|
zstd : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) $(LZ4CPP)
|
||||||
zstd : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD)
|
zstd : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD)
|
||||||
zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
||||||
zstd : $(ZSTDLIB_FILES) zstdcli.o util.o fileio.o benchfn.o benchzstd.o datagen.o dibio.o
|
zstd : $(ZSTDLIB_FILES) zstdcli.o util.o timefn.o fileio.o benchfn.o benchzstd.o datagen.o dibio.o
|
||||||
@echo "$(THREAD_MSG)"
|
@echo "$(THREAD_MSG)"
|
||||||
@echo "$(ZLIB_MSG)"
|
@echo "$(ZLIB_MSG)"
|
||||||
@echo "$(LZMA_MSG)"
|
@echo "$(LZMA_MSG)"
|
||||||
@ -183,13 +183,13 @@ zstd-release: zstd
|
|||||||
zstd32 : CPPFLAGS += $(THREAD_CPP)
|
zstd32 : CPPFLAGS += $(THREAD_CPP)
|
||||||
zstd32 : LDFLAGS += $(THREAD_LD)
|
zstd32 : LDFLAGS += $(THREAD_LD)
|
||||||
zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
||||||
zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c
|
zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c timefn.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c
|
||||||
ifneq (,$(filter Windows%,$(OS)))
|
ifneq (,$(filter Windows%,$(OS)))
|
||||||
windres/generate_res.bat
|
windres/generate_res.bat
|
||||||
endif
|
endif
|
||||||
$(CC) -m32 $(FLAGS) $^ $(RES32_FILE) -o $@$(EXT)
|
$(CC) -m32 $(FLAGS) $^ $(RES32_FILE) -o $@$(EXT)
|
||||||
|
|
||||||
zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o util.o fileio.c benchfn.o benchzstd.o datagen.o dibio.o
|
zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o util.o fileio.c benchfn.o benchzstd.o timefn.o datagen.o dibio.o
|
||||||
$(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS)
|
$(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS)
|
||||||
|
|
||||||
zstd-nomt : THREAD_CPP :=
|
zstd-nomt : THREAD_CPP :=
|
||||||
@ -222,13 +222,13 @@ zstd-pgo :
|
|||||||
|
|
||||||
# minimal target, with only zstd compression and decompression. no bench. no legacy.
|
# minimal target, with only zstd compression and decompression. no bench. no legacy.
|
||||||
zstd-small: CFLAGS = -Os -s
|
zstd-small: CFLAGS = -Os -s
|
||||||
zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c util.c fileio.c
|
zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c util.c timefn.c fileio.c
|
||||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o $@$(EXT)
|
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o $@$(EXT)
|
||||||
|
|
||||||
zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c util.c fileio.c
|
zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c util.c timefn.c fileio.c
|
||||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o $@$(EXT)
|
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o $@$(EXT)
|
||||||
|
|
||||||
zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c util.c fileio.c
|
zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c util.c timefn.c fileio.c
|
||||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT)
|
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT)
|
||||||
|
|
||||||
zstdmt: zstd
|
zstdmt: zstd
|
||||||
@ -265,9 +265,9 @@ man: zstd.1 zstdgrep.1 zstdless.1
|
|||||||
|
|
||||||
.PHONY: clean-man
|
.PHONY: clean-man
|
||||||
clean-man:
|
clean-man:
|
||||||
rm zstd.1
|
$(RM) zstd.1
|
||||||
rm zstdgrep.1
|
$(RM) zstdgrep.1
|
||||||
rm zstdless.1
|
$(RM) zstdless.1
|
||||||
|
|
||||||
.PHONY: preview-man
|
.PHONY: preview-man
|
||||||
preview-man: clean-man man
|
preview-man: clean-man man
|
||||||
|
@ -13,25 +13,20 @@
|
|||||||
/* *************************************
|
/* *************************************
|
||||||
* Includes
|
* Includes
|
||||||
***************************************/
|
***************************************/
|
||||||
#include "platform.h" /* Large Files support */
|
|
||||||
#include "util.h" /* UTIL_getFileSize, UTIL_sleep */
|
|
||||||
#include <stdlib.h> /* malloc, free */
|
#include <stdlib.h> /* malloc, free */
|
||||||
#include <string.h> /* memset */
|
#include <string.h> /* memset */
|
||||||
#include <stdio.h> /* fprintf, fopen */
|
|
||||||
#undef NDEBUG /* assert must not be disabled */
|
#undef NDEBUG /* assert must not be disabled */
|
||||||
#include <assert.h> /* assert */
|
#include <assert.h> /* assert */
|
||||||
|
|
||||||
#include "mem.h"
|
#include "timefn.h" /* UTIL_time_t, UTIL_getTime */
|
||||||
#include "benchfn.h"
|
#include "benchfn.h"
|
||||||
|
|
||||||
|
|
||||||
/* *************************************
|
/* *************************************
|
||||||
* Constants
|
* Constants
|
||||||
***************************************/
|
***************************************/
|
||||||
#define TIMELOOP_MICROSEC (1*1000000ULL) /* 1 second */
|
#define TIMELOOP_MICROSEC SEC_TO_MICRO /* 1 second */
|
||||||
#define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */
|
#define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */
|
||||||
#define ACTIVEPERIOD_MICROSEC (70*TIMELOOP_MICROSEC) /* 70 seconds */
|
|
||||||
#define COOLPERIOD_SEC 10
|
|
||||||
|
|
||||||
#define KB *(1 <<10)
|
#define KB *(1 <<10)
|
||||||
#define MB *(1 <<20)
|
#define MB *(1 <<20)
|
||||||
@ -39,14 +34,16 @@
|
|||||||
|
|
||||||
|
|
||||||
/* *************************************
|
/* *************************************
|
||||||
* Errors
|
* Debug errors
|
||||||
***************************************/
|
***************************************/
|
||||||
#ifndef DEBUG
|
#if defined(DEBUG) && (DEBUG >= 1)
|
||||||
# define DEBUG 0
|
# include <stdio.h> /* fprintf */
|
||||||
#endif
|
|
||||||
|
|
||||||
# define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
# define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||||
# define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }
|
# define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }
|
||||||
|
#else
|
||||||
|
# define DEBUGOUTPUT(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* error without displaying */
|
/* error without displaying */
|
||||||
#define RETURN_QUIET_ERROR(retValue, ...) { \
|
#define RETURN_QUIET_ERROR(retValue, ...) { \
|
||||||
@ -116,15 +113,7 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
|
|||||||
{ size_t i;
|
{ size_t i;
|
||||||
for(i = 0; i < p.blockCount; i++) {
|
for(i = 0; i < p.blockCount; i++) {
|
||||||
memset(p.dstBuffers[i], 0xE5, p.dstCapacities[i]); /* warm up and erase result buffer */
|
memset(p.dstBuffers[i], 0xE5, p.dstCapacities[i]); /* warm up and erase result buffer */
|
||||||
}
|
} }
|
||||||
#if 0
|
|
||||||
/* based on testing these seem to lower accuracy of multiple calls of 1 nbLoops vs 1 call of multiple nbLoops
|
|
||||||
* (Makes former slower)
|
|
||||||
*/
|
|
||||||
UTIL_sleepMilli(5); /* give processor time to other processes */
|
|
||||||
UTIL_waitForNextTick();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* benchmark */
|
/* benchmark */
|
||||||
{ UTIL_time_t const clockStart = UTIL_getTime();
|
{ UTIL_time_t const clockStart = UTIL_getTime();
|
||||||
@ -146,9 +135,9 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
|
|||||||
} }
|
} }
|
||||||
} /* for (loopNb = 0; loopNb < nbLoops; loopNb++) */
|
} /* for (loopNb = 0; loopNb < nbLoops; loopNb++) */
|
||||||
|
|
||||||
{ U64 const totalTime = UTIL_clockSpanNano(clockStart);
|
{ PTime const totalTime = UTIL_clockSpanNano(clockStart);
|
||||||
BMK_runTime_t rt;
|
BMK_runTime_t rt;
|
||||||
rt.nanoSecPerRun = totalTime / nbLoops;
|
rt.nanoSecPerRun = (double)totalTime / nbLoops;
|
||||||
rt.sumOfReturn = dstSize;
|
rt.sumOfReturn = dstSize;
|
||||||
return BMK_setValid_runTime(rt);
|
return BMK_setValid_runTime(rt);
|
||||||
} }
|
} }
|
||||||
@ -158,9 +147,9 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
|
|||||||
/* ==== Benchmarking any function, providing intermediate results ==== */
|
/* ==== Benchmarking any function, providing intermediate results ==== */
|
||||||
|
|
||||||
struct BMK_timedFnState_s {
|
struct BMK_timedFnState_s {
|
||||||
U64 timeSpent_ns;
|
PTime timeSpent_ns;
|
||||||
U64 timeBudget_ns;
|
PTime timeBudget_ns;
|
||||||
U64 runBudget_ns;
|
PTime runBudget_ns;
|
||||||
BMK_runTime_t fastestRun;
|
BMK_runTime_t fastestRun;
|
||||||
unsigned nbLoops;
|
unsigned nbLoops;
|
||||||
UTIL_time_t coolTime;
|
UTIL_time_t coolTime;
|
||||||
@ -174,8 +163,20 @@ BMK_timedFnState_t* BMK_createTimedFnState(unsigned total_ms, unsigned run_ms)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BMK_freeTimedFnState(BMK_timedFnState_t* state) {
|
void BMK_freeTimedFnState(BMK_timedFnState_t* state) { free(state); }
|
||||||
free(state);
|
|
||||||
|
BMK_timedFnState_t*
|
||||||
|
BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms)
|
||||||
|
{
|
||||||
|
typedef char check_size[ 2 * (sizeof(BMK_timedFnState_shell) >= sizeof(struct BMK_timedFnState_s)) - 1]; /* static assert : a compilation failure indicates that BMK_timedFnState_shell is not large enough */
|
||||||
|
typedef struct { check_size c; BMK_timedFnState_t tfs; } tfs_align; /* force tfs to be aligned at its next best position */
|
||||||
|
size_t const tfs_alignment = offsetof(tfs_align, tfs); /* provides the minimal alignment restriction for BMK_timedFnState_t */
|
||||||
|
BMK_timedFnState_t* const r = (BMK_timedFnState_t*)buffer;
|
||||||
|
if (buffer == NULL) return NULL;
|
||||||
|
if (size < sizeof(struct BMK_timedFnState_s)) return NULL;
|
||||||
|
if ((size_t)buffer % tfs_alignment) return NULL; /* buffer must be properly aligned */
|
||||||
|
BMK_resetTimedFnState(r, total_ms, run_ms);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms)
|
void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms)
|
||||||
@ -184,9 +185,9 @@ void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms,
|
|||||||
if (!run_ms) run_ms = 1;
|
if (!run_ms) run_ms = 1;
|
||||||
if (run_ms > total_ms) run_ms = total_ms;
|
if (run_ms > total_ms) run_ms = total_ms;
|
||||||
timedFnState->timeSpent_ns = 0;
|
timedFnState->timeSpent_ns = 0;
|
||||||
timedFnState->timeBudget_ns = (U64)total_ms * TIMELOOP_NANOSEC / 1000;
|
timedFnState->timeBudget_ns = (PTime)total_ms * TIMELOOP_NANOSEC / 1000;
|
||||||
timedFnState->runBudget_ns = (U64)run_ms * TIMELOOP_NANOSEC / 1000;
|
timedFnState->runBudget_ns = (PTime)run_ms * TIMELOOP_NANOSEC / 1000;
|
||||||
timedFnState->fastestRun.nanoSecPerRun = (U64)(-1LL);
|
timedFnState->fastestRun.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000; /* hopefully large enough : must be larger than any potential measurement */
|
||||||
timedFnState->fastestRun.sumOfReturn = (size_t)(-1LL);
|
timedFnState->fastestRun.sumOfReturn = (size_t)(-1LL);
|
||||||
timedFnState->nbLoops = 1;
|
timedFnState->nbLoops = 1;
|
||||||
timedFnState->coolTime = UTIL_getTime();
|
timedFnState->coolTime = UTIL_getTime();
|
||||||
@ -208,37 +209,27 @@ int BMK_isCompleted_TimedFn(const BMK_timedFnState_t* timedFnState)
|
|||||||
BMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* cont,
|
BMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* cont,
|
||||||
BMK_benchParams_t p)
|
BMK_benchParams_t p)
|
||||||
{
|
{
|
||||||
U64 const runBudget_ns = cont->runBudget_ns;
|
PTime const runBudget_ns = cont->runBudget_ns;
|
||||||
U64 const runTimeMin_ns = runBudget_ns / 2;
|
PTime const runTimeMin_ns = runBudget_ns / 2;
|
||||||
int completed = 0;
|
int completed = 0;
|
||||||
BMK_runTime_t bestRunTime = cont->fastestRun;
|
BMK_runTime_t bestRunTime = cont->fastestRun;
|
||||||
|
|
||||||
while (!completed) {
|
while (!completed) {
|
||||||
BMK_runOutcome_t runResult;
|
BMK_runOutcome_t const runResult = BMK_benchFunction(p, cont->nbLoops);
|
||||||
|
|
||||||
/* Overheat protection */
|
|
||||||
if (UTIL_clockSpanMicro(cont->coolTime) > ACTIVEPERIOD_MICROSEC) {
|
|
||||||
DEBUGOUTPUT("\rcooling down ... \r");
|
|
||||||
UTIL_sleep(COOLPERIOD_SEC);
|
|
||||||
cont->coolTime = UTIL_getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reinitialize capacity */
|
|
||||||
runResult = BMK_benchFunction(p, cont->nbLoops);
|
|
||||||
|
|
||||||
if(!BMK_isSuccessful_runOutcome(runResult)) { /* error : move out */
|
if(!BMK_isSuccessful_runOutcome(runResult)) { /* error : move out */
|
||||||
return runResult;
|
return runResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ BMK_runTime_t const newRunTime = BMK_extract_runTime(runResult);
|
{ BMK_runTime_t const newRunTime = BMK_extract_runTime(runResult);
|
||||||
U64 const loopDuration_ns = newRunTime.nanoSecPerRun * cont->nbLoops;
|
double const loopDuration_ns = newRunTime.nanoSecPerRun * cont->nbLoops;
|
||||||
|
|
||||||
cont->timeSpent_ns += loopDuration_ns;
|
cont->timeSpent_ns += (unsigned long long)loopDuration_ns;
|
||||||
|
|
||||||
/* estimate nbLoops for next run to last approximately 1 second */
|
/* estimate nbLoops for next run to last approximately 1 second */
|
||||||
if (loopDuration_ns > (runBudget_ns / 50)) {
|
if (loopDuration_ns > (runBudget_ns / 50)) {
|
||||||
U64 const fastestRun_ns = MIN(bestRunTime.nanoSecPerRun, newRunTime.nanoSecPerRun);
|
double const fastestRun_ns = MIN(bestRunTime.nanoSecPerRun, newRunTime.nanoSecPerRun);
|
||||||
cont->nbLoops = (U32)(runBudget_ns / fastestRun_ns) + 1;
|
cont->nbLoops = (unsigned)(runBudget_ns / fastestRun_ns) + 1;
|
||||||
} else {
|
} else {
|
||||||
/* previous run was too short : blindly increase workload by x multiplier */
|
/* previous run was too short : blindly increase workload by x multiplier */
|
||||||
const unsigned multiplier = 10;
|
const unsigned multiplier = 10;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user