@@ -0,0 +1,9 @@
|
|||||||
|
[cxx]
|
||||||
|
cppflags = -DXXH_NAMESPACE=ZSTD_ -DZSTD_LEGACY_SUPPORT=1
|
||||||
|
cflags = -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wundef -Wpointer-arith
|
||||||
|
cxxppflags = -DXXH_NAMESPACE=ZSTD_ -DZSTD_LEGACY_SUPPORT=1
|
||||||
|
cxxflags = -std=c++11 -Wno-format-security -Wno-deprecated-declarations
|
||||||
|
gtest_dep = //contrib/pzstd:gtest
|
||||||
|
|
||||||
|
[httpserver]
|
||||||
|
port = 0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
c8dec2e8da52d483f6dd7c6cd2ad694e8e6fed2b
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
# Executables
|
# Executables
|
||||||
zstd
|
zstd
|
||||||
|
zstdmt
|
||||||
*.exe
|
*.exe
|
||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
@@ -36,3 +37,5 @@ googletest/
|
|||||||
|
|
||||||
# Directories
|
# Directories
|
||||||
bin/
|
bin/
|
||||||
|
.buckd/
|
||||||
|
buck-out/
|
||||||
|
|||||||
+50
-23
@@ -8,11 +8,7 @@ matrix:
|
|||||||
|
|
||||||
|
|
||||||
# Container-based Ubuntu 12.04 LTS Server Edition 64 bit (doesn't support 32-bit includes)
|
# Container-based Ubuntu 12.04 LTS Server Edition 64 bit (doesn't support 32-bit includes)
|
||||||
- env: Ubu=12.04cont Cmd="make test && make clean && make travis-install"
|
- env: Ubu=12.04cont Cmd="make zlibwrapper && make clean && make -C tests test-symbols && make clean && make -C tests test-zstd-nolegacy && make clean && make cmaketest && make clean && make -C contrib/pzstd googletest pzstd tests check && make -C contrib/pzstd clean"
|
||||||
os: linux
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
- env: Ubu=12.04cont Cmd="make zlibwrapper && make clean && make -C tests test-zstd-nolegacy && make clean && make cmaketest && make clean && make -C contrib/pzstd googletest pzstd tests check && make -C contrib/pzstd clean"
|
|
||||||
os: linux
|
os: linux
|
||||||
sudo: false
|
sudo: false
|
||||||
language: cpp
|
language: cpp
|
||||||
@@ -37,7 +33,7 @@ matrix:
|
|||||||
|
|
||||||
|
|
||||||
# Standard Ubuntu 12.04 LTS Server Edition 64 bit
|
# Standard Ubuntu 12.04 LTS Server Edition 64 bit
|
||||||
- env: Ubu=12.04 Cmd="make -C programs zstd-small zstd-decompress zstd-compress && make -C tests test-gzstd && make -C programs clean && make -C tests versionsTest"
|
- env: Ubu=12.04 Cmd="make -C programs zstd-small zstd-decompress zstd-compress && make -C programs clean && make -C tests versionsTest"
|
||||||
os: linux
|
os: linux
|
||||||
sudo: required
|
sudo: required
|
||||||
|
|
||||||
@@ -69,7 +65,7 @@ matrix:
|
|||||||
|
|
||||||
|
|
||||||
# Ubuntu 14.04 LTS Server Edition 64 bit
|
# Ubuntu 14.04 LTS Server Edition 64 bit
|
||||||
- env: Ubu=14.04 Cmd="make armtest && make clean && make aarch64test"
|
- env: Ubu=14.04 Cmd="make armtest"
|
||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: required
|
sudo: required
|
||||||
addons:
|
addons:
|
||||||
@@ -78,11 +74,30 @@ matrix:
|
|||||||
- qemu-system-arm
|
- qemu-system-arm
|
||||||
- qemu-user-static
|
- qemu-user-static
|
||||||
- gcc-arm-linux-gnueabi
|
- gcc-arm-linux-gnueabi
|
||||||
- libc6-dev-armel-cross
|
- libc6-dev-armel-cross
|
||||||
|
|
||||||
|
- env: Ubu=14.04 Cmd="make aarch64test"
|
||||||
|
dist: trusty
|
||||||
|
sudo: required
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu-system-arm
|
||||||
|
- qemu-user-static
|
||||||
- gcc-aarch64-linux-gnu
|
- gcc-aarch64-linux-gnu
|
||||||
- libc6-dev-arm64-cross
|
- libc6-dev-arm64-cross
|
||||||
|
|
||||||
- env: Ubu=14.04 Cmd='make ppctest && make clean && make ppc64test'
|
- env: Ubu=14.04 Cmd='make ppctest'
|
||||||
|
dist: trusty
|
||||||
|
sudo: required
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu-system-ppc
|
||||||
|
- qemu-user-static
|
||||||
|
- gcc-powerpc-linux-gnu
|
||||||
|
|
||||||
|
- env: Ubu=14.04 Cmd='make ppc64test'
|
||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: required
|
sudo: required
|
||||||
addons:
|
addons:
|
||||||
@@ -101,7 +116,27 @@ matrix:
|
|||||||
packages:
|
packages:
|
||||||
- valgrind
|
- valgrind
|
||||||
|
|
||||||
- env: Ubu=14.04 Cmd="make gpptest && make clean && make gnu90test && make clean && make c99test && make clean && make gnu99test && make clean && make clangtest && make clean && make -C contrib/pzstd googletest32 && make -C contrib/pzstd all32 && make -C contrib/pzstd check && make -C contrib/pzstd clean"
|
|
||||||
|
|
||||||
|
# other feature branches => short tests
|
||||||
|
- env: Ubu=12.04cont Cmd="make test && make clean && make travis-install"
|
||||||
|
os: linux
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
- env: Ubu=14.04 Cmd="make -C tests test32"
|
||||||
|
os: linux
|
||||||
|
dist: trusty
|
||||||
|
sudo: required
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- libc6-dev-i386
|
||||||
|
- gcc-multilib
|
||||||
|
|
||||||
|
- env: Ubu=14.04 Cmd="make gpptest && make clean && make gnu90test && make clean
|
||||||
|
&& make c99test && make clean && make gnu99test && make clean
|
||||||
|
&& make clangtest && make clean && make -C contrib/pzstd googletest32
|
||||||
|
&& make -C contrib/pzstd all32 && make -C contrib/pzstd check && make -C contrib/pzstd clean"
|
||||||
os: linux
|
os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: required
|
sudo: required
|
||||||
@@ -117,17 +152,7 @@ matrix:
|
|||||||
- g++-4.8
|
- g++-4.8
|
||||||
- g++-4.8-multilib
|
- g++-4.8-multilib
|
||||||
|
|
||||||
- env: Ubu=14.04 Cmd="make -C tests test32"
|
- env: Ubu=14.04 Cmd="make gcc5test && make clean && make gcc6test && make clean && make -C tests dll"
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
sudo: required
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libc6-dev-i386
|
|
||||||
- gcc-multilib
|
|
||||||
|
|
||||||
- env: Ubu=14.04 Cmd="make gcc5test && make clean && make gcc6test"
|
|
||||||
os: linux
|
os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: required
|
sudo: required
|
||||||
@@ -144,5 +169,7 @@ matrix:
|
|||||||
|
|
||||||
script:
|
script:
|
||||||
- JOB_NUMBER=$(echo $TRAVIS_JOB_NUMBER | sed -e 's:[0-9][0-9]*\.\(.*\):\1:')
|
- JOB_NUMBER=$(echo $TRAVIS_JOB_NUMBER | sed -e 's:[0-9][0-9]*\.\(.*\):\1:')
|
||||||
# - if [ $JOB_NUMBER -eq 9 ] || [ $JOB_NUMBER -eq 10 ]; then sh -c "$Cmd"; fi
|
# dev => normal tests; other feature branches => short tests (number > 11)
|
||||||
- sh -c "$Cmd"
|
- if [ "$TRAVIS_PULL_REQUEST" = "true" ] || [ $JOB_NUMBER -gt 11 ] || [ "$TRAVIS_BRANCH" = "dev" ] && [ "$TRAVIS_BRANCH" != "master" ]; then sh -c "$Cmd"; fi
|
||||||
|
# master => long tests, as this is the final step towards a Release
|
||||||
|
- if [ "$TRAVIS_BRANCH" = "master" ]; then FUZZERTEST=-T10mn sh -c "$Cmd"; fi
|
||||||
|
|||||||
@@ -23,13 +23,23 @@ EXT =
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: default
|
.PHONY: default
|
||||||
default: lib zstd
|
default: lib zstd-release
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all:
|
all: allmost
|
||||||
$(MAKE) -C $(ZSTDDIR) $@
|
CPPFLAGS=-I../lib LDFLAGS=-L../lib $(MAKE) -C examples/ $@
|
||||||
$(MAKE) -C $(PRGDIR) $@ zstd32
|
|
||||||
$(MAKE) -C $(TESTDIR) $@ all32
|
.PHONY: allmost
|
||||||
|
allmost:
|
||||||
|
$(MAKE) -C $(ZSTDDIR) all
|
||||||
|
$(MAKE) -C $(PRGDIR) all
|
||||||
|
$(MAKE) -C $(TESTDIR) all
|
||||||
|
$(MAKE) -C $(ZWRAPDIR) all
|
||||||
|
|
||||||
|
.PHONY: all32
|
||||||
|
all32:
|
||||||
|
$(MAKE) -C $(PRGDIR) zstd32
|
||||||
|
$(MAKE) -C $(TESTDIR) all32
|
||||||
|
|
||||||
.PHONY: lib
|
.PHONY: lib
|
||||||
lib:
|
lib:
|
||||||
@@ -40,6 +50,16 @@ zstd:
|
|||||||
@$(MAKE) -C $(PRGDIR) $@
|
@$(MAKE) -C $(PRGDIR) $@
|
||||||
cp $(PRGDIR)/zstd$(EXT) .
|
cp $(PRGDIR)/zstd$(EXT) .
|
||||||
|
|
||||||
|
.PHONY: zstd-release
|
||||||
|
zstd-release:
|
||||||
|
@$(MAKE) -C $(PRGDIR)
|
||||||
|
cp $(PRGDIR)/zstd$(EXT) .
|
||||||
|
|
||||||
|
.PHONY: zstdmt
|
||||||
|
zstdmt:
|
||||||
|
@$(MAKE) -C $(PRGDIR) $@
|
||||||
|
cp $(PRGDIR)/zstd$(EXT) ./zstdmt$(EXT)
|
||||||
|
|
||||||
.PHONY: zlibwrapper
|
.PHONY: zlibwrapper
|
||||||
zlibwrapper:
|
zlibwrapper:
|
||||||
$(MAKE) -C $(ZWRAPDIR) test
|
$(MAKE) -C $(ZWRAPDIR) test
|
||||||
@@ -54,7 +74,8 @@ clean:
|
|||||||
@$(MAKE) -C $(PRGDIR) $@ > $(VOID)
|
@$(MAKE) -C $(PRGDIR) $@ > $(VOID)
|
||||||
@$(MAKE) -C $(TESTDIR) $@ > $(VOID)
|
@$(MAKE) -C $(TESTDIR) $@ > $(VOID)
|
||||||
@$(MAKE) -C $(ZWRAPDIR) $@ > $(VOID)
|
@$(MAKE) -C $(ZWRAPDIR) $@ > $(VOID)
|
||||||
@$(RM) zstd$(EXT) tmp*
|
@$(MAKE) -C examples/ $@ > $(VOID)
|
||||||
|
@$(RM) zstd$(EXT) zstdmt$(EXT) tmp*
|
||||||
@echo Cleaning completed
|
@echo Cleaning completed
|
||||||
|
|
||||||
|
|
||||||
@@ -77,7 +98,7 @@ travis-install:
|
|||||||
$(MAKE) install PREFIX=~/install_test_dir
|
$(MAKE) install PREFIX=~/install_test_dir
|
||||||
|
|
||||||
gpptest: clean
|
gpptest: clean
|
||||||
$(MAKE) -C programs all CC=g++ CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror"
|
CC=g++ $(MAKE) -C programs all CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror"
|
||||||
|
|
||||||
gcc5test: clean
|
gcc5test: clean
|
||||||
gcc-5 -v
|
gcc-5 -v
|
||||||
@@ -148,13 +169,13 @@ gnu90test: clean
|
|||||||
CFLAGS="-std=gnu90" $(MAKE) all
|
CFLAGS="-std=gnu90" $(MAKE) all
|
||||||
|
|
||||||
c99test: clean
|
c99test: clean
|
||||||
CFLAGS="-std=c99" $(MAKE) all
|
CFLAGS="-std=c99" $(MAKE) allmost
|
||||||
|
|
||||||
gnu99test: clean
|
gnu99test: clean
|
||||||
CFLAGS="-std=gnu99" $(MAKE) all
|
CFLAGS="-std=gnu99" $(MAKE) all
|
||||||
|
|
||||||
c11test: clean
|
c11test: clean
|
||||||
CFLAGS="-std=c11" $(MAKE) all
|
CFLAGS="-std=c11" $(MAKE) allmost
|
||||||
|
|
||||||
bmix64test: clean
|
bmix64test: clean
|
||||||
CFLAGS="-O3 -mbmi -Werror" $(MAKE) -C $(TESTDIR) test
|
CFLAGS="-O3 -mbmi -Werror" $(MAKE) -C $(TESTDIR) test
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
v1.1.3
|
||||||
|
cli : zstd can decompress .gz files (can be disabled with `make zstd-nogz` or `make HAVE_ZLIB=0`)
|
||||||
|
cli : new : experimental target `make zstdmt`, with multi-threading support
|
||||||
|
cli : new : improved dictionary builder "cover" (experimental), by Nick Terrell
|
||||||
|
cli : new : advanced commands for detailed parameters, by Przemyslaw Skibinski
|
||||||
|
cli : fix zstdless on Mac OS-X, by Andrew Janke
|
||||||
|
cli : fix #232 "compress non-files"
|
||||||
|
dictBuilder : improved dictionary generation quality, thanks to Nick Terrell
|
||||||
|
API : new : lib/compress/ZSTDMT_compress.h multithreading API (experimental)
|
||||||
|
API : new : ZSTD_create?Dict_byReference(), requested by Bartosz Taudul
|
||||||
|
API : new : ZDICT_finalizeDictionary()
|
||||||
|
API : fix : ZSTD_initCStream_usingCDict() properly writes dictID into frame header, by Gregory Szorc (#511)
|
||||||
|
API : fix : all symbols properly exposed in libzstd, by Nick Terrell
|
||||||
|
build : support for Solaris target, by Przemyslaw Skibinski
|
||||||
|
doc : clarified specification, by Andrew Purcell
|
||||||
|
|
||||||
v1.1.2
|
v1.1.2
|
||||||
API : streaming : decompression : changed : automatic implicit reset when chain-decoding new frames without init
|
API : streaming : decompression : changed : automatic implicit reset when chain-decoding new frames without init
|
||||||
API : experimental : added : dictID retrieval functions, and ZSTD_initCStream_srcSize()
|
API : experimental : added : dictID retrieval functions, and ZSTD_initCStream_srcSize()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
targeting real-time compression scenarios at zlib-level and better compression ratios.
|
targeting real-time compression scenarios at zlib-level and better compression ratios.
|
||||||
|
|
||||||
It is provided as an open-source BSD-licensed **C** library,
|
It is provided as an open-source BSD-licensed **C** library,
|
||||||
and a command line utility producing and decoding `.zst` compressed files.
|
and a command line utility producing and decoding `.zst` and `.gz` files.
|
||||||
For other programming languages,
|
For other programming languages,
|
||||||
you can consult a list of known ports on [Zstandard homepage](http://www.zstd.net/#other-languages).
|
you can consult a list of known ports on [Zstandard homepage](http://www.zstd.net/#other-languages).
|
||||||
|
|
||||||
@@ -47,18 +47,27 @@ For a larger picture including very slow modes, [click on this link](doc/images/
|
|||||||
|
|
||||||
### The case for Small Data compression
|
### The case for Small Data compression
|
||||||
|
|
||||||
Previous charts provide results applicable to typical file and stream scenarios (several MB). Small data comes with different perspectives. The smaller the amount of data to compress, the more difficult it is to achieve any significant compression.
|
Previous charts provide results applicable to typical file and stream scenarios (several MB). Small data comes with different perspectives.
|
||||||
|
|
||||||
This problem is common to many compression algorithms. The reason is, compression algorithms learn from past data how to compress future data. But at the beginning of a new file, there is no "past" to build upon.
|
The smaller the amount of data to compress, the more difficult it is to compress. This problem is common to all compression algorithms, and reason is, compression algorithms learn from past data how to compress future data. But at the beginning of a new data set, there is no "past" to build upon.
|
||||||
|
|
||||||
To solve this situation, Zstd offers a __training mode__, which can be used to tune the algorithm for a selected type of data, by providing it with a few samples. The result of the training is stored in a file called "dictionary", which can be loaded before compression and decompression. Using this dictionary, the compression ratio achievable on small data improves dramatically:
|
To solve this situation, Zstd offers a __training mode__, which can be used to tune the algorithm for a selected type of data.
|
||||||
|
Training Zstandard is achieved by provide it with a few samples (one file per sample). The result of this training is stored in a file called "dictionary", which must be loaded before compression and decompression.
|
||||||
|
Using this dictionary, the compression ratio achievable on small data improves dramatically.
|
||||||
|
|
||||||

|
The following example uses the `github-users` [sample set](https://www.dropbox.com/s/mnktkomhkjbf1i2/github_users.tar.zst?dl=0), created from [github public API](https://developer.github.com/v3/users/#get-all-users).
|
||||||
|
It consists of roughly 10K records weighting about 1KB each.
|
||||||
|
|
||||||
These compression gains are achieved while simultaneously providing faster compression and decompression speeds.
|
Compression Ratio | Compression Speed | Decompression Speed
|
||||||
|
------------------|-------------------|--------------------
|
||||||
|
 |  | 
|
||||||
|
|
||||||
Dictionary works if there is some correlation in a family of small data (there is no _universal dictionary_).
|
|
||||||
Hence, deploying one dictionary per type of data will provide the greatest benefits. Dictionary gains are mostly effective in the first few KB. Then, the compression algorithm will rely more and more on previously decoded content to compress the rest of the file.
|
These compression gains are achieved while simultaneously providing _faster_ compression and decompression speeds.
|
||||||
|
|
||||||
|
Training works if there is some correlation in a family of small data samples. The more data-specific a dictionary is, the more efficient it is (there is no _universal dictionary_).
|
||||||
|
Hence, deploying one dictionary per type of data will provide the greatest benefits.
|
||||||
|
Dictionary gains are mostly effective in the first few KB. Then, the compression algorithm will gradually use previously decoded content to better compress the rest of the file.
|
||||||
|
|
||||||
#### Dictionary compression How To :
|
#### Dictionary compression How To :
|
||||||
|
|
||||||
@@ -68,11 +77,12 @@ Hence, deploying one dictionary per type of data will provide the greatest benef
|
|||||||
|
|
||||||
2) Compress with dictionary
|
2) Compress with dictionary
|
||||||
|
|
||||||
`zstd FILE -D dictionaryName`
|
`zstd -D dictionaryName FILE`
|
||||||
|
|
||||||
3) Decompress with dictionary
|
3) Decompress with dictionary
|
||||||
|
|
||||||
`zstd --decompress FILE.zst -D dictionaryName`
|
`zstd -D dictionaryName --decompress FILE.zst`
|
||||||
|
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|
||||||
|
|||||||
+11
-4
@@ -2,10 +2,10 @@ version: 1.0.{build}
|
|||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- COMPILER: "gcc"
|
- COMPILER: "gcc"
|
||||||
MAKE_PARAMS: "test"
|
MAKE_PARAMS: '"make test && make lib && make -C tests test-symbols fullbench-dll fullbench-lib"'
|
||||||
PLATFORM: "mingw64"
|
PLATFORM: "mingw64"
|
||||||
- COMPILER: "gcc"
|
- COMPILER: "gcc"
|
||||||
MAKE_PARAMS: "test"
|
MAKE_PARAMS: "make test"
|
||||||
PLATFORM: "mingw32"
|
PLATFORM: "mingw32"
|
||||||
- COMPILER: "visual"
|
- COMPILER: "visual"
|
||||||
CONFIGURATION: "Debug"
|
CONFIGURATION: "Debug"
|
||||||
@@ -46,6 +46,13 @@ build_script:
|
|||||||
ECHO make %CLANG_PARAMS% &&
|
ECHO make %CLANG_PARAMS% &&
|
||||||
make %CLANG_PARAMS% &&
|
make %CLANG_PARAMS% &&
|
||||||
COPY tests\fuzzer.exe tests\fuzzer_clang.exe &&
|
COPY tests\fuzzer.exe tests\fuzzer_clang.exe &&
|
||||||
|
ECHO *** &&
|
||||||
|
ECHO *** Building cmake for %PLATFORM% &&
|
||||||
|
ECHO *** &&
|
||||||
|
mkdir build\cmake\build &&
|
||||||
|
cd build\cmake\build &&
|
||||||
|
cmake -G "Visual Studio 14 2015 Win64" .. &&
|
||||||
|
cd ..\..\.. &&
|
||||||
make clean &&
|
make clean &&
|
||||||
ECHO *** &&
|
ECHO *** &&
|
||||||
ECHO *** Building pzstd for %PLATFORM% &&
|
ECHO *** Building pzstd for %PLATFORM% &&
|
||||||
@@ -62,8 +69,8 @@ build_script:
|
|||||||
ECHO *** &&
|
ECHO *** &&
|
||||||
make -v &&
|
make -v &&
|
||||||
cc -v &&
|
cc -v &&
|
||||||
ECHO make %MAKE_PARAMS% &&
|
ECHO %MAKE_PARAMS% &&
|
||||||
make %MAKE_PARAMS%
|
sh -c %MAKE_PARAMS%
|
||||||
)
|
)
|
||||||
- if [%COMPILER%]==[gcc] if [%PLATFORM%]==[mingw64] (
|
- if [%COMPILER%]==[gcc] if [%PLATFORM%]==[mingw64] (
|
||||||
COPY programs\zstd.exe bin\zstd.exe &&
|
COPY programs\zstd.exe bin\zstd.exe &&
|
||||||
|
|||||||
@@ -331,6 +331,10 @@
|
|||||||
RelativePath="..\..\..\programs\datagen.c"
|
RelativePath="..\..\..\programs\datagen.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\dictBuilder\cover.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
||||||
>
|
>
|
||||||
@@ -339,10 +343,22 @@
|
|||||||
RelativePath="..\..\..\lib\common\entropy_common.c"
|
RelativePath="..\..\..\lib\common\entropy_common.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\error_private.c"
|
RelativePath="..\..\..\lib\common\error_private.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\compress\fse_compress.c"
|
RelativePath="..\..\..\lib\compress\fse_compress.c"
|
||||||
>
|
>
|
||||||
@@ -389,6 +405,14 @@
|
|||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\bitstream.h"
|
RelativePath="..\..\..\lib\common\bitstream.h"
|
||||||
>
|
>
|
||||||
@@ -445,6 +469,10 @@
|
|||||||
RelativePath="..\..\..\lib\common\zstd_internal.h"
|
RelativePath="..\..\..\lib\common\zstd_internal.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\compress\zstd_opt.h"
|
RelativePath="..\..\..\lib\compress\zstd_opt.h"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
|
||||||
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
Optimization="2"
|
Optimization="2"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
|
||||||
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
|
||||||
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
@@ -273,7 +273,7 @@
|
|||||||
Optimization="2"
|
Optimization="2"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
|
||||||
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
@@ -343,6 +343,10 @@
|
|||||||
RelativePath="..\..\..\programs\dibio.c"
|
RelativePath="..\..\..\programs\dibio.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\dictBuilder\cover.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
||||||
>
|
>
|
||||||
@@ -391,6 +395,10 @@
|
|||||||
RelativePath="..\..\..\lib\compress\zstd_compress.c"
|
RelativePath="..\..\..\lib\compress\zstd_compress.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\decompress\zstd_decompress.c"
|
RelativePath="..\..\..\lib\decompress\zstd_decompress.c"
|
||||||
>
|
>
|
||||||
@@ -529,6 +537,10 @@
|
|||||||
RelativePath="..\..\..\lib\legacy\zstd_v07.h"
|
RelativePath="..\..\..\lib\legacy\zstd_v07.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Files>
|
</Files>
|
||||||
<Globals>
|
<Globals>
|
||||||
|
|||||||
@@ -327,10 +327,22 @@
|
|||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\dictBuilder\cover.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\entropy_common.c"
|
RelativePath="..\..\..\lib\common\entropy_common.c"
|
||||||
>
|
>
|
||||||
@@ -359,6 +371,10 @@
|
|||||||
RelativePath="..\..\..\lib\common\xxhash.c"
|
RelativePath="..\..\..\lib\common\xxhash.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\deprecated\zbuff_common.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\deprecated\zbuff_compress.c"
|
RelativePath="..\..\..\lib\deprecated\zbuff_compress.c"
|
||||||
>
|
>
|
||||||
@@ -375,6 +391,10 @@
|
|||||||
RelativePath="..\..\..\lib\common\zstd_common.c"
|
RelativePath="..\..\..\lib\common\zstd_common.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\compress\zstd_compress.c"
|
RelativePath="..\..\..\lib\compress\zstd_compress.c"
|
||||||
>
|
>
|
||||||
@@ -425,6 +445,14 @@
|
|||||||
RelativePath="..\..\..\lib\dictBuilder\divsufsort.h"
|
RelativePath="..\..\..\lib\dictBuilder\divsufsort.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\error_private.h"
|
RelativePath="..\..\..\lib\common\error_private.h"
|
||||||
>
|
>
|
||||||
@@ -485,6 +513,10 @@
|
|||||||
RelativePath="..\..\..\lib\compress\zstd_opt.h"
|
RelativePath="..\..\..\lib\compress\zstd_opt.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\zstd_static.h"
|
RelativePath="..\..\..\lib\common\zstd_static.h"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -332,10 +332,22 @@
|
|||||||
RelativePath="..\..\..\programs\datagen.c"
|
RelativePath="..\..\..\programs\datagen.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\dictBuilder\cover.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\entropy_common.c"
|
RelativePath="..\..\..\lib\common\entropy_common.c"
|
||||||
>
|
>
|
||||||
@@ -376,6 +388,10 @@
|
|||||||
RelativePath="..\..\..\lib\common\zstd_common.c"
|
RelativePath="..\..\..\lib\common\zstd_common.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\compress\zstd_compress.c"
|
RelativePath="..\..\..\lib\compress\zstd_compress.c"
|
||||||
>
|
>
|
||||||
@@ -398,6 +414,14 @@
|
|||||||
RelativePath="..\..\..\lib\dictBuilder\divsufsort.h"
|
RelativePath="..\..\..\lib\dictBuilder\divsufsort.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\error_private.h"
|
RelativePath="..\..\..\lib\common\error_private.h"
|
||||||
>
|
>
|
||||||
@@ -446,6 +470,10 @@
|
|||||||
RelativePath="..\..\..\lib\common\zstd_internal.h"
|
RelativePath="..\..\..\lib\common\zstd_internal.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\compress\zstd_opt.h"
|
RelativePath="..\..\..\lib\compress\zstd_opt.h"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
|
||||||
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
Optimization="2"
|
Optimization="2"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
|
||||||
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
|
||||||
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
@@ -274,7 +274,7 @@
|
|||||||
Optimization="2"
|
Optimization="2"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
|
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
|
||||||
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
@@ -344,6 +344,10 @@
|
|||||||
RelativePath="..\..\..\programs\dibio.c"
|
RelativePath="..\..\..\programs\dibio.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\dictBuilder\cover.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
||||||
>
|
>
|
||||||
@@ -376,6 +380,14 @@
|
|||||||
RelativePath="..\..\..\lib\decompress\huf_decompress.c"
|
RelativePath="..\..\..\lib\decompress\huf_decompress.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\xxhash.c"
|
RelativePath="..\..\..\lib\common\xxhash.c"
|
||||||
>
|
>
|
||||||
@@ -428,6 +440,10 @@
|
|||||||
RelativePath="..\..\..\programs\zstdcli.c"
|
RelativePath="..\..\..\programs\zstdcli.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header Files"
|
Name="Header Files"
|
||||||
@@ -446,10 +462,6 @@
|
|||||||
RelativePath="..\..\..\lib\common\error_private.h"
|
RelativePath="..\..\..\lib\common\error_private.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\..\lib\common\zstd_errors.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\fse.h"
|
RelativePath="..\..\..\lib\common\fse.h"
|
||||||
>
|
>
|
||||||
@@ -470,6 +482,14 @@
|
|||||||
RelativePath="..\..\..\lib\common\mem.h"
|
RelativePath="..\..\..\lib\common\mem.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\xxhash.h"
|
RelativePath="..\..\..\lib\common\xxhash.h"
|
||||||
>
|
>
|
||||||
@@ -486,6 +506,10 @@
|
|||||||
RelativePath="..\..\..\lib\zstd.h"
|
RelativePath="..\..\..\lib\zstd.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\zstd_errors.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\zstd_internal.h"
|
RelativePath="..\..\..\lib\common\zstd_internal.h"
|
||||||
>
|
>
|
||||||
@@ -530,6 +554,10 @@
|
|||||||
RelativePath="..\..\..\lib\legacy\zstd_v07.h"
|
RelativePath="..\..\..\lib\legacy\zstd_v07.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Files>
|
</Files>
|
||||||
<Globals>
|
<Globals>
|
||||||
|
|||||||
@@ -328,10 +328,22 @@
|
|||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\dictBuilder\cover.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
RelativePath="..\..\..\lib\dictBuilder\divsufsort.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\entropy_common.c"
|
RelativePath="..\..\..\lib\common\entropy_common.c"
|
||||||
>
|
>
|
||||||
@@ -368,6 +380,10 @@
|
|||||||
RelativePath="..\..\..\lib\common\zstd_common.c"
|
RelativePath="..\..\..\lib\common\zstd_common.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\compress\zstd_compress.c"
|
RelativePath="..\..\..\lib\compress\zstd_compress.c"
|
||||||
>
|
>
|
||||||
@@ -418,6 +434,14 @@
|
|||||||
RelativePath="..\..\..\lib\dictBuilder\divsufsort.h"
|
RelativePath="..\..\..\lib\dictBuilder\divsufsort.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\pool.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\common\threading.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\error_private.h"
|
RelativePath="..\..\..\lib\common\error_private.h"
|
||||||
>
|
>
|
||||||
@@ -474,6 +498,10 @@
|
|||||||
RelativePath="..\..\..\lib\compress\zstd_opt.h"
|
RelativePath="..\..\..\lib\compress\zstd_opt.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\lib\compress\zstdmt_compress.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\lib\common\zstd_static.h"
|
RelativePath="..\..\..\lib\common\zstd_static.h"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -99,6 +99,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@@ -138,6 +139,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
|||||||
@@ -155,6 +155,8 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\lib\common\pool.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\common\threading.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\error_private.c" />
|
<ClCompile Include="..\..\..\lib\common\error_private.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\fse_decompress.c" />
|
<ClCompile Include="..\..\..\lib\common\fse_decompress.c" />
|
||||||
@@ -163,14 +165,18 @@
|
|||||||
<ClCompile Include="..\..\..\lib\compress\fse_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\fse_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\compress\huf_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\huf_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\compress\zstd_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\zstd_compress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\compress\zstdmt_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\huf_decompress.c" />
|
<ClCompile Include="..\..\..\lib\decompress\huf_decompress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\dictBuilder\cover.c" />
|
||||||
<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\datagen.c" />
|
<ClCompile Include="..\..\..\programs\datagen.c" />
|
||||||
<ClCompile Include="..\..\..\tests\fuzzer.c" />
|
<ClCompile Include="..\..\..\tests\fuzzer.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\lib\common\pool.h" />
|
||||||
|
<ClInclude Include="..\..\..\lib\common\threading.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\fse.h" />
|
<ClInclude Include="..\..\..\lib\common\fse.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\huf.h" />
|
<ClInclude Include="..\..\..\lib\common\huf.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\xxhash.h" />
|
<ClInclude Include="..\..\..\lib\common\xxhash.h" />
|
||||||
@@ -178,6 +184,7 @@
|
|||||||
<ClInclude Include="..\..\..\lib\common\zstd_errors.h" />
|
<ClInclude Include="..\..\..\lib\common\zstd_errors.h" />
|
||||||
<ClInclude Include="..\..\..\lib\zstd.h" />
|
<ClInclude Include="..\..\..\lib\zstd.h" />
|
||||||
<ClInclude Include="..\..\..\lib\compress\zstd_opt.h" />
|
<ClInclude Include="..\..\..\lib\compress\zstd_opt.h" />
|
||||||
|
<ClInclude Include="..\..\..\lib\compress\zstdmt_compress.h" />
|
||||||
<ClInclude Include="..\..\..\lib\dictBuilder\divsufsort.h" />
|
<ClInclude Include="..\..\..\lib\dictBuilder\divsufsort.h" />
|
||||||
<ClInclude Include="..\..\..\lib\dictBuilder\zdict.h" />
|
<ClInclude Include="..\..\..\lib\dictBuilder\zdict.h" />
|
||||||
<ClInclude Include="..\..\..\lib\legacy\zstd_legacy.h" />
|
<ClInclude Include="..\..\..\lib\legacy\zstd_legacy.h" />
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "040904B0"
|
BLOCK "040904B0"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Yann Collet"
|
VALUE "CompanyName", "Yann Collet, Facebook, Inc."
|
||||||
VALUE "FileDescription", "Fast and efficient compression algorithm"
|
VALUE "FileDescription", "Zstandard - Fast and efficient compression algorithm"
|
||||||
VALUE "FileVersion", ZSTD_VERSION_STRING
|
VALUE "FileVersion", ZSTD_VERSION_STRING
|
||||||
VALUE "InternalName", "libzstd.dll"
|
VALUE "InternalName", "libzstd.dll"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2013-2016, Yann Collet"
|
VALUE "LegalCopyright", "Copyright (c) 2013-present, Yann Collet, Facebook, Inc."
|
||||||
VALUE "OriginalFilename", "libzstd.dll"
|
VALUE "OriginalFilename", "libzstd.dll"
|
||||||
VALUE "ProductName", "Zstandard"
|
VALUE "ProductName", "Zstandard"
|
||||||
VALUE "ProductVersion", ZSTD_VERSION_STRING
|
VALUE "ProductVersion", ZSTD_VERSION_STRING
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\lib\common\pool.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\common\threading.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\error_private.c" />
|
<ClCompile Include="..\..\..\lib\common\error_private.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\xxhash.c" />
|
<ClCompile Include="..\..\..\lib\common\xxhash.c" />
|
||||||
@@ -27,10 +29,13 @@
|
|||||||
<ClCompile Include="..\..\..\lib\compress\fse_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\fse_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\compress\huf_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\huf_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\compress\zstd_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\zstd_compress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\compress\zstdmt_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\huf_decompress.c" />
|
<ClCompile Include="..\..\..\lib\decompress\huf_decompress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\deprecated\zbuff_common.c" />
|
||||||
<ClCompile Include="..\..\..\lib\deprecated\zbuff_compress.c" />
|
<ClCompile Include="..\..\..\lib\deprecated\zbuff_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\deprecated\zbuff_decompress.c" />
|
<ClCompile Include="..\..\..\lib\deprecated\zbuff_decompress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\dictBuilder\cover.c" />
|
||||||
<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="..\..\..\lib\legacy\zstd_v01.c" />
|
<ClCompile Include="..\..\..\lib\legacy\zstd_v01.c" />
|
||||||
@@ -41,7 +46,9 @@
|
|||||||
<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" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\lib\common\pool.h" />
|
||||||
|
<ClInclude Include="..\..\..\lib\common\threading.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\bitstream.h" />
|
<ClInclude Include="..\..\..\lib\common\bitstream.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\error_private.h" />
|
<ClInclude Include="..\..\..\lib\common\error_private.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\zstd_errors.h" />
|
<ClInclude Include="..\..\..\lib\common\zstd_errors.h" />
|
||||||
@@ -61,6 +68,7 @@
|
|||||||
<ClInclude Include="..\..\..\lib\zstd.h" />
|
<ClInclude Include="..\..\..\lib\zstd.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\zstd_internal.h" />
|
<ClInclude Include="..\..\..\lib\common\zstd_internal.h" />
|
||||||
<ClInclude Include="..\..\..\lib\compress\zstd_opt.h" />
|
<ClInclude Include="..\..\..\lib\compress\zstd_opt.h" />
|
||||||
|
<ClInclude Include="..\..\..\lib\compress\zstdmt_compress.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="libzstd-dll.rc" />
|
<ResourceCompile Include="libzstd-dll.rc" />
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\lib\common\pool.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\common\threading.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\error_private.c" />
|
<ClCompile Include="..\..\..\lib\common\error_private.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\xxhash.c" />
|
<ClCompile Include="..\..\..\lib\common\xxhash.c" />
|
||||||
@@ -27,10 +29,13 @@
|
|||||||
<ClCompile Include="..\..\..\lib\compress\fse_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\fse_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\compress\huf_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\huf_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\compress\zstd_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\zstd_compress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\compress\zstdmt_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\huf_decompress.c" />
|
<ClCompile Include="..\..\..\lib\decompress\huf_decompress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\deprecated\zbuff_common.c" />
|
||||||
<ClCompile Include="..\..\..\lib\deprecated\zbuff_compress.c" />
|
<ClCompile Include="..\..\..\lib\deprecated\zbuff_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\deprecated\zbuff_decompress.c" />
|
<ClCompile Include="..\..\..\lib\deprecated\zbuff_decompress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\dictBuilder\cover.c" />
|
||||||
<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="..\..\..\lib\legacy\zstd_v01.c" />
|
<ClCompile Include="..\..\..\lib\legacy\zstd_v01.c" />
|
||||||
@@ -41,7 +46,9 @@
|
|||||||
<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" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\lib\common\pool.h" />
|
||||||
|
<ClInclude Include="..\..\..\lib\common\threading.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\bitstream.h" />
|
<ClInclude Include="..\..\..\lib\common\bitstream.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\error_private.h" />
|
<ClInclude Include="..\..\..\lib\common\error_private.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\zstd_errors.h" />
|
<ClInclude Include="..\..\..\lib\common\zstd_errors.h" />
|
||||||
@@ -61,6 +68,7 @@
|
|||||||
<ClInclude Include="..\..\..\lib\zstd.h" />
|
<ClInclude Include="..\..\..\lib\zstd.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\zstd_internal.h" />
|
<ClInclude Include="..\..\..\lib\common\zstd_internal.h" />
|
||||||
<ClInclude Include="..\..\..\lib\compress\zstd_opt.h" />
|
<ClInclude Include="..\..\..\lib\compress\zstd_opt.h" />
|
||||||
|
<ClInclude Include="..\..\..\lib\compress\zstdmt_compress.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}</ProjectGuid>
|
<ProjectGuid>{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}</ProjectGuid>
|
||||||
|
|||||||
@@ -21,14 +21,18 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
<ClCompile Include="..\..\..\lib\common\entropy_common.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\error_private.c" />
|
<ClCompile Include="..\..\..\lib\common\error_private.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\common\pool.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\common\threading.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\xxhash.c" />
|
<ClCompile Include="..\..\..\lib\common\xxhash.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\zstd_common.c" />
|
<ClCompile Include="..\..\..\lib\common\zstd_common.c" />
|
||||||
<ClCompile Include="..\..\..\lib\common\fse_decompress.c" />
|
<ClCompile Include="..\..\..\lib\common\fse_decompress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\compress\fse_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\fse_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\compress\huf_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\huf_compress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\compress\zstdmt_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\compress\zstd_compress.c" />
|
<ClCompile Include="..\..\..\lib\compress\zstd_compress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\huf_decompress.c" />
|
<ClCompile Include="..\..\..\lib\decompress\huf_decompress.c" />
|
||||||
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
|
||||||
|
<ClCompile Include="..\..\..\lib\dictBuilder\cover.c" />
|
||||||
<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="..\..\..\lib\legacy\zstd_v01.c" />
|
<ClCompile Include="..\..\..\lib\legacy\zstd_v01.c" />
|
||||||
@@ -45,7 +49,10 @@
|
|||||||
<ClCompile Include="..\..\..\programs\zstdcli.c" />
|
<ClCompile Include="..\..\..\programs\zstdcli.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\lib\common\pool.h" />
|
||||||
|
<ClInclude Include="..\..\..\lib\common\threading.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\xxhash.h" />
|
<ClInclude Include="..\..\..\lib\common\xxhash.h" />
|
||||||
|
<ClInclude Include="..\..\..\lib\compress\zstdmt_compress.h" />
|
||||||
<ClInclude Include="..\..\..\lib\dictBuilder\zdict.h" />
|
<ClInclude Include="..\..\..\lib\dictBuilder\zdict.h" />
|
||||||
<ClInclude Include="..\..\..\lib\dictBuilder\divsufsort.h" />
|
<ClInclude Include="..\..\..\lib\dictBuilder\divsufsort.h" />
|
||||||
<ClInclude Include="..\..\..\lib\common\fse.h" />
|
<ClInclude Include="..\..\..\lib\common\fse.h" />
|
||||||
@@ -66,6 +73,7 @@
|
|||||||
<ClInclude Include="..\..\..\programs\datagen.h" />
|
<ClInclude Include="..\..\..\programs\datagen.h" />
|
||||||
<ClInclude Include="..\..\..\programs\dibio.h" />
|
<ClInclude Include="..\..\..\programs\dibio.h" />
|
||||||
<ClInclude Include="..\..\..\programs\fileio.h" />
|
<ClInclude Include="..\..\..\programs\fileio.h" />
|
||||||
|
<ClInclude Include="..\..\..\programs\platform.h" />
|
||||||
<ClInclude Include="..\..\..\programs\util.h" />
|
<ClInclude Include="..\..\..\programs\util.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -119,25 +127,25 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
||||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
||||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||||
<LibraryPath>$(LibraryPath);</LibraryPath>
|
<LibraryPath>$(LibraryPath);</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
||||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
<IncludePath>$(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath);</IncludePath>
|
||||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||||
<LibraryPath>$(LibraryPath);</LibraryPath>
|
<LibraryPath>$(LibraryPath);</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -206,6 +214,7 @@
|
|||||||
<TreatWarningAsError>false</TreatWarningAsError>
|
<TreatWarningAsError>false</TreatWarningAsError>
|
||||||
<EnablePREfast>false</EnablePREfast>
|
<EnablePREfast>false</EnablePREfast>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<AdditionalOptions>/DZSTD_MULTITHREAD %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
|||||||
@@ -1,30 +1,10 @@
|
|||||||
# ################################################################
|
# ################################################################
|
||||||
# zstd - Makefile
|
# * Copyright (c) 2014-present, Yann Collet, Facebook, Inc.
|
||||||
# Copyright (C) Yann Collet 2014-2016
|
# * All rights reserved.
|
||||||
# All rights reserved.
|
# *
|
||||||
#
|
# * This source code is licensed under the BSD-style license found in the
|
||||||
# BSD license
|
# * LICENSE file in the root directory of this source tree. An additional grant
|
||||||
#
|
# * of patent rights can be found in the PATENTS file in the same directory.
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice, this
|
|
||||||
# list of conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
# list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
# other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
#
|
||||||
# You can contact the author at :
|
# You can contact the author at :
|
||||||
# - zstd homepage : http://www.zstd.net/
|
# - zstd homepage : http://www.zstd.net/
|
||||||
@@ -58,22 +38,29 @@ MESSAGE("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/threading.c
|
||||||
|
${LIBRARY_DIR}/common/pool.c
|
||||||
${LIBRARY_DIR}/common/zstd_common.c
|
${LIBRARY_DIR}/common/zstd_common.c
|
||||||
${LIBRARY_DIR}/common/error_private.c
|
${LIBRARY_DIR}/common/error_private.c
|
||||||
${LIBRARY_DIR}/common/xxhash.c
|
${LIBRARY_DIR}/common/xxhash.c
|
||||||
${LIBRARY_DIR}/common/fse_decompress.c
|
|
||||||
${LIBRARY_DIR}/compress/fse_compress.c
|
${LIBRARY_DIR}/compress/fse_compress.c
|
||||||
${LIBRARY_DIR}/compress/huf_compress.c
|
${LIBRARY_DIR}/compress/huf_compress.c
|
||||||
${LIBRARY_DIR}/compress/zstd_compress.c
|
${LIBRARY_DIR}/compress/zstd_compress.c
|
||||||
|
${LIBRARY_DIR}/compress/zstdmt_compress.c
|
||||||
${LIBRARY_DIR}/decompress/huf_decompress.c
|
${LIBRARY_DIR}/decompress/huf_decompress.c
|
||||||
${LIBRARY_DIR}/decompress/zstd_decompress.c
|
${LIBRARY_DIR}/decompress/zstd_decompress.c
|
||||||
|
${LIBRARY_DIR}/dictBuilder/cover.c
|
||||||
${LIBRARY_DIR}/dictBuilder/divsufsort.c
|
${LIBRARY_DIR}/dictBuilder/divsufsort.c
|
||||||
${LIBRARY_DIR}/dictBuilder/zdict.c
|
${LIBRARY_DIR}/dictBuilder/zdict.c
|
||||||
|
${LIBRARY_DIR}/deprecated/zbuff_common.c
|
||||||
${LIBRARY_DIR}/deprecated/zbuff_compress.c
|
${LIBRARY_DIR}/deprecated/zbuff_compress.c
|
||||||
${LIBRARY_DIR}/deprecated/zbuff_decompress.c)
|
${LIBRARY_DIR}/deprecated/zbuff_decompress.c)
|
||||||
|
|
||||||
SET(Headers
|
SET(Headers
|
||||||
${LIBRARY_DIR}/zstd.h
|
${LIBRARY_DIR}/zstd.h
|
||||||
|
${LIBRARY_DIR}/common/pool.h
|
||||||
|
${LIBRARY_DIR}/common/threading.h
|
||||||
${LIBRARY_DIR}/common/bitstream.h
|
${LIBRARY_DIR}/common/bitstream.h
|
||||||
${LIBRARY_DIR}/common/error_private.h
|
${LIBRARY_DIR}/common/error_private.h
|
||||||
${LIBRARY_DIR}/common/zstd_errors.h
|
${LIBRARY_DIR}/common/zstd_errors.h
|
||||||
@@ -81,6 +68,7 @@ SET(Headers
|
|||||||
${LIBRARY_DIR}/common/huf.h
|
${LIBRARY_DIR}/common/huf.h
|
||||||
${LIBRARY_DIR}/common/mem.h
|
${LIBRARY_DIR}/common/mem.h
|
||||||
${LIBRARY_DIR}/common/zstd_internal.h
|
${LIBRARY_DIR}/common/zstd_internal.h
|
||||||
|
${LIBRARY_DIR}/compress/zstdmt_compress.h
|
||||||
${LIBRARY_DIR}/dictBuilder/zdict.h
|
${LIBRARY_DIR}/dictBuilder/zdict.h
|
||||||
${LIBRARY_DIR}/deprecated/zbuff.h)
|
${LIBRARY_DIR}/deprecated/zbuff.h)
|
||||||
|
|
||||||
@@ -109,12 +97,12 @@ IF (ZSTD_LEGACY_SUPPORT)
|
|||||||
ENDIF (ZSTD_LEGACY_SUPPORT)
|
ENDIF (ZSTD_LEGACY_SUPPORT)
|
||||||
|
|
||||||
IF (MSVC)
|
IF (MSVC)
|
||||||
SET(MSVC_RESOURCE_DIR ${ROOT_DIR}/build/VS2010/zstdlib)
|
SET(MSVC_RESOURCE_DIR ${ROOT_DIR}/build/VS2010/libzstd-dll)
|
||||||
SET(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstdlib.rc)
|
SET(PlatformDependResources ${MSVC_RESOURCE_DIR}/libzstd-dll.rc)
|
||||||
ENDIF (MSVC)
|
ENDIF (MSVC)
|
||||||
|
|
||||||
# Split project to static and shared libraries build
|
# Split project to static and shared libraries build
|
||||||
ADD_LIBRARY(libzstd_static STATIC ${Sources} ${Headers} ${PlatformDependResources})
|
ADD_LIBRARY(libzstd_static STATIC ${Sources} ${Headers})
|
||||||
ADD_LIBRARY(libzstd_shared SHARED ${Sources} ${Headers} ${PlatformDependResources})
|
ADD_LIBRARY(libzstd_shared SHARED ${Sources} ${Headers} ${PlatformDependResources})
|
||||||
|
|
||||||
# Add specific compile definitions for MSVC project
|
# Add specific compile definitions for MSVC project
|
||||||
|
|||||||
@@ -1,30 +1,10 @@
|
|||||||
# ################################################################
|
# ################################################################
|
||||||
# zstd - Makefile
|
# * Copyright (c) 2015-present, Yann Collet, Facebook, Inc.
|
||||||
# Copyright (C) Yann Collet 2014-2016
|
# * All rights reserved.
|
||||||
# All rights reserved.
|
# *
|
||||||
#
|
# * This source code is licensed under the BSD-style license found in the
|
||||||
# BSD license
|
# * LICENSE file in the root directory of this source tree. An additional grant
|
||||||
#
|
# * of patent rights can be found in the PATENTS file in the same directory.
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice, this
|
|
||||||
# list of conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
# list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
# other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
#
|
||||||
# You can contact the author at :
|
# You can contact the author at :
|
||||||
# - zstd homepage : http://www.zstd.net/
|
# - zstd homepage : http://www.zstd.net/
|
||||||
@@ -40,14 +20,19 @@ SET(ROOT_DIR ../../..)
|
|||||||
# Define programs directory, where sources and header files are located
|
# Define programs directory, where sources and header files are located
|
||||||
SET(LIBRARY_DIR ${ROOT_DIR}/lib)
|
SET(LIBRARY_DIR ${ROOT_DIR}/lib)
|
||||||
SET(PROGRAMS_DIR ${ROOT_DIR}/programs)
|
SET(PROGRAMS_DIR ${ROOT_DIR}/programs)
|
||||||
INCLUDE_DIRECTORIES(${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/common ${LIBRARY_DIR}/dictBuilder)
|
INCLUDE_DIRECTORIES(${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/common ${LIBRARY_DIR}/compress ${LIBRARY_DIR}/dictBuilder)
|
||||||
|
|
||||||
IF (ZSTD_LEGACY_SUPPORT)
|
IF (ZSTD_LEGACY_SUPPORT)
|
||||||
SET(PROGRAMS_LEGACY_DIR ${PROGRAMS_DIR}/legacy)
|
SET(PROGRAMS_LEGACY_DIR ${PROGRAMS_DIR}/legacy)
|
||||||
INCLUDE_DIRECTORIES(${PROGRAMS_LEGACY_DIR} ${LIBRARY_DIR}/legacy)
|
INCLUDE_DIRECTORIES(${PROGRAMS_LEGACY_DIR} ${LIBRARY_DIR}/legacy)
|
||||||
ENDIF (ZSTD_LEGACY_SUPPORT)
|
ENDIF (ZSTD_LEGACY_SUPPORT)
|
||||||
|
|
||||||
ADD_EXECUTABLE(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/bench.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c)
|
IF (MSVC)
|
||||||
|
SET(MSVC_RESOURCE_DIR ${ROOT_DIR}/build/VS2010/zstd)
|
||||||
|
SET(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstd.rc)
|
||||||
|
ENDIF (MSVC)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/bench.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${PlatformDependResources})
|
||||||
TARGET_LINK_LIBRARIES(zstd libzstd_static)
|
TARGET_LINK_LIBRARIES(zstd libzstd_static)
|
||||||
|
|
||||||
IF (UNIX)
|
IF (UNIX)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ SET(ROOT_DIR ../../..)
|
|||||||
SET(LIBRARY_DIR ${ROOT_DIR}/lib)
|
SET(LIBRARY_DIR ${ROOT_DIR}/lib)
|
||||||
SET(PROGRAMS_DIR ${ROOT_DIR}/programs)
|
SET(PROGRAMS_DIR ${ROOT_DIR}/programs)
|
||||||
SET(TESTS_DIR ${ROOT_DIR}/tests)
|
SET(TESTS_DIR ${ROOT_DIR}/tests)
|
||||||
INCLUDE_DIRECTORIES(${TESTS_DIR} ${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/common ${LIBRARY_DIR}/dictBuilder)
|
INCLUDE_DIRECTORIES(${TESTS_DIR} ${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/common ${LIBRARY_DIR}/compress ${LIBRARY_DIR}/dictBuilder)
|
||||||
|
|
||||||
ADD_EXECUTABLE(fullbench ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/fullbench.c)
|
ADD_EXECUTABLE(fullbench ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/fullbench.c)
|
||||||
TARGET_LINK_LIBRARIES(fullbench libzstd_static)
|
TARGET_LINK_LIBRARIES(fullbench libzstd_static)
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
cxx_library(
|
||||||
|
name='libpzstd',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='',
|
||||||
|
exported_headers=[
|
||||||
|
'ErrorHolder.h',
|
||||||
|
'Logging.h',
|
||||||
|
'Pzstd.h',
|
||||||
|
],
|
||||||
|
headers=[
|
||||||
|
'SkippableFrame.h',
|
||||||
|
],
|
||||||
|
srcs=[
|
||||||
|
'Pzstd.cpp',
|
||||||
|
'SkippableFrame.cpp',
|
||||||
|
],
|
||||||
|
deps=[
|
||||||
|
':options',
|
||||||
|
'//contrib/pzstd/utils:utils',
|
||||||
|
'//lib:mem',
|
||||||
|
'//lib:zstd',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='options',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='',
|
||||||
|
exported_headers=['Options.h'],
|
||||||
|
srcs=['Options.cpp'],
|
||||||
|
deps=[
|
||||||
|
'//contrib/pzstd/utils:scope_guard',
|
||||||
|
'//lib:zstd',
|
||||||
|
'//programs:util',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_binary(
|
||||||
|
name='pzstd',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
srcs=['main.cpp'],
|
||||||
|
deps=[
|
||||||
|
':libpzstd',
|
||||||
|
':options',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Must run "make googletest" first
|
||||||
|
cxx_library(
|
||||||
|
name='gtest',
|
||||||
|
srcs=glob([
|
||||||
|
'googletest/googletest/src/gtest-all.cc',
|
||||||
|
'googletest/googlemock/src/gmock-all.cc',
|
||||||
|
'googletest/googlemock/src/gmock_main.cc',
|
||||||
|
]),
|
||||||
|
header_namespace='',
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('googletest/googletest/include', '**/*.h'),
|
||||||
|
('googletest/googlemock/include', '**/*.h'),
|
||||||
|
]),
|
||||||
|
headers=subdir_glob([
|
||||||
|
('googletest/googletest', 'src/*.cc'),
|
||||||
|
('googletest/googletest', 'src/*.h'),
|
||||||
|
('googletest/googlemock', 'src/*.cc'),
|
||||||
|
('googletest/googlemock', 'src/*.h'),
|
||||||
|
]),
|
||||||
|
platform_linker_flags=[
|
||||||
|
('android', []),
|
||||||
|
('', ['-lpthread']),
|
||||||
|
],
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
)
|
||||||
@@ -26,7 +26,7 @@ POSTCOMPILE = mv -f $*.Td $*.d
|
|||||||
|
|
||||||
# CFLAGS, CXXFLAGS, CPPFLAGS, and LDFLAGS are for the users to override
|
# CFLAGS, CXXFLAGS, CPPFLAGS, and LDFLAGS are for the users to override
|
||||||
CFLAGS ?= -O3 -Wall -Wextra
|
CFLAGS ?= -O3 -Wall -Wextra
|
||||||
CXXFLAGS ?= -O3 -Wall -Wextra -pedantic -std=c++11
|
CXXFLAGS ?= -O3 -Wall -Wextra -pedantic
|
||||||
CPPFLAGS ?=
|
CPPFLAGS ?=
|
||||||
LDFLAGS ?=
|
LDFLAGS ?=
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ GTEST_INC = -isystem googletest/googletest/include
|
|||||||
PZSTD_CPPFLAGS = $(PZSTD_INC)
|
PZSTD_CPPFLAGS = $(PZSTD_INC)
|
||||||
PZSTD_CCXXFLAGS =
|
PZSTD_CCXXFLAGS =
|
||||||
PZSTD_CFLAGS = $(PZSTD_CCXXFLAGS)
|
PZSTD_CFLAGS = $(PZSTD_CCXXFLAGS)
|
||||||
PZSTD_CXXFLAGS = $(PZSTD_CCXXFLAGS)
|
PZSTD_CXXFLAGS = $(PZSTD_CCXXFLAGS) -std=c++11
|
||||||
PZSTD_LDFLAGS =
|
PZSTD_LDFLAGS =
|
||||||
EXTRA_FLAGS =
|
EXTRA_FLAGS =
|
||||||
ALL_CFLAGS = $(EXTRA_FLAGS) $(CPPFLAGS) $(PZSTD_CPPFLAGS) $(CFLAGS) $(PZSTD_CFLAGS)
|
ALL_CFLAGS = $(EXTRA_FLAGS) $(CPPFLAGS) $(PZSTD_CPPFLAGS) $(CFLAGS) $(PZSTD_CFLAGS)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
*/
|
*/
|
||||||
#include "Options.h"
|
#include "Options.h"
|
||||||
|
#include "util.h"
|
||||||
#include "utils/ScopeGuard.h"
|
#include "utils/ScopeGuard.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -15,7 +16,6 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <util.h>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || \
|
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || \
|
||||||
|
|||||||
@@ -9,11 +9,6 @@
|
|||||||
#include "ErrorHolder.h"
|
#include "ErrorHolder.h"
|
||||||
#include "Options.h"
|
#include "Options.h"
|
||||||
#include "Pzstd.h"
|
#include "Pzstd.h"
|
||||||
#include "utils/FileSystem.h"
|
|
||||||
#include "utils/Range.h"
|
|
||||||
#include "utils/ScopeGuard.h"
|
|
||||||
#include "utils/ThreadPool.h"
|
|
||||||
#include "utils/WorkQueue.h"
|
|
||||||
|
|
||||||
using namespace pzstd;
|
using namespace pzstd;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
cxx_test(
|
||||||
|
name='options_test',
|
||||||
|
srcs=['OptionsTest.cpp'],
|
||||||
|
deps=['//contrib/pzstd:options'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_test(
|
||||||
|
name='pzstd_test',
|
||||||
|
srcs=['PzstdTest.cpp'],
|
||||||
|
deps=[
|
||||||
|
':round_trip',
|
||||||
|
'//contrib/pzstd:libpzstd',
|
||||||
|
'//contrib/pzstd/utils:scope_guard',
|
||||||
|
'//programs:datagen',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_binary(
|
||||||
|
name='round_trip_test',
|
||||||
|
srcs=['RoundTripTest.cpp'],
|
||||||
|
deps=[
|
||||||
|
':round_trip',
|
||||||
|
'//contrib/pzstd/utils:scope_guard',
|
||||||
|
'//programs:datagen',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='round_trip',
|
||||||
|
header_namespace='test',
|
||||||
|
exported_headers=['RoundTrip.h'],
|
||||||
|
deps=[
|
||||||
|
'//contrib/pzstd:libpzstd',
|
||||||
|
'//contrib/pzstd:options',
|
||||||
|
'//contrib/pzstd/utils:scope_guard',
|
||||||
|
]
|
||||||
|
)
|
||||||
@@ -41,23 +41,20 @@ TEST(Pzstd, SmallSizes) {
|
|||||||
std::fclose(fd);
|
std::fclose(fd);
|
||||||
ASSERT_EQ(written, len);
|
ASSERT_EQ(written, len);
|
||||||
}
|
}
|
||||||
for (unsigned headers = 0; headers <= 1; ++headers) {
|
for (unsigned numThreads = 1; numThreads <= 2; ++numThreads) {
|
||||||
for (unsigned numThreads = 1; numThreads <= 2; ++numThreads) {
|
for (unsigned level = 1; level <= 4; level *= 4) {
|
||||||
for (unsigned level = 1; level <= 4; level *= 4) {
|
auto errorGuard = makeScopeGuard([&] {
|
||||||
auto errorGuard = makeScopeGuard([&] {
|
std::fprintf(stderr, "# threads: %u\n", numThreads);
|
||||||
std::fprintf(stderr, "pzstd headers: %u\n", headers);
|
std::fprintf(stderr, "compression level: %u\n", level);
|
||||||
std::fprintf(stderr, "# threads: %u\n", numThreads);
|
});
|
||||||
std::fprintf(stderr, "compression level: %u\n", level);
|
Options options;
|
||||||
});
|
options.overwrite = true;
|
||||||
Options options;
|
options.inputFiles = {inputFile};
|
||||||
options.overwrite = true;
|
options.numThreads = numThreads;
|
||||||
options.inputFiles = {inputFile};
|
options.compressionLevel = level;
|
||||||
options.numThreads = numThreads;
|
options.verbosity = 1;
|
||||||
options.compressionLevel = level;
|
ASSERT_TRUE(roundTrip(options));
|
||||||
options.verbosity = 1;
|
errorGuard.dismiss();
|
||||||
ASSERT_TRUE(roundTrip(options));
|
|
||||||
errorGuard.dismiss();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,29 +76,26 @@ TEST(Pzstd, LargeSizes) {
|
|||||||
std::fclose(fd);
|
std::fclose(fd);
|
||||||
ASSERT_EQ(written, len);
|
ASSERT_EQ(written, len);
|
||||||
}
|
}
|
||||||
for (unsigned headers = 0; headers <= 1; ++headers) {
|
for (unsigned numThreads = 1; numThreads <= 16; numThreads *= 4) {
|
||||||
for (unsigned numThreads = 1; numThreads <= 16; numThreads *= 4) {
|
for (unsigned level = 1; level <= 4; level *= 4) {
|
||||||
for (unsigned level = 1; level <= 4; level *= 2) {
|
auto errorGuard = makeScopeGuard([&] {
|
||||||
auto errorGuard = makeScopeGuard([&] {
|
std::fprintf(stderr, "# threads: %u\n", numThreads);
|
||||||
std::fprintf(stderr, "pzstd headers: %u\n", headers);
|
std::fprintf(stderr, "compression level: %u\n", level);
|
||||||
std::fprintf(stderr, "# threads: %u\n", numThreads);
|
});
|
||||||
std::fprintf(stderr, "compression level: %u\n", level);
|
Options options;
|
||||||
});
|
options.overwrite = true;
|
||||||
Options options;
|
options.inputFiles = {inputFile};
|
||||||
options.overwrite = true;
|
options.numThreads = std::min(numThreads, options.numThreads);
|
||||||
options.inputFiles = {inputFile};
|
options.compressionLevel = level;
|
||||||
options.numThreads = std::min(numThreads, options.numThreads);
|
options.verbosity = 1;
|
||||||
options.compressionLevel = level;
|
ASSERT_TRUE(roundTrip(options));
|
||||||
options.verbosity = 1;
|
errorGuard.dismiss();
|
||||||
ASSERT_TRUE(roundTrip(options));
|
|
||||||
errorGuard.dismiss();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Pzstd, ExtremelyLargeSize) {
|
TEST(Pzstd, DISABLED_ExtremelyLargeSize) {
|
||||||
unsigned seed = std::random_device{}();
|
unsigned seed = std::random_device{}();
|
||||||
std::fprintf(stderr, "Pzstd.ExtremelyLargeSize seed: %u\n", seed);
|
std::fprintf(stderr, "Pzstd.ExtremelyLargeSize seed: %u\n", seed);
|
||||||
std::mt19937 gen(seed);
|
std::mt19937 gen(seed);
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
cxx_library(
|
||||||
|
name='buffer',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='utils',
|
||||||
|
exported_headers=['Buffer.h'],
|
||||||
|
deps=[':range'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='file_system',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='utils',
|
||||||
|
exported_headers=['FileSystem.h'],
|
||||||
|
deps=[':range'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='likely',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='utils',
|
||||||
|
exported_headers=['Likely.h'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='range',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='utils',
|
||||||
|
exported_headers=['Range.h'],
|
||||||
|
deps=[':likely'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='resource_pool',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='utils',
|
||||||
|
exported_headers=['ResourcePool.h'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='scope_guard',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='utils',
|
||||||
|
exported_headers=['ScopeGuard.h'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='thread_pool',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='utils',
|
||||||
|
exported_headers=['ThreadPool.h'],
|
||||||
|
deps=[':work_queue'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='work_queue',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='utils',
|
||||||
|
exported_headers=['WorkQueue.h'],
|
||||||
|
deps=[':buffer'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='utils',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
deps=[
|
||||||
|
':buffer',
|
||||||
|
':file_system',
|
||||||
|
':likely',
|
||||||
|
':range',
|
||||||
|
':resource_pool',
|
||||||
|
':scope_guard',
|
||||||
|
':thread_pool',
|
||||||
|
':work_queue',
|
||||||
|
],
|
||||||
|
)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
cxx_test(
|
||||||
|
name='buffer_test',
|
||||||
|
srcs=['BufferTest.cpp'],
|
||||||
|
deps=['//contrib/pzstd/utils:buffer'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_test(
|
||||||
|
name='range_test',
|
||||||
|
srcs=['RangeTest.cpp'],
|
||||||
|
deps=['//contrib/pzstd/utils:range'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_test(
|
||||||
|
name='resource_pool_test',
|
||||||
|
srcs=['ResourcePoolTest.cpp'],
|
||||||
|
deps=['//contrib/pzstd/utils:resource_pool'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_test(
|
||||||
|
name='scope_guard_test',
|
||||||
|
srcs=['ScopeGuardTest.cpp'],
|
||||||
|
deps=['//contrib/pzstd/utils:scope_guard'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_test(
|
||||||
|
name='thread_pool_test',
|
||||||
|
srcs=['ThreadPoolTest.cpp'],
|
||||||
|
deps=['//contrib/pzstd/utils:thread_pool'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_test(
|
||||||
|
name='work_queue_test',
|
||||||
|
srcs=['RangeTest.cpp'],
|
||||||
|
deps=['//contrib/pzstd/utils:work_queue'],
|
||||||
|
)
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB |
@@ -16,7 +16,7 @@ Distribution of this document is unlimited.
|
|||||||
|
|
||||||
### Version
|
### Version
|
||||||
|
|
||||||
0.2.2 (14/09/16)
|
0.2.3 (27/01/17)
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
@@ -57,7 +57,6 @@ Whenever it does not support a parameter defined in the compressed stream,
|
|||||||
it must produce a non-ambiguous error code and associated error message
|
it must produce a non-ambiguous error code and associated error message
|
||||||
explaining which parameter is unsupported.
|
explaining which parameter is unsupported.
|
||||||
|
|
||||||
|
|
||||||
Overall conventions
|
Overall conventions
|
||||||
-----------
|
-----------
|
||||||
In this document:
|
In this document:
|
||||||
@@ -117,7 +116,7 @@ Skippable frames defined in this specification are compatible with [LZ4] ones.
|
|||||||
__`Magic_Number`__
|
__`Magic_Number`__
|
||||||
|
|
||||||
4 Bytes, little-endian format.
|
4 Bytes, little-endian format.
|
||||||
Value : 0x184D2A5X, which means any value from 0x184D2A50 to 0x184D2A5F.
|
Value : 0x184D2A5?, which means any value from 0x184D2A50 to 0x184D2A5F.
|
||||||
All 16 values are valid to identify a skippable frame.
|
All 16 values are valid to identify a skippable frame.
|
||||||
|
|
||||||
__`Frame_Size`__
|
__`Frame_Size`__
|
||||||
@@ -267,7 +266,7 @@ The `Window_Descriptor` byte is optional. It is absent when `Single_Segment_flag
|
|||||||
In this case, the maximum back-reference distance is the content size itself,
|
In this case, the maximum back-reference distance is the content size itself,
|
||||||
which can be any value from 1 to 2^64-1 bytes (16 EB).
|
which can be any value from 1 to 2^64-1 bytes (16 EB).
|
||||||
|
|
||||||
| Bit numbers | 7-3 | 0-2 |
|
| Bit numbers | 7-3 | 2-0 |
|
||||||
| ----------- | ---------- | ---------- |
|
| ----------- | ---------- | ---------- |
|
||||||
| Field name | `Exponent` | `Mantissa` |
|
| Field name | `Exponent` | `Mantissa` |
|
||||||
|
|
||||||
@@ -381,9 +380,9 @@ There are 4 block types :
|
|||||||
This value cannot be used with current version of this specification.
|
This value cannot be used with current version of this specification.
|
||||||
|
|
||||||
Block sizes must respect a few rules :
|
Block sizes must respect a few rules :
|
||||||
- In compressed mode, compressed size if always strictly `< decompressed size`.
|
- In compressed mode, compressed size is always strictly less than decompressed size.
|
||||||
- Block decompressed size is always <= maximum back-reference distance .
|
- Block decompressed size is always <= maximum back-reference distance.
|
||||||
- Block decompressed size is always <= 128 KB
|
- Block decompressed size is always <= 128 KB.
|
||||||
|
|
||||||
|
|
||||||
__`Block_Content`__
|
__`Block_Content`__
|
||||||
@@ -478,13 +477,16 @@ For values spanning several bytes, convention is little-endian.
|
|||||||
|
|
||||||
__`Size_Format` for `Raw_Literals_Block` and `RLE_Literals_Block`__ :
|
__`Size_Format` for `Raw_Literals_Block` and `RLE_Literals_Block`__ :
|
||||||
|
|
||||||
- Value x0 : `Regenerated_Size` uses 5 bits (0-31).
|
- Value ?0 : `Size_Format` uses 1 bit.
|
||||||
|
`Regenerated_Size` uses 5 bits (0-31).
|
||||||
`Literals_Section_Header` has 1 byte.
|
`Literals_Section_Header` has 1 byte.
|
||||||
`Regenerated_Size = Header[0]>>3`
|
`Regenerated_Size = Header[0]>>3`
|
||||||
- Value 01 : `Regenerated_Size` uses 12 bits (0-4095).
|
- Value 01 : `Size_Format` uses 2 bits.
|
||||||
|
`Regenerated_Size` uses 12 bits (0-4095).
|
||||||
`Literals_Section_Header` has 2 bytes.
|
`Literals_Section_Header` has 2 bytes.
|
||||||
`Regenerated_Size = (Header[0]>>4) + (Header[1]<<4)`
|
`Regenerated_Size = (Header[0]>>4) + (Header[1]<<4)`
|
||||||
- Value 11 : `Regenerated_Size` uses 20 bits (0-1048575).
|
- Value 11 : `Size_Format` uses 2 bits.
|
||||||
|
`Regenerated_Size` uses 20 bits (0-1048575).
|
||||||
`Literals_Section_Header` has 3 bytes.
|
`Literals_Section_Header` has 3 bytes.
|
||||||
`Regenerated_Size = (Header[0]>>4) + (Header[1]<<4) + (Header[2]<<12)`
|
`Regenerated_Size = (Header[0]>>4) + (Header[1]<<4) + (Header[2]<<12)`
|
||||||
|
|
||||||
@@ -507,7 +509,8 @@ __`Size_Format` for `Compressed_Literals_Block` and `Repeat_Stats_Literals_Block
|
|||||||
`Literals_Section_Header` has 5 bytes.
|
`Literals_Section_Header` has 5 bytes.
|
||||||
|
|
||||||
Both `Compressed_Size` and `Regenerated_Size` fields follow little-endian convention.
|
Both `Compressed_Size` and `Regenerated_Size` fields follow little-endian convention.
|
||||||
|
Note: `Compressed_Size` __includes__ the size of the Huffman Tree description if it
|
||||||
|
is present.
|
||||||
|
|
||||||
#### `Huffman_Tree_Description`
|
#### `Huffman_Tree_Description`
|
||||||
|
|
||||||
@@ -550,23 +553,24 @@ Let's presume the following Huffman tree must be described :
|
|||||||
| `Number_of_Bits` | 1 | 2 | 3 | 0 | 4 | 4 |
|
| `Number_of_Bits` | 1 | 2 | 3 | 0 | 4 | 4 |
|
||||||
|
|
||||||
The tree depth is 4, since its smallest element uses 4 bits.
|
The tree depth is 4, since its smallest element uses 4 bits.
|
||||||
Value `5` will not be listed, nor will values above `5`.
|
Value `5` will not be listed as it can be determined from the values for 0-4,
|
||||||
|
nor will values above `5` as they are all 0.
|
||||||
Values from `0` to `4` will be listed using `Weight` instead of `Number_of_Bits`.
|
Values from `0` to `4` will be listed using `Weight` instead of `Number_of_Bits`.
|
||||||
Weight formula is :
|
Weight formula is :
|
||||||
```
|
```
|
||||||
Weight = Number_of_Bits ? (Max_Number_of_Bits + 1 - Number_of_Bits) : 0
|
Weight = Number_of_Bits ? (Max_Number_of_Bits + 1 - Number_of_Bits) : 0
|
||||||
```
|
```
|
||||||
It gives the following serie of weights :
|
It gives the following series of weights :
|
||||||
|
|
||||||
| `Weight` | 4 | 3 | 2 | 0 | 1 |
|
|
||||||
| -------- | --- | --- | --- | --- | --- |
|
|
||||||
| literal | 0 | 1 | 2 | 3 | 4 |
|
| literal | 0 | 1 | 2 | 3 | 4 |
|
||||||
|
| -------- | --- | --- | --- | --- | --- |
|
||||||
|
| `Weight` | 4 | 3 | 2 | 0 | 1 |
|
||||||
|
|
||||||
The decoder will do the inverse operation :
|
The decoder will do the inverse operation :
|
||||||
having collected weights of literals from `0` to `4`,
|
having collected weights of literals from `0` to `4`,
|
||||||
it knows the last literal, `5`, is present with a non-zero weight.
|
it knows the last literal, `5`, is present with a non-zero weight.
|
||||||
The weight of `5` can be deducted by joining to the nearest power of 2.
|
The weight of `5` can be determined by advancing to the next power of 2.
|
||||||
Sum of `2^(Weight-1)` (excluding 0) is :
|
The sum of `2^(Weight-1)` (excluding 0's) is :
|
||||||
`8 + 4 + 2 + 0 + 1 = 15`.
|
`8 + 4 + 2 + 0 + 1 = 15`.
|
||||||
Nearest power of 2 is 16.
|
Nearest power of 2 is 16.
|
||||||
Therefore, `Max_Number_of_Bits = 4` and `Weight[5] = 1`.
|
Therefore, `Max_Number_of_Bits = 4` and `Weight[5] = 1`.
|
||||||
@@ -574,23 +578,39 @@ Therefore, `Max_Number_of_Bits = 4` and `Weight[5] = 1`.
|
|||||||
##### Huffman Tree header
|
##### Huffman Tree header
|
||||||
|
|
||||||
This is a single byte value (0-255),
|
This is a single byte value (0-255),
|
||||||
which tells how to decode the list of weights.
|
which describes how to decode the list of weights.
|
||||||
|
|
||||||
- if `headerByte` >= 128 : this is a direct representation,
|
- if `headerByte` >= 128 : this is a direct representation,
|
||||||
where each `Weight` is written directly as a 4 bits field (0-15).
|
where each `Weight` is written directly as a 4 bits field (0-15).
|
||||||
|
They are encoded forward, 2 weights to a byte with the first weight taking
|
||||||
|
the top four bits and the second taking the bottom four (e.g. the following
|
||||||
|
operations could be used to read the weights:
|
||||||
|
`Weight[0] = (Byte[0] >> 4), Weight[1] = (Byte[0] & 0xf)`, etc.).
|
||||||
The full representation occupies `((Number_of_Symbols+1)/2)` bytes,
|
The full representation occupies `((Number_of_Symbols+1)/2)` bytes,
|
||||||
meaning it uses a last full byte even if `Number_of_Symbols` is odd.
|
meaning it uses a last full byte even if `Number_of_Symbols` is odd.
|
||||||
`Number_of_Symbols = headerByte - 127`.
|
`Number_of_Symbols = headerByte - 127`.
|
||||||
Note that maximum `Number_of_Symbols` is 255-127 = 128.
|
Note that maximum `Number_of_Symbols` is 255-127 = 128.
|
||||||
A larger serie must necessarily use FSE compression.
|
A larger series must necessarily use FSE compression.
|
||||||
|
|
||||||
- if `headerByte` < 128 :
|
- if `headerByte` < 128 :
|
||||||
the serie of weights is compressed by FSE.
|
the series of weights is compressed by FSE.
|
||||||
The length of the FSE-compressed serie is equal to `headerByte` (0-127).
|
The length of the FSE-compressed series is equal to `headerByte` (0-127).
|
||||||
|
|
||||||
##### Finite State Entropy (FSE) compression of Huffman weights
|
##### Finite State Entropy (FSE) compression of Huffman weights
|
||||||
|
|
||||||
The serie of weights is compressed using FSE compression.
|
FSE decoding uses three operations: `Init_State`, `Decode_Symbol`, and `Update_State`.
|
||||||
|
`Init_State` reads in the initial state value from a bitstream,
|
||||||
|
`Decode_Symbol` outputs a symbol based on the current state,
|
||||||
|
and `Update_State` goes to a new state based on the current state and some number of consumed bits.
|
||||||
|
|
||||||
|
FSE streams must be read in reverse from the order they're encoded in,
|
||||||
|
so bitstreams start at a certain offset and works backwards towards their base.
|
||||||
|
|
||||||
|
For more on how FSE bitstreams work, see [Finite State Entropy].
|
||||||
|
|
||||||
|
[Finite State Entropy]:https://github.com/Cyan4973/FiniteStateEntropy/
|
||||||
|
|
||||||
|
The series of Huffman weights is compressed using FSE compression.
|
||||||
It's a single bitstream with 2 interleaved states,
|
It's a single bitstream with 2 interleaved states,
|
||||||
sharing a single distribution table.
|
sharing a single distribution table.
|
||||||
|
|
||||||
@@ -598,22 +618,27 @@ To decode an FSE bitstream, it is necessary to know its compressed size.
|
|||||||
Compressed size is provided by `headerByte`.
|
Compressed size is provided by `headerByte`.
|
||||||
It's also necessary to know its _maximum possible_ decompressed size,
|
It's also necessary to know its _maximum possible_ decompressed size,
|
||||||
which is `255`, since literal values span from `0` to `255`,
|
which is `255`, since literal values span from `0` to `255`,
|
||||||
and last symbol value is not represented.
|
and last symbol's weight is not represented.
|
||||||
|
|
||||||
An FSE bitstream starts by a header, describing probabilities distribution.
|
An FSE bitstream starts by a header, describing probabilities distribution.
|
||||||
It will create a Decoding Table.
|
It will create a Decoding Table.
|
||||||
Table must be pre-allocated, which requires to support a maximum accuracy.
|
The table must be pre-allocated, so a maximum accuracy must be fixed.
|
||||||
For a list of Huffman weights, maximum accuracy is 7 bits.
|
For a list of Huffman weights, maximum accuracy is 7 bits.
|
||||||
|
|
||||||
FSE header is [described in relevant chapter](#fse-distribution-table--condensed-format),
|
The FSE header format is [described in a relevant chapter](#fse-distribution-table--condensed-format),
|
||||||
and so is [FSE bitstream](#bitstream).
|
as well as the [FSE bitstream](#bitstream).
|
||||||
The main difference is that Huffman header compression uses 2 states,
|
The main difference is that Huffman header compression uses 2 states,
|
||||||
which share the same FSE distribution table.
|
which share the same FSE distribution table.
|
||||||
Bitstream contains only FSE symbols (no interleaved "raw bitfields").
|
The first state (`State1`) encodes the even indexed symbols,
|
||||||
The number of symbols to decode is discovered
|
and the second (`State2`) encodes the odd indexes.
|
||||||
by tracking bitStream overflow condition.
|
State1 is initialized first, and then State2, and they take turns decoding
|
||||||
When both states have overflowed the bitstream, end is reached.
|
a single symbol and updating their state.
|
||||||
|
|
||||||
|
The number of symbols to decode is determined
|
||||||
|
by tracking bitStream overflow condition:
|
||||||
|
If updating state after decoding a symbol would require more bits than
|
||||||
|
remain in the stream, it is assumed the extra bits are 0. Then,
|
||||||
|
the symbols for each of the final states are decoded and the process is complete.
|
||||||
|
|
||||||
##### Conversion from weights to Huffman prefix codes
|
##### Conversion from weights to Huffman prefix codes
|
||||||
|
|
||||||
@@ -687,9 +712,20 @@ Consequently, a last byte of `0` is not possible.
|
|||||||
And the final-bit-flag itself is not part of the useful bitstream.
|
And the final-bit-flag itself is not part of the useful bitstream.
|
||||||
Hence, the last byte contains between 0 and 7 useful bits.
|
Hence, the last byte contains between 0 and 7 useful bits.
|
||||||
|
|
||||||
|
For example, if the literal sequence "0145" was encoded using the prefix codes above,
|
||||||
|
it would be encoded as:
|
||||||
|
```
|
||||||
|
00000001 01110000
|
||||||
|
```
|
||||||
|
|
||||||
|
|Symbol | 5 | 4 | 1 | 0 | Padding |
|
||||||
|
|--------|------|------|----|---|---------|
|
||||||
|
|Encoding|`0000`|`0001`|`01`|`1`| `10000` |
|
||||||
|
|
||||||
Starting from the end,
|
Starting from the end,
|
||||||
it's possible to read the bitstream in a little-endian fashion,
|
it's possible to read the bitstream in a little-endian fashion,
|
||||||
keeping track of already used bits.
|
keeping track of already used bits. Since the bitstream is encoded in reverse
|
||||||
|
order, by starting at the end the symbols can be read in forward order.
|
||||||
|
|
||||||
Reading the last `Max_Number_of_Bits` bits,
|
Reading the last `Max_Number_of_Bits` bits,
|
||||||
it's then possible to compare extracted value to decoding table,
|
it's then possible to compare extracted value to decoding table,
|
||||||
@@ -700,7 +736,6 @@ If a bitstream is not entirely and exactly consumed,
|
|||||||
hence reaching exactly its beginning position with _all_ bits consumed,
|
hence reaching exactly its beginning position with _all_ bits consumed,
|
||||||
the decoding process is considered faulty.
|
the decoding process is considered faulty.
|
||||||
|
|
||||||
|
|
||||||
### `Sequences_Section`
|
### `Sequences_Section`
|
||||||
|
|
||||||
A compressed block is a succession of _sequences_ .
|
A compressed block is a succession of _sequences_ .
|
||||||
@@ -712,7 +747,7 @@ The offset gives the position to copy from,
|
|||||||
which can be within a previous block.
|
which can be within a previous block.
|
||||||
|
|
||||||
When all _sequences_ are decoded,
|
When all _sequences_ are decoded,
|
||||||
if there is any literal left in the _literal section_,
|
if there is are any literals left in the _literal section_,
|
||||||
these bytes are added at the end of the block.
|
these bytes are added at the end of the block.
|
||||||
|
|
||||||
The `Sequences_Section` regroup all symbols required to decode commands.
|
The `Sequences_Section` regroup all symbols required to decode commands.
|
||||||
@@ -810,7 +845,7 @@ They define lengths from 0 to 131071 bytes.
|
|||||||
When `Compression_Mode` is `Predefined_Mode`,
|
When `Compression_Mode` is `Predefined_Mode`,
|
||||||
a predefined distribution is used for FSE compression.
|
a predefined distribution is used for FSE compression.
|
||||||
|
|
||||||
Below is its definition. It uses an accuracy of 6 bits (64 states).
|
Its definition is below. It uses an accuracy of 6 bits (64 states).
|
||||||
```
|
```
|
||||||
short literalsLength_defaultDistribution[36] =
|
short literalsLength_defaultDistribution[36] =
|
||||||
{ 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
|
{ 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
|
||||||
@@ -835,12 +870,12 @@ They define lengths from 3 to 131074 bytes.
|
|||||||
|
|
||||||
| `Match_Length_Code` | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
|
| `Match_Length_Code` | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
|
||||||
| ------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
|
| ------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
|
||||||
| `Baseline` | 67 | 83 | 99 | 131 | 258 | 514 | 1026 | 2050 |
|
| `Baseline` | 67 | 83 | 99 | 131 | 259 | 515 | 1027 | 2051 |
|
||||||
| `Number_of_Bits` | 4 | 4 | 5 | 7 | 8 | 9 | 10 | 11 |
|
| `Number_of_Bits` | 4 | 4 | 5 | 7 | 8 | 9 | 10 | 11 |
|
||||||
|
|
||||||
| `Match_Length_Code` | 48 | 49 | 50 | 51 | 52 |
|
| `Match_Length_Code` | 48 | 49 | 50 | 51 | 52 |
|
||||||
| ------------------- | ---- | ---- | ---- | ---- | ---- |
|
| ------------------- | ---- | ---- | ---- | ---- | ---- |
|
||||||
| `Baseline` | 4098 | 8194 |16486 |32770 |65538 |
|
| `Baseline` | 4099 | 8195 |16387 |32771 |65539 |
|
||||||
| `Number_of_Bits` | 12 | 13 | 14 | 15 | 16 |
|
| `Number_of_Bits` | 12 | 13 | 14 | 15 | 16 |
|
||||||
|
|
||||||
##### Default distribution for match length codes
|
##### Default distribution for match length codes
|
||||||
@@ -848,7 +883,7 @@ They define lengths from 3 to 131074 bytes.
|
|||||||
When `Compression_Mode` is defined as `Predefined_Mode`,
|
When `Compression_Mode` is defined as `Predefined_Mode`,
|
||||||
a predefined distribution is used for FSE compression.
|
a predefined distribution is used for FSE compression.
|
||||||
|
|
||||||
Below is its definition. It uses an accuracy of 6 bits (64 states).
|
Its definition is below. It uses an accuracy of 6 bits (64 states).
|
||||||
```
|
```
|
||||||
short matchLengths_defaultDistribution[53] =
|
short matchLengths_defaultDistribution[53] =
|
||||||
{ 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
|
{ 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
|
||||||
@@ -908,7 +943,7 @@ When present, they are in this order :
|
|||||||
- Match Lengths
|
- Match Lengths
|
||||||
|
|
||||||
The content to decode depends on their respective encoding mode :
|
The content to decode depends on their respective encoding mode :
|
||||||
- `Predefined_Mode` : no content. Use predefined distribution table.
|
- `Predefined_Mode` : no content. Use the predefined distribution table.
|
||||||
- `RLE_Mode` : 1 byte. This is the only code to use across the whole compressed block.
|
- `RLE_Mode` : 1 byte. This is the only code to use across the whole compressed block.
|
||||||
- `FSE_Compressed_Mode` : A distribution table is present.
|
- `FSE_Compressed_Mode` : A distribution table is present.
|
||||||
- `Repeat_Mode` : no content. Re-use distribution from previous compressed block.
|
- `Repeat_Mode` : no content. Re-use distribution from previous compressed block.
|
||||||
@@ -936,12 +971,12 @@ It depends on :
|
|||||||
__example__ :
|
__example__ :
|
||||||
Presuming an `Accuracy_Log` of 8,
|
Presuming an `Accuracy_Log` of 8,
|
||||||
and presuming 100 probabilities points have already been distributed,
|
and presuming 100 probabilities points have already been distributed,
|
||||||
the decoder may read any value from `0` to `255 - 100 + 1 == 156` (included).
|
the decoder may read any value from `0` to `255 - 100 + 1 == 156` (inclusive).
|
||||||
Therefore, it must read `log2sup(156) == 8` bits.
|
Therefore, it must read `log2sup(156) == 8` bits.
|
||||||
|
|
||||||
- Value decoded : small values use 1 less bit :
|
- Value decoded : small values use 1 less bit :
|
||||||
__example__ :
|
__example__ :
|
||||||
Presuming values from 0 to 156 (included) are possible,
|
Presuming values from 0 to 156 (inclusive) are possible,
|
||||||
255-156 = 99 values are remaining in an 8-bits field.
|
255-156 = 99 values are remaining in an 8-bits field.
|
||||||
They are used this way :
|
They are used this way :
|
||||||
first 99 values (hence from 0 to 98) use only 7 bits,
|
first 99 values (hence from 0 to 98) use only 7 bits,
|
||||||
@@ -967,7 +1002,7 @@ For the purpose of calculating cumulated distribution, it counts as one.
|
|||||||
|
|
||||||
[next paragraph]:#fse-decoding--from-normalized-distribution-to-decoding-tables
|
[next paragraph]:#fse-decoding--from-normalized-distribution-to-decoding-tables
|
||||||
|
|
||||||
When a symbol has a probability of `zero`,
|
When a symbol has a __probability__ of `zero`,
|
||||||
it is followed by a 2-bits repeat flag.
|
it is followed by a 2-bits repeat flag.
|
||||||
This repeat flag tells how many probabilities of zeroes follow the current one.
|
This repeat flag tells how many probabilities of zeroes follow the current one.
|
||||||
It provides a number ranging from 0 to 3.
|
It provides a number ranging from 0 to 3.
|
||||||
@@ -1012,6 +1047,9 @@ position &= tableSize-1;
|
|||||||
|
|
||||||
A position is skipped if already occupied,
|
A position is skipped if already occupied,
|
||||||
typically by a "less than 1" probability symbol.
|
typically by a "less than 1" probability symbol.
|
||||||
|
`position` does not reset between symbols, it simply iterates through
|
||||||
|
each position in the table, switching to the next symbol when enough
|
||||||
|
states have been allocated to the current one.
|
||||||
|
|
||||||
The result is a list of state values.
|
The result is a list of state values.
|
||||||
Each state will decode the current symbol.
|
Each state will decode the current symbol.
|
||||||
@@ -1043,7 +1081,7 @@ Numbering starts from higher states using less bits.
|
|||||||
| `Baseline` | 32 | 64 | 96 | 0 | 16 |
|
| `Baseline` | 32 | 64 | 96 | 0 | 16 |
|
||||||
| range | 32-63 | 64-95 | 96-127 | 0-15 | 16-31 |
|
| range | 32-63 | 64-95 | 96-127 | 0-15 | 16-31 |
|
||||||
|
|
||||||
Next state is determined from current state
|
The next state is determined from current state
|
||||||
by reading the required `Number_of_Bits`, and adding the specified `Baseline`.
|
by reading the required `Number_of_Bits`, and adding the specified `Baseline`.
|
||||||
|
|
||||||
|
|
||||||
@@ -1093,15 +1131,16 @@ and then for `Literals_Length`.
|
|||||||
It starts by inserting the number of literals defined by `Literals_Length`,
|
It starts by inserting the number of literals defined by `Literals_Length`,
|
||||||
then continue by copying `Match_Length` bytes from `currentPos - Offset`.
|
then continue by copying `Match_Length` bytes from `currentPos - Offset`.
|
||||||
|
|
||||||
The next operation is to update states.
|
If it is not the last sequence in the block,
|
||||||
Using rules pre-calculated in the decoding tables,
|
the next operation is to update states.
|
||||||
|
Using the rules pre-calculated in the decoding tables,
|
||||||
`Literals_Length_State` is updated,
|
`Literals_Length_State` is updated,
|
||||||
followed by `Match_Length_State`,
|
followed by `Match_Length_State`,
|
||||||
and then `Offset_State`.
|
and then `Offset_State`.
|
||||||
|
|
||||||
This operation will be repeated `Number_of_Sequences` times.
|
This operation will be repeated `Number_of_Sequences` times.
|
||||||
At the end, the bitstream shall be entirely consumed,
|
At the end, the bitstream shall be entirely consumed,
|
||||||
otherwise bitstream is considered corrupted.
|
otherwise the bitstream is considered corrupted.
|
||||||
|
|
||||||
[Symbol Decoding]:#the-codes-for-literals-lengths-match-lengths-and-offsets
|
[Symbol Decoding]:#the-codes-for-literals-lengths-match-lengths-and-offsets
|
||||||
|
|
||||||
@@ -1111,13 +1150,13 @@ As seen in [Offset Codes], the first 3 values define a repeated offset and we wi
|
|||||||
They are sorted in recency order, with `Repeated_Offset1` meaning "most recent one".
|
They are sorted in recency order, with `Repeated_Offset1` meaning "most recent one".
|
||||||
|
|
||||||
There is an exception though, when current sequence's literals length is `0`.
|
There is an exception though, when current sequence's literals length is `0`.
|
||||||
In which case, repeated offsets are "pushed by one",
|
In this case, repeated offsets are shifted by one,
|
||||||
so `Repeated_Offset1` becomes `Repeated_Offset2`, `Repeated_Offset2` becomes `Repeated_Offset3`,
|
so `Repeated_Offset1` becomes `Repeated_Offset2`, `Repeated_Offset2` becomes `Repeated_Offset3`,
|
||||||
and `Repeated_Offset3` becomes `Repeated_Offset1 - 1_byte`.
|
and `Repeated_Offset3` becomes `Repeated_Offset1 - 1_byte`.
|
||||||
|
|
||||||
On first block, offset history is populated by the following values : 1, 4 and 8 (in order).
|
In the first block, the offset history is populated with the following values : 1, 4 and 8 (in order).
|
||||||
|
|
||||||
Then each block receives its start value from previous compressed block.
|
Then each block gets its starting offset history from the ending values of the most recent compressed block.
|
||||||
Note that non-compressed blocks are skipped,
|
Note that non-compressed blocks are skipped,
|
||||||
they do not contribute to offset history.
|
they do not contribute to offset history.
|
||||||
|
|
||||||
@@ -1125,11 +1164,12 @@ they do not contribute to offset history.
|
|||||||
|
|
||||||
###### Offset updates rules
|
###### Offset updates rules
|
||||||
|
|
||||||
New offset take the lead in offset history,
|
The newest offset takes the lead in offset history,
|
||||||
up to its previous place if it was already present.
|
shifting others back (up to its previous place if it was already present).
|
||||||
|
|
||||||
It means that when `Repeated_Offset1` (most recent) is used, history is unmodified.
|
This means that when `Repeated_Offset1` (most recent) is used, history is unmodified.
|
||||||
When `Repeated_Offset2` is used, it's swapped with `Repeated_Offset1`.
|
When `Repeated_Offset2` is used, it's swapped with `Repeated_Offset1`.
|
||||||
|
If any other offset is used, it becomes `Repeated_Offset1` and the rest are shift back by one.
|
||||||
|
|
||||||
|
|
||||||
Dictionary format
|
Dictionary format
|
||||||
@@ -1137,6 +1177,9 @@ Dictionary format
|
|||||||
|
|
||||||
`zstd` is compatible with "raw content" dictionaries, free of any format restriction,
|
`zstd` is compatible with "raw content" dictionaries, free of any format restriction,
|
||||||
except that they must be at least 8 bytes.
|
except that they must be at least 8 bytes.
|
||||||
|
These dictionaries function as if they were just the `Content` block of a formatted
|
||||||
|
dictionary.
|
||||||
|
|
||||||
But dictionaries created by `zstd --train` follow a format, described here.
|
But dictionaries created by `zstd --train` follow a format, described here.
|
||||||
|
|
||||||
__Pre-requisites__ : a dictionary has a size,
|
__Pre-requisites__ : a dictionary has a size,
|
||||||
@@ -1160,16 +1203,17 @@ _Reserved ranges :_
|
|||||||
- low range : 1 - 32767
|
- low range : 1 - 32767
|
||||||
- high range : >= (2^31)
|
- high range : >= (2^31)
|
||||||
|
|
||||||
__`Entropy_Tables`__ : following the same format as a [compressed blocks].
|
__`Entropy_Tables`__ : following the same format as the tables in [compressed blocks].
|
||||||
They are stored in following order :
|
They are stored in following order :
|
||||||
Huffman tables for literals, FSE table for offsets,
|
Huffman tables for literals, FSE table for offsets,
|
||||||
FSE table for match lengths, and FSE table for literals lengths.
|
FSE table for match lengths, and FSE table for literals lengths.
|
||||||
It's finally followed by 3 offset values, populating recent offsets,
|
It's finally followed by 3 offset values, populating recent offsets (instead of using `{1,4,8}`),
|
||||||
stored in order, 4-bytes little-endian each, for a total of 12 bytes.
|
stored in order, 4-bytes little-endian each, for a total of 12 bytes.
|
||||||
Each recent offset must have a value < dictionary size.
|
Each recent offset must have a value < dictionary size.
|
||||||
|
|
||||||
__`Content`__ : The rest of the dictionary is its content.
|
__`Content`__ : The rest of the dictionary is its content.
|
||||||
The content act as a "past" in front of data to compress or decompress.
|
The content act as a "past" in front of data to compress or decompress,
|
||||||
|
so it can be referenced in sequence commands.
|
||||||
|
|
||||||
[compressed blocks]: #the-format-of-compressed_block
|
[compressed blocks]: #the-format-of-compressed_block
|
||||||
|
|
||||||
@@ -1358,6 +1402,7 @@ to crosscheck that an implementation implements the decoding table generation al
|
|||||||
|
|
||||||
Version changes
|
Version changes
|
||||||
---------------
|
---------------
|
||||||
|
- 0.2.3 : clarified several details, by Sean Purcell
|
||||||
- 0.2.2 : added predefined codes, by Johannes Rudolph
|
- 0.2.2 : added predefined codes, by Johannes Rudolph
|
||||||
- 0.2.1 : clarify field names, by Przemyslaw Skibinski
|
- 0.2.1 : clarify field names, by Przemyslaw Skibinski
|
||||||
- 0.2.0 : numerous format adjustments for zstd v0.8
|
- 0.2.0 : numerous format adjustments for zstd v0.8
|
||||||
|
|||||||
@@ -0,0 +1,186 @@
|
|||||||
|
cxx_library(
|
||||||
|
name='zstd',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
deps=[
|
||||||
|
':common',
|
||||||
|
':compress',
|
||||||
|
':decompress',
|
||||||
|
':deprecated',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='compress',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('compress', 'zstdmt_compress.h'),
|
||||||
|
]),
|
||||||
|
headers=subdir_glob([
|
||||||
|
('compress', 'zstd_opt.h'),
|
||||||
|
]),
|
||||||
|
srcs=[
|
||||||
|
'compress/zstd_compress.c',
|
||||||
|
'compress/zstdmt_compress.c',
|
||||||
|
],
|
||||||
|
deps=[':common'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='decompress',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
srcs=['decompress/zstd_decompress.c'],
|
||||||
|
deps=[
|
||||||
|
':common',
|
||||||
|
':legacy',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='deprecated',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('decprecated', '*.h'),
|
||||||
|
]),
|
||||||
|
srcs=glob(['deprecated/*.c']),
|
||||||
|
deps=[':common'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='legacy',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('legacy', '*.h'),
|
||||||
|
]),
|
||||||
|
srcs=glob(['legacy/*.c']),
|
||||||
|
deps=[':common'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='zdict',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('dictBuilder', 'zdict.h'),
|
||||||
|
]),
|
||||||
|
headers=subdir_glob([
|
||||||
|
('dictBuilder', 'divsufsort.h'),
|
||||||
|
]),
|
||||||
|
srcs=glob(['dictBuilder/*.c']),
|
||||||
|
deps=[':common'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='bitstream',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'bitstream.h'),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='entropy',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'fse.h'),
|
||||||
|
('common', 'huf.h'),
|
||||||
|
]),
|
||||||
|
srcs=[
|
||||||
|
'common/entropy_common.c',
|
||||||
|
'common/fse_decompress.c',
|
||||||
|
'compress/fse_compress.c',
|
||||||
|
'compress/huf_compress.c',
|
||||||
|
'decompress/huf_decompress.c',
|
||||||
|
],
|
||||||
|
deps=[
|
||||||
|
':bitstream',
|
||||||
|
':errors',
|
||||||
|
':mem',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='errors',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'error_private.h'),
|
||||||
|
('common', 'zstd_errors.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/error_private.c'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='mem',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'mem.h'),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='pool',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'pool.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/pool.c'],
|
||||||
|
deps=[':threading'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='threading',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'threading.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/threading.c'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='xxhash',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'xxhash.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/xxhash.c'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='zstd_common',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('', 'zstd.h'),
|
||||||
|
('common', 'zstd_internal.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/zstd_common.c'],
|
||||||
|
deps=[
|
||||||
|
':errors',
|
||||||
|
':mem',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='common',
|
||||||
|
deps=[
|
||||||
|
':bitstream',
|
||||||
|
':entropy',
|
||||||
|
':errors',
|
||||||
|
':mem',
|
||||||
|
':pool',
|
||||||
|
':threading',
|
||||||
|
':xxhash',
|
||||||
|
':zstd_common',
|
||||||
|
]
|
||||||
|
)
|
||||||
+58
-31
@@ -1,11 +1,13 @@
|
|||||||
# ################################################################
|
# ##########################################################################
|
||||||
# Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
# Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
# This Makefile is validated for Linux, macOS, *BSD, Hurd, Solaris, MSYS2 targets
|
||||||
|
#
|
||||||
# This source code is licensed under the BSD-style license found in the
|
# This source code is licensed under the BSD-style license found in the
|
||||||
# LICENSE file in the root directory of this source tree. An additional grant
|
# LICENSE file in the root directory of this source tree. An additional grant
|
||||||
# of patent rights can be found in the PATENTS file in the same directory.
|
# of patent rights can be found in the PATENTS file in the same directory.
|
||||||
# ################################################################
|
# ##########################################################################
|
||||||
|
|
||||||
# Version numbers
|
# Version numbers
|
||||||
LIBVER_MAJOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ./zstd.h`
|
LIBVER_MAJOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ./zstd.h`
|
||||||
@@ -18,17 +20,12 @@ LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT))
|
|||||||
LIBVER := $(shell echo $(LIBVER_SCRIPT))
|
LIBVER := $(shell echo $(LIBVER_SCRIPT))
|
||||||
VERSION?= $(LIBVER)
|
VERSION?= $(LIBVER)
|
||||||
|
|
||||||
DESTDIR?=
|
|
||||||
PREFIX ?= /usr/local
|
|
||||||
LIBDIR ?= $(PREFIX)/lib
|
|
||||||
INCLUDEDIR=$(PREFIX)/include
|
|
||||||
|
|
||||||
CPPFLAGS+= -I. -I./common -DXXH_NAMESPACE=ZSTD_
|
CPPFLAGS+= -I. -I./common -DXXH_NAMESPACE=ZSTD_
|
||||||
CFLAGS ?= -O3
|
CFLAGS ?= -O3
|
||||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 \
|
DEBUGFLAGS = -g -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||||
-Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wundef \
|
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||||
-Wpointer-arith
|
-Wstrict-prototypes -Wundef -Wpointer-arith
|
||||||
CFLAGS += $(MOREFLAGS)
|
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||||
FLAGS = $(CPPFLAGS) $(CFLAGS)
|
FLAGS = $(CPPFLAGS) $(CFLAGS)
|
||||||
|
|
||||||
|
|
||||||
@@ -41,6 +38,8 @@ CPPFLAGS += -I./legacy -DZSTD_LEGACY_SUPPORT=1
|
|||||||
ZSTD_FILES+= $(wildcard legacy/*.c)
|
ZSTD_FILES+= $(wildcard legacy/*.c)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ZSTD_OBJ := $(patsubst %.c,%.o,$(ZSTD_FILES))
|
||||||
|
|
||||||
# OS X linker doesn't support -soname, and use different extension
|
# OS X linker doesn't support -soname, and use different extension
|
||||||
# see : https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html
|
# see : https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html
|
||||||
ifeq ($(shell uname), Darwin)
|
ifeq ($(shell uname), Darwin)
|
||||||
@@ -60,15 +59,14 @@ LIBZSTD = libzstd.$(SHARED_EXT_VER)
|
|||||||
|
|
||||||
.PHONY: default all clean install uninstall
|
.PHONY: default all clean install uninstall
|
||||||
|
|
||||||
default: lib
|
default: lib-release
|
||||||
|
|
||||||
all: lib
|
all: lib
|
||||||
|
|
||||||
libzstd.a: ARFLAGS = rcs
|
libzstd.a: ARFLAGS = rcs
|
||||||
libzstd.a: $(ZSTD_FILES)
|
libzstd.a: $(ZSTD_OBJ)
|
||||||
@echo compiling static library
|
@echo compiling static library
|
||||||
@$(CC) $(FLAGS) -c $^
|
@$(AR) $(ARFLAGS) $@ $^
|
||||||
@$(AR) $(ARFLAGS) $@ *.o
|
|
||||||
|
|
||||||
$(LIBZSTD): LDFLAGS += -shared -fPIC -fvisibility=hidden
|
$(LIBZSTD): LDFLAGS += -shared -fPIC -fvisibility=hidden
|
||||||
$(LIBZSTD): $(ZSTD_FILES)
|
$(LIBZSTD): $(ZSTD_FILES)
|
||||||
@@ -87,14 +85,41 @@ libzstd : $(LIBZSTD)
|
|||||||
|
|
||||||
lib: libzstd.a libzstd
|
lib: libzstd.a libzstd
|
||||||
|
|
||||||
|
lib-release: DEBUGFLAGS :=
|
||||||
|
lib-release: lib
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(RM) core *.o *.a *.gcda *.$(SHARED_EXT) *.$(SHARED_EXT).* libzstd.pc dll/libzstd.dll dll/libzstd.lib
|
@$(RM) -r *.dSYM # Mac OS-X specific
|
||||||
@$(RM) decompress/*.o
|
@$(RM) core *.o *.a *.gcda *.$(SHARED_EXT) *.$(SHARED_EXT).* libzstd.pc
|
||||||
|
@$(RM) dll/libzstd.dll dll/libzstd.lib
|
||||||
|
@$(RM) common/*.o compress/*.o decompress/*.o dictBuilder/*.o legacy/*.o deprecated/*.o
|
||||||
@echo Cleaning library completed
|
@echo Cleaning library completed
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
#make install is validated only for Linux, OSX, kFreeBSD, Hurd and some BSD targets
|
# make install is validated only for Linux, OSX, BSD, Hurd and Solaris targets
|
||||||
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU FreeBSD DragonFly NetBSD))
|
#-----------------------------------------------------------------------------
|
||||||
|
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS))
|
||||||
|
|
||||||
|
ifneq (,$(filter $(shell uname),SunOS))
|
||||||
|
INSTALL ?= ginstall
|
||||||
|
else
|
||||||
|
INSTALL ?= install
|
||||||
|
endif
|
||||||
|
|
||||||
|
PREFIX ?= /usr/local
|
||||||
|
DESTDIR ?=
|
||||||
|
LIBDIR ?= $(PREFIX)/lib
|
||||||
|
INCLUDEDIR ?= $(PREFIX)/include
|
||||||
|
|
||||||
|
ifneq (,$(filter $(shell uname),OpenBSD FreeBSD NetBSD DragonFly))
|
||||||
|
PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig
|
||||||
|
else
|
||||||
|
PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig
|
||||||
|
endif
|
||||||
|
|
||||||
|
INSTALL_LIB ?= $(INSTALL) -m 755
|
||||||
|
INSTALL_DATA ?= $(INSTALL) -m 644
|
||||||
|
|
||||||
|
|
||||||
libzstd.pc:
|
libzstd.pc:
|
||||||
libzstd.pc: libzstd.pc.in
|
libzstd.pc: libzstd.pc.in
|
||||||
@@ -106,16 +131,18 @@ libzstd.pc: libzstd.pc.in
|
|||||||
$< >$@
|
$< >$@
|
||||||
|
|
||||||
install: libzstd.a libzstd libzstd.pc
|
install: libzstd.a libzstd libzstd.pc
|
||||||
@install -d -m 755 $(DESTDIR)$(LIBDIR)/pkgconfig/ $(DESTDIR)$(INCLUDEDIR)/
|
@$(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR)/ $(DESTDIR)$(INCLUDEDIR)/
|
||||||
@install -m 755 libzstd.$(SHARED_EXT_VER) $(DESTDIR)$(LIBDIR)
|
@$(INSTALL_DATA) libzstd.pc $(DESTDIR)$(PKGCONFIGDIR)/
|
||||||
@cp -a libzstd.$(SHARED_EXT_MAJOR) $(DESTDIR)$(LIBDIR)
|
@echo Installing libraries
|
||||||
@cp -a libzstd.$(SHARED_EXT) $(DESTDIR)$(LIBDIR)
|
@$(INSTALL_LIB) libzstd.a $(DESTDIR)$(LIBDIR)
|
||||||
@cp -a libzstd.pc $(DESTDIR)$(LIBDIR)/pkgconfig/
|
@$(INSTALL_LIB) libzstd.$(SHARED_EXT_VER) $(DESTDIR)$(LIBDIR)
|
||||||
@install -m 644 libzstd.a $(DESTDIR)$(LIBDIR)
|
@ln -sf libzstd.$(SHARED_EXT_VER) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)
|
||||||
@install -m 644 zstd.h $(DESTDIR)$(INCLUDEDIR)
|
@ln -sf libzstd.$(SHARED_EXT_VER) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)
|
||||||
@install -m 644 common/zstd_errors.h $(DESTDIR)$(INCLUDEDIR)
|
@echo Installing includes
|
||||||
@install -m 644 deprecated/zbuff.h $(DESTDIR)$(INCLUDEDIR) # prototypes generate deprecation warnings
|
@$(INSTALL_DATA) zstd.h $(DESTDIR)$(INCLUDEDIR)
|
||||||
@install -m 644 dictBuilder/zdict.h $(DESTDIR)$(INCLUDEDIR)
|
@$(INSTALL_DATA) common/zstd_errors.h $(DESTDIR)$(INCLUDEDIR)
|
||||||
|
@$(INSTALL_DATA) deprecated/zbuff.h $(DESTDIR)$(INCLUDEDIR) # prototypes generate deprecation warnings
|
||||||
|
@$(INSTALL_DATA) dictBuilder/zdict.h $(DESTDIR)$(INCLUDEDIR)
|
||||||
@echo zstd static and shared library installed
|
@echo zstd static and shared library installed
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
@@ -123,7 +150,7 @@ uninstall:
|
|||||||
@$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)
|
@$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)
|
||||||
@$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)
|
@$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)
|
||||||
@$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_VER)
|
@$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_VER)
|
||||||
@$(RM) $(DESTDIR)$(LIBDIR)/pkgconfig/libzstd.pc
|
@$(RM) $(DESTDIR)$(PKGCONFIGDIR)/libzstd.pc
|
||||||
@$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd.h
|
@$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd.h
|
||||||
@$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd_errors.h
|
@$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd_errors.h
|
||||||
@$(RM) $(DESTDIR)$(INCLUDEDIR)/zbuff.h # Deprecated streaming functions
|
@$(RM) $(DESTDIR)$(INCLUDEDIR)/zbuff.h # Deprecated streaming functions
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* code only tested on 32 and 64 bits systems */
|
/* code only tested on 32 and 64 bits systems */
|
||||||
#define MEM_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; }
|
#define MEM_STATIC_ASSERT(c) { enum { MEM_static_assert = 1/(int)(!!(c)) }; }
|
||||||
MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
|
MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,194 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* ====== Dependencies ======= */
|
||||||
|
#include <stddef.h> /* size_t */
|
||||||
|
#include <stdlib.h> /* malloc, calloc, free */
|
||||||
|
#include "pool.h"
|
||||||
|
|
||||||
|
/* ====== Compiler specifics ====== */
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
|
||||||
|
#include "threading.h" /* pthread adaptation */
|
||||||
|
|
||||||
|
/* A job is a function and an opaque argument */
|
||||||
|
typedef struct POOL_job_s {
|
||||||
|
POOL_function function;
|
||||||
|
void *opaque;
|
||||||
|
} POOL_job;
|
||||||
|
|
||||||
|
struct POOL_ctx_s {
|
||||||
|
/* Keep track of the threads */
|
||||||
|
pthread_t *threads;
|
||||||
|
size_t numThreads;
|
||||||
|
|
||||||
|
/* The queue is a circular buffer */
|
||||||
|
POOL_job *queue;
|
||||||
|
size_t queueHead;
|
||||||
|
size_t queueTail;
|
||||||
|
size_t queueSize;
|
||||||
|
/* The mutex protects the queue */
|
||||||
|
pthread_mutex_t queueMutex;
|
||||||
|
/* Condition variable for pushers to wait on when the queue is full */
|
||||||
|
pthread_cond_t queuePushCond;
|
||||||
|
/* Condition variables for poppers to wait on when the queue is empty */
|
||||||
|
pthread_cond_t queuePopCond;
|
||||||
|
/* Indicates if the queue is shutting down */
|
||||||
|
int shutdown;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* POOL_thread() :
|
||||||
|
Work thread for the thread pool.
|
||||||
|
Waits for jobs and executes them.
|
||||||
|
@returns : NULL on failure else non-null.
|
||||||
|
*/
|
||||||
|
static void* POOL_thread(void* opaque) {
|
||||||
|
POOL_ctx* const ctx = (POOL_ctx*)opaque;
|
||||||
|
if (!ctx) { return NULL; }
|
||||||
|
for (;;) {
|
||||||
|
/* Lock the mutex and wait for a non-empty queue or until shutdown */
|
||||||
|
pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
while (ctx->queueHead == ctx->queueTail && !ctx->shutdown) {
|
||||||
|
pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
|
||||||
|
}
|
||||||
|
/* empty => shutting down: so stop */
|
||||||
|
if (ctx->queueHead == ctx->queueTail) {
|
||||||
|
pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
return opaque;
|
||||||
|
}
|
||||||
|
/* Pop a job off the queue */
|
||||||
|
{ POOL_job const job = ctx->queue[ctx->queueHead];
|
||||||
|
ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
|
||||||
|
/* Unlock the mutex, signal a pusher, and run the job */
|
||||||
|
pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
pthread_cond_signal(&ctx->queuePushCond);
|
||||||
|
job.function(job.opaque);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Unreachable */
|
||||||
|
}
|
||||||
|
|
||||||
|
POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) {
|
||||||
|
POOL_ctx *ctx;
|
||||||
|
/* Check the parameters */
|
||||||
|
if (!numThreads || !queueSize) { return NULL; }
|
||||||
|
/* Allocate the context and zero initialize */
|
||||||
|
ctx = (POOL_ctx *)calloc(1, sizeof(POOL_ctx));
|
||||||
|
if (!ctx) { return NULL; }
|
||||||
|
/* Initialize the job queue.
|
||||||
|
* It needs one extra space since one space is wasted to differentiate empty
|
||||||
|
* and full queues.
|
||||||
|
*/
|
||||||
|
ctx->queueSize = queueSize + 1;
|
||||||
|
ctx->queue = (POOL_job *)malloc(ctx->queueSize * sizeof(POOL_job));
|
||||||
|
ctx->queueHead = 0;
|
||||||
|
ctx->queueTail = 0;
|
||||||
|
pthread_mutex_init(&ctx->queueMutex, NULL);
|
||||||
|
pthread_cond_init(&ctx->queuePushCond, NULL);
|
||||||
|
pthread_cond_init(&ctx->queuePopCond, NULL);
|
||||||
|
ctx->shutdown = 0;
|
||||||
|
/* Allocate space for the thread handles */
|
||||||
|
ctx->threads = (pthread_t *)malloc(numThreads * sizeof(pthread_t));
|
||||||
|
ctx->numThreads = 0;
|
||||||
|
/* Check for errors */
|
||||||
|
if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
|
||||||
|
/* Initialize the threads */
|
||||||
|
{ size_t i;
|
||||||
|
for (i = 0; i < numThreads; ++i) {
|
||||||
|
if (pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
|
||||||
|
ctx->numThreads = i;
|
||||||
|
POOL_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
} }
|
||||||
|
ctx->numThreads = numThreads;
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! POOL_join() :
|
||||||
|
Shutdown the queue, wake any sleeping threads, and join all of the threads.
|
||||||
|
*/
|
||||||
|
static void POOL_join(POOL_ctx *ctx) {
|
||||||
|
/* Shut down the queue */
|
||||||
|
pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
ctx->shutdown = 1;
|
||||||
|
pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
/* Wake up sleeping threads */
|
||||||
|
pthread_cond_broadcast(&ctx->queuePushCond);
|
||||||
|
pthread_cond_broadcast(&ctx->queuePopCond);
|
||||||
|
/* Join all of the threads */
|
||||||
|
{ size_t i;
|
||||||
|
for (i = 0; i < ctx->numThreads; ++i) {
|
||||||
|
pthread_join(ctx->threads[i], NULL);
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
void POOL_free(POOL_ctx *ctx) {
|
||||||
|
if (!ctx) { return; }
|
||||||
|
POOL_join(ctx);
|
||||||
|
pthread_mutex_destroy(&ctx->queueMutex);
|
||||||
|
pthread_cond_destroy(&ctx->queuePushCond);
|
||||||
|
pthread_cond_destroy(&ctx->queuePopCond);
|
||||||
|
if (ctx->queue) free(ctx->queue);
|
||||||
|
if (ctx->threads) free(ctx->threads);
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void POOL_add(void *ctxVoid, POOL_function function, void *opaque) {
|
||||||
|
POOL_ctx *ctx = (POOL_ctx *)ctxVoid;
|
||||||
|
if (!ctx) { return; }
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
{ POOL_job const job = {function, opaque};
|
||||||
|
/* Wait until there is space in the queue for the new job */
|
||||||
|
size_t newTail = (ctx->queueTail + 1) % ctx->queueSize;
|
||||||
|
while (ctx->queueHead == newTail && !ctx->shutdown) {
|
||||||
|
pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
|
||||||
|
newTail = (ctx->queueTail + 1) % ctx->queueSize;
|
||||||
|
}
|
||||||
|
/* The queue is still going => there is space */
|
||||||
|
if (!ctx->shutdown) {
|
||||||
|
ctx->queue[ctx->queueTail] = job;
|
||||||
|
ctx->queueTail = newTail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
pthread_cond_signal(&ctx->queuePopCond);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* ZSTD_MULTITHREAD not defined */
|
||||||
|
/* No multi-threading support */
|
||||||
|
|
||||||
|
/* We don't need any data, but if it is empty malloc() might return NULL. */
|
||||||
|
struct POOL_ctx_s {
|
||||||
|
int data;
|
||||||
|
};
|
||||||
|
|
||||||
|
POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) {
|
||||||
|
(void)numThreads;
|
||||||
|
(void)queueSize;
|
||||||
|
return (POOL_ctx *)malloc(sizeof(POOL_ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
void POOL_free(POOL_ctx *ctx) {
|
||||||
|
if (ctx) free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void POOL_add(void *ctx, POOL_function function, void *opaque) {
|
||||||
|
(void)ctx;
|
||||||
|
function(opaque);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ZSTD_MULTITHREAD */
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
#ifndef POOL_H
|
||||||
|
#define POOL_H
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h> /* size_t */
|
||||||
|
|
||||||
|
typedef struct POOL_ctx_s POOL_ctx;
|
||||||
|
|
||||||
|
/*! POOL_create() :
|
||||||
|
Create a thread pool with at most `numThreads` threads.
|
||||||
|
`numThreads` must be at least 1.
|
||||||
|
The maximum number of queued jobs before blocking is `queueSize`.
|
||||||
|
`queueSize` must be at least 1.
|
||||||
|
@return : The POOL_ctx pointer on success else NULL.
|
||||||
|
*/
|
||||||
|
POOL_ctx *POOL_create(size_t numThreads, size_t queueSize);
|
||||||
|
|
||||||
|
/*! POOL_free() :
|
||||||
|
Free a thread pool returned by POOL_create().
|
||||||
|
*/
|
||||||
|
void POOL_free(POOL_ctx *ctx);
|
||||||
|
|
||||||
|
/*! POOL_function :
|
||||||
|
The function type that can be added to a thread pool.
|
||||||
|
*/
|
||||||
|
typedef void (*POOL_function)(void *);
|
||||||
|
/*! POOL_add_function :
|
||||||
|
The function type for a generic thread pool add function.
|
||||||
|
*/
|
||||||
|
typedef void (*POOL_add_function)(void *, POOL_function, void *);
|
||||||
|
|
||||||
|
/*! POOL_add() :
|
||||||
|
Add the job `function(opaque)` to the thread pool.
|
||||||
|
Possibly blocks until there is room in the queue.
|
||||||
|
Note : The function may be executed asynchronously, so `opaque` must live until the function has been completed.
|
||||||
|
*/
|
||||||
|
void POOL_add(void *ctx, POOL_function function, void *opaque);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2016 Tino Reichardt
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* You can contact the author at:
|
||||||
|
* - zstdmt source repository: https://github.com/mcmilk/zstdmt
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file will hold wrapper for systems, which do not support pthreads
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ====== Compiler specifics ====== */
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable : 4206) /* disable: C4206: translation unit is empty (when ZSTD_MULTITHREAD is not defined) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows minimalist Pthread Wrapper, based on :
|
||||||
|
* http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* === Dependencies === */
|
||||||
|
#include <process.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "threading.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* === Implementation === */
|
||||||
|
|
||||||
|
static unsigned __stdcall worker(void *arg)
|
||||||
|
{
|
||||||
|
pthread_t* const thread = (pthread_t*) arg;
|
||||||
|
thread->arg = thread->start_routine(thread->arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_create(pthread_t* thread, const void* unused,
|
||||||
|
void* (*start_routine) (void*), void* arg)
|
||||||
|
{
|
||||||
|
(void)unused;
|
||||||
|
thread->arg = arg;
|
||||||
|
thread->start_routine = start_routine;
|
||||||
|
thread->handle = (HANDLE) _beginthreadex(NULL, 0, worker, thread, 0, NULL);
|
||||||
|
|
||||||
|
if (!thread->handle)
|
||||||
|
return errno;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _pthread_join(pthread_t * thread, void **value_ptr)
|
||||||
|
{
|
||||||
|
DWORD result;
|
||||||
|
|
||||||
|
if (!thread->handle) return 0;
|
||||||
|
|
||||||
|
result = WaitForSingleObject(thread->handle, INFINITE);
|
||||||
|
switch (result) {
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
if (value_ptr) *value_ptr = thread->arg;
|
||||||
|
return 0;
|
||||||
|
case WAIT_ABANDONED:
|
||||||
|
return EINVAL;
|
||||||
|
default:
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ZSTD_MULTITHREAD */
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2016 Tino Reichardt
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* You can contact the author at:
|
||||||
|
* - zstdmt source repository: https://github.com/mcmilk/zstdmt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef THREADING_H_938743
|
||||||
|
#define THREADING_H_938743
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows minimalist Pthread Wrapper, based on :
|
||||||
|
* http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
|
||||||
|
*/
|
||||||
|
#ifdef WINVER
|
||||||
|
# undef WINVER
|
||||||
|
#endif
|
||||||
|
#define WINVER 0x0600
|
||||||
|
|
||||||
|
#ifdef _WIN32_WINNT
|
||||||
|
# undef _WIN32_WINNT
|
||||||
|
#endif
|
||||||
|
#define _WIN32_WINNT 0x0600
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
/* mutex */
|
||||||
|
#define pthread_mutex_t CRITICAL_SECTION
|
||||||
|
#define pthread_mutex_init(a,b) InitializeCriticalSection((a))
|
||||||
|
#define pthread_mutex_destroy(a) DeleteCriticalSection((a))
|
||||||
|
#define pthread_mutex_lock(a) EnterCriticalSection((a))
|
||||||
|
#define pthread_mutex_unlock(a) LeaveCriticalSection((a))
|
||||||
|
|
||||||
|
/* condition variable */
|
||||||
|
#define pthread_cond_t CONDITION_VARIABLE
|
||||||
|
#define pthread_cond_init(a, b) InitializeConditionVariable((a))
|
||||||
|
#define pthread_cond_destroy(a) /* No delete */
|
||||||
|
#define pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE)
|
||||||
|
#define pthread_cond_signal(a) WakeConditionVariable((a))
|
||||||
|
#define pthread_cond_broadcast(a) WakeAllConditionVariable((a))
|
||||||
|
|
||||||
|
/* pthread_create() and pthread_join() */
|
||||||
|
typedef struct {
|
||||||
|
HANDLE handle;
|
||||||
|
void* (*start_routine)(void*);
|
||||||
|
void* arg;
|
||||||
|
} pthread_t;
|
||||||
|
|
||||||
|
int pthread_create(pthread_t* thread, const void* unused,
|
||||||
|
void* (*start_routine) (void*), void* arg);
|
||||||
|
|
||||||
|
#define pthread_join(a, b) _pthread_join(&(a), (b))
|
||||||
|
int _pthread_join(pthread_t* thread, void** value_ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add here more wrappers as required
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(ZSTD_MULTITHREAD) /* posix assumed ; need a better detection mathod */
|
||||||
|
/* === POSIX Systems === */
|
||||||
|
# include <pthread.h>
|
||||||
|
|
||||||
|
#else /* ZSTD_MULTITHREAD not defined */
|
||||||
|
/* No multithreading support */
|
||||||
|
|
||||||
|
#define pthread_mutex_t int /* #define rather than typedef, as sometimes pthread support is implicit, resulting in duplicated symbols */
|
||||||
|
#define pthread_mutex_init(a,b)
|
||||||
|
#define pthread_mutex_destroy(a)
|
||||||
|
#define pthread_mutex_lock(a)
|
||||||
|
#define pthread_mutex_unlock(a)
|
||||||
|
|
||||||
|
#define pthread_cond_t int
|
||||||
|
#define pthread_cond_init(a,b)
|
||||||
|
#define pthread_cond_destroy(a)
|
||||||
|
#define pthread_cond_wait(a,b)
|
||||||
|
#define pthread_cond_signal(a)
|
||||||
|
#define pthread_cond_broadcast(a)
|
||||||
|
|
||||||
|
/* do not use pthread_t */
|
||||||
|
|
||||||
|
#endif /* ZSTD_MULTITHREAD */
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* THREADING_H_938743 */
|
||||||
@@ -43,10 +43,6 @@ ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); }
|
|||||||
* provides error code string from enum */
|
* provides error code string from enum */
|
||||||
const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorName(code); }
|
const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorName(code); }
|
||||||
|
|
||||||
/* --- ZBUFF Error Management (deprecated) --- */
|
|
||||||
unsigned ZBUFF_isError(size_t errorCode) { return ERR_isError(errorCode); }
|
|
||||||
const char* ZBUFF_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
|
|
||||||
|
|
||||||
|
|
||||||
/*=**************************************************************
|
/*=**************************************************************
|
||||||
* Custom allocator
|
* Custom allocator
|
||||||
|
|||||||
@@ -18,6 +18,20 @@ extern "C" {
|
|||||||
#include <stddef.h> /* size_t */
|
#include <stddef.h> /* size_t */
|
||||||
|
|
||||||
|
|
||||||
|
/* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
# define ZSTDERRORLIB_VISIBILITY __attribute__ ((visibility ("default")))
|
||||||
|
#else
|
||||||
|
# define ZSTDERRORLIB_VISIBILITY
|
||||||
|
#endif
|
||||||
|
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||||
|
# define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBILITY
|
||||||
|
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||||
|
# define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||||
|
#else
|
||||||
|
# define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBILITY
|
||||||
|
#endif
|
||||||
|
|
||||||
/*-****************************************
|
/*-****************************************
|
||||||
* error codes list
|
* error codes list
|
||||||
******************************************/
|
******************************************/
|
||||||
@@ -49,8 +63,8 @@ typedef enum {
|
|||||||
/*! ZSTD_getErrorCode() :
|
/*! ZSTD_getErrorCode() :
|
||||||
convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
|
convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
|
||||||
which can be used to compare directly with enum list published into "error_public.h" */
|
which can be used to compare directly with enum list published into "error_public.h" */
|
||||||
ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
|
ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
|
||||||
const char* ZSTD_getErrorString(ZSTD_ErrorCode code);
|
ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code);
|
||||||
|
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
|
|||||||
@@ -267,4 +267,13 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* hidden functions */
|
||||||
|
|
||||||
|
/* ZSTD_invalidateRepCodes() :
|
||||||
|
* ensures next compression will not use repcodes from previous block.
|
||||||
|
* Note : only works with regular variant;
|
||||||
|
* do not use with extDict variant ! */
|
||||||
|
void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);
|
||||||
|
|
||||||
|
|
||||||
#endif /* ZSTD_CCOMMON_H_MODULE */
|
#endif /* ZSTD_CCOMMON_H_MODULE */
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
|
|||||||
/*-*************************************
|
/*-*************************************
|
||||||
* Context memory management
|
* Context memory management
|
||||||
***************************************/
|
***************************************/
|
||||||
struct ZSTD_CCtx_s
|
struct ZSTD_CCtx_s {
|
||||||
{
|
|
||||||
const BYTE* nextSrc; /* next block here to continue on current prefix */
|
const BYTE* nextSrc; /* next block here to continue on current prefix */
|
||||||
const BYTE* base; /* All regular indexes relative to this position */
|
const BYTE* base; /* All regular indexes relative to this position */
|
||||||
const BYTE* dictBase; /* extDict indexes relative to this position */
|
const BYTE* dictBase; /* extDict indexes relative to this position */
|
||||||
@@ -61,10 +60,11 @@ struct ZSTD_CCtx_s
|
|||||||
U32 nextToUpdate; /* index from which to continue dictionary update */
|
U32 nextToUpdate; /* index from which to continue dictionary update */
|
||||||
U32 nextToUpdate3; /* index from which to continue dictionary update */
|
U32 nextToUpdate3; /* index from which to continue dictionary update */
|
||||||
U32 hashLog3; /* dispatch table : larger == faster, more memory */
|
U32 hashLog3; /* dispatch table : larger == faster, more memory */
|
||||||
U32 loadedDictEnd;
|
U32 loadedDictEnd; /* index of end of dictionary */
|
||||||
|
U32 forceWindow; /* force back-references to respect limit of 1<<wLog, even for dictionary */
|
||||||
ZSTD_compressionStage_e stage;
|
ZSTD_compressionStage_e stage;
|
||||||
U32 rep[ZSTD_REP_NUM];
|
U32 rep[ZSTD_REP_NUM];
|
||||||
U32 savedRep[ZSTD_REP_NUM];
|
U32 repToConfirm[ZSTD_REP_NUM];
|
||||||
U32 dictID;
|
U32 dictID;
|
||||||
ZSTD_parameters params;
|
ZSTD_parameters params;
|
||||||
void* workSpace;
|
void* workSpace;
|
||||||
@@ -101,7 +101,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
|
|||||||
cctx = (ZSTD_CCtx*) ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
|
cctx = (ZSTD_CCtx*) ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
|
||||||
if (!cctx) return NULL;
|
if (!cctx) return NULL;
|
||||||
memset(cctx, 0, sizeof(ZSTD_CCtx));
|
memset(cctx, 0, sizeof(ZSTD_CCtx));
|
||||||
memcpy(&(cctx->customMem), &customMem, sizeof(customMem));
|
cctx->customMem = customMem;
|
||||||
return cctx;
|
return cctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +119,15 @@ size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
|
|||||||
return sizeof(*cctx) + cctx->workSpaceSize;
|
return sizeof(*cctx) + cctx->workSpaceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value)
|
||||||
|
{
|
||||||
|
switch(param)
|
||||||
|
{
|
||||||
|
case ZSTD_p_forceWindow : cctx->forceWindow = value>0; cctx->loadedDictEnd = 0; return 0;
|
||||||
|
default: return ERROR(parameter_unknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) /* hidden interface */
|
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) /* hidden interface */
|
||||||
{
|
{
|
||||||
return &(ctx->seqStore);
|
return &(ctx->seqStore);
|
||||||
@@ -318,6 +327,14 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ZSTD_invalidateRepCodes() :
|
||||||
|
* ensures next compression will not use repcodes from previous block.
|
||||||
|
* Note : only works with regular variant;
|
||||||
|
* do not use with extDict variant ! */
|
||||||
|
void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<ZSTD_REP_NUM; i++) cctx->rep[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*! ZSTD_copyCCtx() :
|
/*! ZSTD_copyCCtx() :
|
||||||
* Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
|
* Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
|
||||||
@@ -735,12 +752,19 @@ _check_compressibility:
|
|||||||
if ((size_t)(op-ostart) >= maxCSize) return 0; }
|
if ((size_t)(op-ostart) >= maxCSize) return 0; }
|
||||||
|
|
||||||
/* confirm repcodes */
|
/* confirm repcodes */
|
||||||
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->rep[i] = zc->savedRep[i]; }
|
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->rep[i] = zc->repToConfirm[i]; }
|
||||||
|
|
||||||
return op - ostart;
|
return op - ostart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 /* for debug */
|
||||||
|
# define STORESEQ_DEBUG
|
||||||
|
#include <stdio.h> /* fprintf */
|
||||||
|
U32 g_startDebug = 0;
|
||||||
|
const BYTE* g_start = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! ZSTD_storeSeq() :
|
/*! ZSTD_storeSeq() :
|
||||||
Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
|
Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
|
||||||
`offsetCode` : distance to match, or 0 == repCode.
|
`offsetCode` : distance to match, or 0 == repCode.
|
||||||
@@ -748,13 +772,14 @@ _check_compressibility:
|
|||||||
*/
|
*/
|
||||||
MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
|
MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
|
||||||
{
|
{
|
||||||
#if 0 /* for debug */
|
#ifdef STORESEQ_DEBUG
|
||||||
static const BYTE* g_start = NULL;
|
if (g_startDebug) {
|
||||||
const U32 pos = (U32)((const BYTE*)literals - g_start);
|
const U32 pos = (U32)((const BYTE*)literals - g_start);
|
||||||
if (g_start==NULL) g_start = (const BYTE*)literals;
|
if (g_start==NULL) g_start = (const BYTE*)literals;
|
||||||
//if ((pos > 1) && (pos < 50000))
|
if ((pos > 1895000) && (pos < 1895300))
|
||||||
printf("Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
|
fprintf(stderr, "Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
|
||||||
pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
|
pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
/* copy Literals */
|
/* copy Literals */
|
||||||
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
|
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
|
||||||
@@ -1004,8 +1029,8 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
|
|||||||
} } }
|
} } }
|
||||||
|
|
||||||
/* save reps for next block */
|
/* save reps for next block */
|
||||||
cctx->savedRep[0] = offset_1 ? offset_1 : offsetSaved;
|
cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
|
||||||
cctx->savedRep[1] = offset_2 ? offset_2 : offsetSaved;
|
cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
|
||||||
|
|
||||||
/* Last Literals */
|
/* Last Literals */
|
||||||
{ size_t const lastLLSize = iend - anchor;
|
{ size_t const lastLLSize = iend - anchor;
|
||||||
@@ -1119,7 +1144,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
|||||||
} } }
|
} } }
|
||||||
|
|
||||||
/* save reps for next block */
|
/* save reps for next block */
|
||||||
ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
|
ctx->repToConfirm[0] = offset_1; ctx->repToConfirm[1] = offset_2;
|
||||||
|
|
||||||
/* Last Literals */
|
/* Last Literals */
|
||||||
{ size_t const lastLLSize = iend - anchor;
|
{ size_t const lastLLSize = iend - anchor;
|
||||||
@@ -1273,8 +1298,8 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
|
|||||||
} } }
|
} } }
|
||||||
|
|
||||||
/* save reps for next block */
|
/* save reps for next block */
|
||||||
cctx->savedRep[0] = offset_1 ? offset_1 : offsetSaved;
|
cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
|
||||||
cctx->savedRep[1] = offset_2 ? offset_2 : offsetSaved;
|
cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
|
||||||
|
|
||||||
/* Last Literals */
|
/* Last Literals */
|
||||||
{ size_t const lastLLSize = iend - anchor;
|
{ size_t const lastLLSize = iend - anchor;
|
||||||
@@ -1423,7 +1448,7 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
|
|||||||
} } }
|
} } }
|
||||||
|
|
||||||
/* save reps for next block */
|
/* save reps for next block */
|
||||||
ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
|
ctx->repToConfirm[0] = offset_1; ctx->repToConfirm[1] = offset_2;
|
||||||
|
|
||||||
/* Last Literals */
|
/* Last Literals */
|
||||||
{ size_t const lastLLSize = iend - anchor;
|
{ size_t const lastLLSize = iend - anchor;
|
||||||
@@ -1955,8 +1980,8 @@ _storeSequence:
|
|||||||
} }
|
} }
|
||||||
|
|
||||||
/* Save reps for next block */
|
/* Save reps for next block */
|
||||||
ctx->savedRep[0] = offset_1 ? offset_1 : savedOffset;
|
ctx->repToConfirm[0] = offset_1 ? offset_1 : savedOffset;
|
||||||
ctx->savedRep[1] = offset_2 ? offset_2 : savedOffset;
|
ctx->repToConfirm[1] = offset_2 ? offset_2 : savedOffset;
|
||||||
|
|
||||||
/* Last Literals */
|
/* Last Literals */
|
||||||
{ size_t const lastLLSize = iend - anchor;
|
{ size_t const lastLLSize = iend - anchor;
|
||||||
@@ -2150,7 +2175,7 @@ _storeSequence:
|
|||||||
} }
|
} }
|
||||||
|
|
||||||
/* Save reps for next block */
|
/* Save reps for next block */
|
||||||
ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
|
ctx->repToConfirm[0] = offset_1; ctx->repToConfirm[1] = offset_2;
|
||||||
|
|
||||||
/* Last Literals */
|
/* Last Literals */
|
||||||
{ size_t const lastLLSize = iend - anchor;
|
{ size_t const lastLLSize = iend - anchor;
|
||||||
@@ -2409,12 +2434,14 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
|||||||
|
|
||||||
cctx->nextSrc = ip + srcSize;
|
cctx->nextSrc = ip + srcSize;
|
||||||
|
|
||||||
{ size_t const cSize = frame ?
|
if (srcSize) {
|
||||||
|
size_t const cSize = frame ?
|
||||||
ZSTD_compress_generic (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
|
ZSTD_compress_generic (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
|
||||||
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
|
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
|
||||||
if (ZSTD_isError(cSize)) return cSize;
|
if (ZSTD_isError(cSize)) return cSize;
|
||||||
return cSize + fhSize;
|
return cSize + fhSize;
|
||||||
}
|
} else
|
||||||
|
return fhSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2450,7 +2477,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
|
|||||||
zc->dictBase = zc->base;
|
zc->dictBase = zc->base;
|
||||||
zc->base += ip - zc->nextSrc;
|
zc->base += ip - zc->nextSrc;
|
||||||
zc->nextToUpdate = zc->dictLimit;
|
zc->nextToUpdate = zc->dictLimit;
|
||||||
zc->loadedDictEnd = (U32)(iend - zc->base);
|
zc->loadedDictEnd = zc->forceWindow ? 0 : (U32)(iend - zc->base);
|
||||||
|
|
||||||
zc->nextSrc = iend;
|
zc->nextSrc = iend;
|
||||||
if (srcSize <= HASH_READ_SIZE) return 0;
|
if (srcSize <= HASH_READ_SIZE) return 0;
|
||||||
@@ -2557,9 +2584,9 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
||||||
cctx->rep[0] = MEM_readLE32(dictPtr+0); if (cctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
|
cctx->rep[0] = MEM_readLE32(dictPtr+0); if (cctx->rep[0] == 0 || cctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
|
||||||
cctx->rep[1] = MEM_readLE32(dictPtr+4); if (cctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
|
cctx->rep[1] = MEM_readLE32(dictPtr+4); if (cctx->rep[1] == 0 || cctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
|
||||||
cctx->rep[2] = MEM_readLE32(dictPtr+8); if (cctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
|
cctx->rep[2] = MEM_readLE32(dictPtr+8); if (cctx->rep[2] == 0 || cctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
|
||||||
dictPtr += 12;
|
dictPtr += 12;
|
||||||
|
|
||||||
{ U32 offcodeMax = MaxOff;
|
{ U32 offcodeMax = MaxOff;
|
||||||
@@ -2594,7 +2621,6 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, si
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! ZSTD_compressBegin_internal() :
|
/*! ZSTD_compressBegin_internal() :
|
||||||
* @return : 0, or an error code */
|
* @return : 0, or an error code */
|
||||||
static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
||||||
@@ -2626,9 +2652,9 @@ size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t di
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel)
|
size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
|
||||||
{
|
{
|
||||||
return ZSTD_compressBegin_usingDict(zc, NULL, 0, compressionLevel);
|
return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2733,7 +2759,8 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcS
|
|||||||
/* ===== Dictionary API ===== */
|
/* ===== Dictionary API ===== */
|
||||||
|
|
||||||
struct ZSTD_CDict_s {
|
struct ZSTD_CDict_s {
|
||||||
void* dictContent;
|
void* dictBuffer;
|
||||||
|
const void* dictContent;
|
||||||
size_t dictContentSize;
|
size_t dictContentSize;
|
||||||
ZSTD_CCtx* refContext;
|
ZSTD_CCtx* refContext;
|
||||||
}; /* typedef'd tp ZSTD_CDict within "zstd.h" */
|
}; /* typedef'd tp ZSTD_CDict within "zstd.h" */
|
||||||
@@ -2741,39 +2768,45 @@ struct ZSTD_CDict_s {
|
|||||||
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
|
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
|
||||||
{
|
{
|
||||||
if (cdict==NULL) return 0; /* support sizeof on NULL */
|
if (cdict==NULL) return 0; /* support sizeof on NULL */
|
||||||
return ZSTD_sizeof_CCtx(cdict->refContext) + cdict->dictContentSize;
|
return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, ZSTD_parameters params, ZSTD_customMem customMem)
|
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, unsigned byReference,
|
||||||
|
ZSTD_parameters params, ZSTD_customMem customMem)
|
||||||
{
|
{
|
||||||
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
||||||
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
||||||
|
|
||||||
{ ZSTD_CDict* const cdict = (ZSTD_CDict*) ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
|
{ ZSTD_CDict* const cdict = (ZSTD_CDict*) ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
|
||||||
void* const dictContent = ZSTD_malloc(dictSize, customMem);
|
|
||||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
|
ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
|
||||||
|
|
||||||
if (!dictContent || !cdict || !cctx) {
|
if (!cdict || !cctx) {
|
||||||
ZSTD_free(dictContent, customMem);
|
|
||||||
ZSTD_free(cdict, customMem);
|
ZSTD_free(cdict, customMem);
|
||||||
ZSTD_free(cctx, customMem);
|
ZSTD_free(cctx, customMem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dictSize) {
|
if ((byReference) || (!dictBuffer) || (!dictSize)) {
|
||||||
memcpy(dictContent, dict, dictSize);
|
cdict->dictBuffer = NULL;
|
||||||
|
cdict->dictContent = dictBuffer;
|
||||||
|
} else {
|
||||||
|
void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
|
||||||
|
if (!internalBuffer) { ZSTD_free(cctx, customMem); ZSTD_free(cdict, customMem); return NULL; }
|
||||||
|
memcpy(internalBuffer, dictBuffer, dictSize);
|
||||||
|
cdict->dictBuffer = internalBuffer;
|
||||||
|
cdict->dictContent = internalBuffer;
|
||||||
}
|
}
|
||||||
{ size_t const errorCode = ZSTD_compressBegin_advanced(cctx, dictContent, dictSize, params, 0);
|
|
||||||
|
{ size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0);
|
||||||
if (ZSTD_isError(errorCode)) {
|
if (ZSTD_isError(errorCode)) {
|
||||||
ZSTD_free(dictContent, customMem);
|
ZSTD_free(cdict->dictBuffer, customMem);
|
||||||
ZSTD_free(cdict, customMem);
|
|
||||||
ZSTD_free(cctx, customMem);
|
ZSTD_free(cctx, customMem);
|
||||||
|
ZSTD_free(cdict, customMem);
|
||||||
return NULL;
|
return NULL;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
cdict->dictContent = dictContent;
|
|
||||||
cdict->dictContentSize = dictSize;
|
|
||||||
cdict->refContext = cctx;
|
cdict->refContext = cctx;
|
||||||
|
cdict->dictContentSize = dictSize;
|
||||||
return cdict;
|
return cdict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2783,7 +2816,15 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL
|
|||||||
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
||||||
ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
|
ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
|
||||||
params.fParams.contentSizeFlag = 1;
|
params.fParams.contentSizeFlag = 1;
|
||||||
return ZSTD_createCDict_advanced(dict, dictSize, params, allocator);
|
return ZSTD_createCDict_advanced(dict, dictSize, 0, params, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
|
||||||
|
{
|
||||||
|
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
||||||
|
ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
|
||||||
|
params.fParams.contentSizeFlag = 1;
|
||||||
|
return ZSTD_createCDict_advanced(dict, dictSize, 1, params, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
||||||
@@ -2791,7 +2832,7 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
|||||||
if (cdict==NULL) return 0; /* support free on NULL */
|
if (cdict==NULL) return 0; /* support free on NULL */
|
||||||
{ ZSTD_customMem const cMem = cdict->refContext->customMem;
|
{ ZSTD_customMem const cMem = cdict->refContext->customMem;
|
||||||
ZSTD_freeCCtx(cdict->refContext);
|
ZSTD_freeCCtx(cdict->refContext);
|
||||||
ZSTD_free(cdict->dictContent, cMem);
|
ZSTD_free(cdict->dictBuffer, cMem);
|
||||||
ZSTD_free(cdict, cMem);
|
ZSTD_free(cdict, cMem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2801,7 +2842,7 @@ static ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
|
|||||||
return ZSTD_getParamsFromCCtx(cdict->refContext);
|
return ZSTD_getParamsFromCCtx(cdict->refContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, U64 pledgedSrcSize)
|
size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize)
|
||||||
{
|
{
|
||||||
if (cdict->dictContentSize) CHECK_F(ZSTD_copyCCtx(cctx, cdict->refContext, pledgedSrcSize))
|
if (cdict->dictContentSize) CHECK_F(ZSTD_copyCCtx(cctx, cdict->refContext, pledgedSrcSize))
|
||||||
else CHECK_F(ZSTD_compressBegin_advanced(cctx, NULL, 0, cdict->refContext->params, pledgedSrcSize));
|
else CHECK_F(ZSTD_compressBegin_advanced(cctx, NULL, 0, cdict->refContext->params, pledgedSrcSize));
|
||||||
@@ -2900,7 +2941,7 @@ size_t ZSTD_CStreamOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSO
|
|||||||
|
|
||||||
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
|
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
|
||||||
{
|
{
|
||||||
if (zcs->inBuffSize==0) return ERROR(stage_wrong); /* zcs has not been init at least once */
|
if (zcs->inBuffSize==0) return ERROR(stage_wrong); /* zcs has not been init at least once => can't reset */
|
||||||
|
|
||||||
if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict(zcs->cctx, zcs->cdict, pledgedSrcSize))
|
if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict(zcs->cctx, zcs->cdict, pledgedSrcSize))
|
||||||
else CHECK_F(ZSTD_compressBegin_advanced(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize));
|
else CHECK_F(ZSTD_compressBegin_advanced(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize));
|
||||||
@@ -2937,9 +2978,9 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
|||||||
if (zcs->outBuff == NULL) return ERROR(memory_allocation);
|
if (zcs->outBuff == NULL) return ERROR(memory_allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict) {
|
if (dict && dictSize >= 8) {
|
||||||
ZSTD_freeCDict(zcs->cdictLocal);
|
ZSTD_freeCDict(zcs->cdictLocal);
|
||||||
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, params, zcs->customMem);
|
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0, params, zcs->customMem);
|
||||||
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
||||||
zcs->cdict = zcs->cdictLocal;
|
zcs->cdict = zcs->cdictLocal;
|
||||||
} else zcs->cdict = NULL;
|
} else zcs->cdict = NULL;
|
||||||
@@ -2956,6 +2997,7 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
|
|||||||
ZSTD_parameters const params = ZSTD_getParamsFromCDict(cdict);
|
ZSTD_parameters const params = ZSTD_getParamsFromCDict(cdict);
|
||||||
size_t const initError = ZSTD_initCStream_advanced(zcs, NULL, 0, params, 0);
|
size_t const initError = ZSTD_initCStream_advanced(zcs, NULL, 0, params, 0);
|
||||||
zcs->cdict = cdict;
|
zcs->cdict = cdict;
|
||||||
|
zcs->cctx->dictID = params.fParams.noDictIDFlag ? 0 : cdict->refContext->dictID;
|
||||||
return initError;
|
return initError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2967,7 +3009,8 @@ size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t di
|
|||||||
|
|
||||||
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
|
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
|
||||||
{
|
{
|
||||||
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
|
ZSTD_parameters params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
|
||||||
|
if (pledgedSrcSize) params.fParams.contentSizeFlag = 1;
|
||||||
return ZSTD_initCStream_advanced(zcs, NULL, 0, params, pledgedSrcSize);
|
return ZSTD_initCStream_advanced(zcs, NULL, 0, params, pledgedSrcSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ MEM_STATIC void ZSTD_rescaleFreqs(seqStore_t* ssPtr, const BYTE* src, size_t src
|
|||||||
|
|
||||||
ssPtr->cachedLiterals = NULL;
|
ssPtr->cachedLiterals = NULL;
|
||||||
ssPtr->cachedPrice = ssPtr->cachedLitLength = 0;
|
ssPtr->cachedPrice = ssPtr->cachedLitLength = 0;
|
||||||
ssPtr->staticPrices = 0;
|
ssPtr->staticPrices = 0;
|
||||||
|
|
||||||
if (ssPtr->litLengthSum == 0) {
|
if (ssPtr->litLengthSum == 0) {
|
||||||
if (srcSize <= 1024) ssPtr->staticPrices = 1;
|
if (srcSize <= 1024) ssPtr->staticPrices = 1;
|
||||||
@@ -56,7 +56,7 @@ MEM_STATIC void ZSTD_rescaleFreqs(seqStore_t* ssPtr, const BYTE* src, size_t src
|
|||||||
|
|
||||||
for (u=0; u<=MaxLit; u++) {
|
for (u=0; u<=MaxLit; u++) {
|
||||||
ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u]>>ZSTD_FREQ_DIV);
|
ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u]>>ZSTD_FREQ_DIV);
|
||||||
ssPtr->litSum += ssPtr->litFreq[u];
|
ssPtr->litSum += ssPtr->litFreq[u];
|
||||||
}
|
}
|
||||||
for (u=0; u<=MaxLL; u++)
|
for (u=0; u<=MaxLL; u++)
|
||||||
ssPtr->litLengthFreq[u] = 1;
|
ssPtr->litLengthFreq[u] = 1;
|
||||||
@@ -634,7 +634,7 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
|
|||||||
} } /* for (cur=0; cur < last_pos; ) */
|
} } /* for (cur=0; cur < last_pos; ) */
|
||||||
|
|
||||||
/* Save reps for next block */
|
/* Save reps for next block */
|
||||||
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) ctx->savedRep[i] = rep[i]; }
|
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) ctx->repToConfirm[i] = rep[i]; }
|
||||||
|
|
||||||
/* Last Literals */
|
/* Last Literals */
|
||||||
{ size_t const lastLLSize = iend - anchor;
|
{ size_t const lastLLSize = iend - anchor;
|
||||||
@@ -825,7 +825,7 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
|
|||||||
|
|
||||||
match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
|
match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
|
||||||
|
|
||||||
if (match_num > 0 && matches[match_num-1].len > sufficient_len) {
|
if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
|
||||||
best_mlen = matches[match_num-1].len;
|
best_mlen = matches[match_num-1].len;
|
||||||
best_off = matches[match_num-1].off;
|
best_off = matches[match_num-1].off;
|
||||||
last_pos = cur + 1;
|
last_pos = cur + 1;
|
||||||
@@ -835,7 +835,7 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
|
|||||||
/* set prices using matches at position = cur */
|
/* set prices using matches at position = cur */
|
||||||
for (u = 0; u < match_num; u++) {
|
for (u = 0; u < match_num; u++) {
|
||||||
mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
|
mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
|
||||||
best_mlen = (cur + matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM - cur;
|
best_mlen = matches[u].len;
|
||||||
|
|
||||||
while (mlen <= best_mlen) {
|
while (mlen <= best_mlen) {
|
||||||
if (opt[cur].mlen == 1) {
|
if (opt[cur].mlen == 1) {
|
||||||
@@ -907,7 +907,7 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
|
|||||||
} } /* for (cur=0; cur < last_pos; ) */
|
} } /* for (cur=0; cur < last_pos; ) */
|
||||||
|
|
||||||
/* Save reps for next block */
|
/* Save reps for next block */
|
||||||
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) ctx->savedRep[i] = rep[i]; }
|
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) ctx->repToConfirm[i] = rep[i]; }
|
||||||
|
|
||||||
/* Last Literals */
|
/* Last Literals */
|
||||||
{ size_t lastLLSize = iend - anchor;
|
{ size_t lastLLSize = iend - anchor;
|
||||||
|
|||||||
@@ -0,0 +1,740 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* ====== Tuning parameters ====== */
|
||||||
|
#define ZSTDMT_NBTHREADS_MAX 128
|
||||||
|
|
||||||
|
|
||||||
|
/* ====== Compiler specifics ====== */
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ====== Dependencies ====== */
|
||||||
|
#include <stdlib.h> /* malloc */
|
||||||
|
#include <string.h> /* memcpy */
|
||||||
|
#include "pool.h" /* threadpool */
|
||||||
|
#include "threading.h" /* mutex */
|
||||||
|
#include "zstd_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
||||||
|
#include "zstdmt_compress.h"
|
||||||
|
#define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
||||||
|
#include "xxhash.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* ====== Debug ====== */
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <sys/times.h>
|
||||||
|
static unsigned g_debugLevel = 3;
|
||||||
|
# define DEBUGLOGRAW(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __VA_ARGS__); }
|
||||||
|
# define DEBUGLOG(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __FILE__ ": "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, " \n"); }
|
||||||
|
|
||||||
|
# define DEBUG_PRINTHEX(l,p,n) { \
|
||||||
|
unsigned debug_u; \
|
||||||
|
for (debug_u=0; debug_u<(n); debug_u++) \
|
||||||
|
DEBUGLOGRAW(l, "%02X ", ((const unsigned char*)(p))[debug_u]); \
|
||||||
|
DEBUGLOGRAW(l, " \n"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long long GetCurrentClockTimeMicroseconds()
|
||||||
|
{
|
||||||
|
static clock_t _ticksPerSecond = 0;
|
||||||
|
if (_ticksPerSecond <= 0) _ticksPerSecond = sysconf(_SC_CLK_TCK);
|
||||||
|
|
||||||
|
struct tms junk; clock_t newTicks = (clock_t) times(&junk);
|
||||||
|
return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MUTEX_WAIT_TIME_DLEVEL 5
|
||||||
|
#define PTHREAD_MUTEX_LOCK(mutex) \
|
||||||
|
if (g_debugLevel>=MUTEX_WAIT_TIME_DLEVEL) { \
|
||||||
|
unsigned long long beforeTime = GetCurrentClockTimeMicroseconds(); \
|
||||||
|
pthread_mutex_lock(mutex); \
|
||||||
|
unsigned long long afterTime = GetCurrentClockTimeMicroseconds(); \
|
||||||
|
unsigned long long elapsedTime = (afterTime-beforeTime); \
|
||||||
|
if (elapsedTime > 1000) { /* or whatever threshold you like; I'm using 1 millisecond here */ \
|
||||||
|
DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
|
||||||
|
elapsedTime, #mutex); \
|
||||||
|
} \
|
||||||
|
} else pthread_mutex_lock(mutex);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||||
|
# define PTHREAD_MUTEX_LOCK(m) pthread_mutex_lock(m)
|
||||||
|
# define DEBUG_PRINTHEX(l,p,n) {}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ===== Buffer Pool ===== */
|
||||||
|
|
||||||
|
typedef struct buffer_s {
|
||||||
|
void* start;
|
||||||
|
size_t size;
|
||||||
|
} buffer_t;
|
||||||
|
|
||||||
|
static const buffer_t g_nullBuffer = { NULL, 0 };
|
||||||
|
|
||||||
|
typedef struct ZSTDMT_bufferPool_s {
|
||||||
|
unsigned totalBuffers;
|
||||||
|
unsigned nbBuffers;
|
||||||
|
buffer_t bTable[1]; /* variable size */
|
||||||
|
} ZSTDMT_bufferPool;
|
||||||
|
|
||||||
|
static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbThreads)
|
||||||
|
{
|
||||||
|
unsigned const maxNbBuffers = 2*nbThreads + 2;
|
||||||
|
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)calloc(1, sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t));
|
||||||
|
if (bufPool==NULL) return NULL;
|
||||||
|
bufPool->totalBuffers = maxNbBuffers;
|
||||||
|
bufPool->nbBuffers = 0;
|
||||||
|
return bufPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
|
||||||
|
{
|
||||||
|
unsigned u;
|
||||||
|
if (!bufPool) return; /* compatibility with free on NULL */
|
||||||
|
for (u=0; u<bufPool->totalBuffers; u++)
|
||||||
|
free(bufPool->bTable[u].start);
|
||||||
|
free(bufPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assumption : invocation from main thread only ! */
|
||||||
|
static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* pool, size_t bSize)
|
||||||
|
{
|
||||||
|
if (pool->nbBuffers) { /* try to use an existing buffer */
|
||||||
|
buffer_t const buf = pool->bTable[--(pool->nbBuffers)];
|
||||||
|
size_t const availBufferSize = buf.size;
|
||||||
|
if ((availBufferSize >= bSize) & (availBufferSize <= 10*bSize)) /* large enough, but not too much */
|
||||||
|
return buf;
|
||||||
|
free(buf.start); /* size conditions not respected : scratch this buffer and create a new one */
|
||||||
|
}
|
||||||
|
/* create new buffer */
|
||||||
|
{ buffer_t buffer;
|
||||||
|
void* const start = malloc(bSize);
|
||||||
|
if (start==NULL) bSize = 0;
|
||||||
|
buffer.start = start; /* note : start can be NULL if malloc fails ! */
|
||||||
|
buffer.size = bSize;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store buffer for later re-use, up to pool capacity */
|
||||||
|
static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* pool, buffer_t buf)
|
||||||
|
{
|
||||||
|
if (buf.start == NULL) return; /* release on NULL */
|
||||||
|
if (pool->nbBuffers < pool->totalBuffers) {
|
||||||
|
pool->bTable[pool->nbBuffers++] = buf; /* store for later re-use */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Reached bufferPool capacity (should not happen) */
|
||||||
|
free(buf.start);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ===== CCtx Pool ===== */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned totalCCtx;
|
||||||
|
unsigned availCCtx;
|
||||||
|
ZSTD_CCtx* cctx[1]; /* variable size */
|
||||||
|
} ZSTDMT_CCtxPool;
|
||||||
|
|
||||||
|
/* assumption : CCtxPool invocation only from main thread */
|
||||||
|
|
||||||
|
/* note : all CCtx borrowed from the pool should be released back to the pool _before_ freeing the pool */
|
||||||
|
static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
|
||||||
|
{
|
||||||
|
unsigned u;
|
||||||
|
for (u=0; u<pool->totalCCtx; u++)
|
||||||
|
ZSTD_freeCCtx(pool->cctx[u]); /* note : compatible with free on NULL */
|
||||||
|
free(pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ZSTDMT_createCCtxPool() :
|
||||||
|
* implies nbThreads >= 1 , checked by caller ZSTDMT_createCCtx() */
|
||||||
|
static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbThreads)
|
||||||
|
{
|
||||||
|
ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) calloc(1, sizeof(ZSTDMT_CCtxPool) + (nbThreads-1)*sizeof(ZSTD_CCtx*));
|
||||||
|
if (!cctxPool) return NULL;
|
||||||
|
cctxPool->totalCCtx = nbThreads;
|
||||||
|
cctxPool->availCCtx = 1; /* at least one cctx for single-thread mode */
|
||||||
|
cctxPool->cctx[0] = ZSTD_createCCtx();
|
||||||
|
if (!cctxPool->cctx[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; }
|
||||||
|
DEBUGLOG(1, "cctxPool created, with %u threads", nbThreads);
|
||||||
|
return cctxPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* pool)
|
||||||
|
{
|
||||||
|
if (pool->availCCtx) {
|
||||||
|
pool->availCCtx--;
|
||||||
|
return pool->cctx[pool->availCCtx];
|
||||||
|
}
|
||||||
|
return ZSTD_createCCtx(); /* note : can be NULL, when creation fails ! */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)
|
||||||
|
{
|
||||||
|
if (cctx==NULL) return; /* compatibility with release on NULL */
|
||||||
|
if (pool->availCCtx < pool->totalCCtx)
|
||||||
|
pool->cctx[pool->availCCtx++] = cctx;
|
||||||
|
else
|
||||||
|
/* pool overflow : should not happen, since totalCCtx==nbThreads */
|
||||||
|
ZSTD_freeCCtx(cctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ===== Thread worker ===== */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
buffer_t buffer;
|
||||||
|
size_t filled;
|
||||||
|
} inBuff_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ZSTD_CCtx* cctx;
|
||||||
|
buffer_t src;
|
||||||
|
const void* srcStart;
|
||||||
|
size_t srcSize;
|
||||||
|
size_t dictSize;
|
||||||
|
buffer_t dstBuff;
|
||||||
|
size_t cSize;
|
||||||
|
size_t dstFlushed;
|
||||||
|
unsigned firstChunk;
|
||||||
|
unsigned lastChunk;
|
||||||
|
unsigned jobCompleted;
|
||||||
|
unsigned jobScanned;
|
||||||
|
pthread_mutex_t* jobCompleted_mutex;
|
||||||
|
pthread_cond_t* jobCompleted_cond;
|
||||||
|
ZSTD_parameters params;
|
||||||
|
ZSTD_CDict* cdict;
|
||||||
|
unsigned long long fullFrameSize;
|
||||||
|
} ZSTDMT_jobDescription;
|
||||||
|
|
||||||
|
/* ZSTDMT_compressChunk() : POOL_function type */
|
||||||
|
void ZSTDMT_compressChunk(void* jobDescription)
|
||||||
|
{
|
||||||
|
ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
|
||||||
|
const void* const src = (const char*)job->srcStart + job->dictSize;
|
||||||
|
buffer_t const dstBuff = job->dstBuff;
|
||||||
|
DEBUGLOG(3, "job (first:%u) (last:%u) : dictSize %u, srcSize %u", job->firstChunk, job->lastChunk, (U32)job->dictSize, (U32)job->srcSize);
|
||||||
|
if (job->cdict) {
|
||||||
|
size_t const initError = ZSTD_compressBegin_usingCDict(job->cctx, job->cdict, job->fullFrameSize);
|
||||||
|
if (job->cdict) DEBUGLOG(3, "using CDict ");
|
||||||
|
if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
|
||||||
|
} else {
|
||||||
|
size_t const initError = ZSTD_compressBegin_advanced(job->cctx, job->srcStart, job->dictSize, job->params, job->fullFrameSize);
|
||||||
|
if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
|
||||||
|
ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceWindow, 1);
|
||||||
|
}
|
||||||
|
if (!job->firstChunk) { /* flush frame header */
|
||||||
|
size_t const hSize = ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, src, 0);
|
||||||
|
if (ZSTD_isError(hSize)) { job->cSize = hSize; goto _endJob; }
|
||||||
|
ZSTD_invalidateRepCodes(job->cctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGLOG(4, "Compressing : ");
|
||||||
|
DEBUG_PRINTHEX(4, job->srcStart, 12);
|
||||||
|
job->cSize = (job->lastChunk) ? /* last chunk signal */
|
||||||
|
ZSTD_compressEnd (job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize) :
|
||||||
|
ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize);
|
||||||
|
DEBUGLOG(3, "compressed %u bytes into %u bytes (first:%u) (last:%u)", (unsigned)job->srcSize, (unsigned)job->cSize, job->firstChunk, job->lastChunk);
|
||||||
|
|
||||||
|
_endJob:
|
||||||
|
PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
|
||||||
|
job->jobCompleted = 1;
|
||||||
|
job->jobScanned = 0;
|
||||||
|
pthread_cond_signal(job->jobCompleted_cond);
|
||||||
|
pthread_mutex_unlock(job->jobCompleted_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------ */
|
||||||
|
/* ===== Multi-threaded compression ===== */
|
||||||
|
/* ------------------------------------------ */
|
||||||
|
|
||||||
|
struct ZSTDMT_CCtx_s {
|
||||||
|
POOL_ctx* factory;
|
||||||
|
ZSTDMT_bufferPool* buffPool;
|
||||||
|
ZSTDMT_CCtxPool* cctxPool;
|
||||||
|
pthread_mutex_t jobCompleted_mutex;
|
||||||
|
pthread_cond_t jobCompleted_cond;
|
||||||
|
size_t targetSectionSize;
|
||||||
|
size_t marginSize;
|
||||||
|
size_t inBuffSize;
|
||||||
|
size_t dictSize;
|
||||||
|
size_t targetDictSize;
|
||||||
|
inBuff_t inBuff;
|
||||||
|
ZSTD_parameters params;
|
||||||
|
XXH64_state_t xxhState;
|
||||||
|
unsigned nbThreads;
|
||||||
|
unsigned jobIDMask;
|
||||||
|
unsigned doneJobID;
|
||||||
|
unsigned nextJobID;
|
||||||
|
unsigned frameEnded;
|
||||||
|
unsigned allJobsCompleted;
|
||||||
|
unsigned overlapRLog;
|
||||||
|
unsigned long long frameContentSize;
|
||||||
|
size_t sectionSize;
|
||||||
|
ZSTD_CDict* cdict;
|
||||||
|
ZSTD_CStream* cstream;
|
||||||
|
ZSTDMT_jobDescription jobs[1]; /* variable size (must lies at the end) */
|
||||||
|
};
|
||||||
|
|
||||||
|
ZSTDMT_CCtx *ZSTDMT_createCCtx(unsigned nbThreads)
|
||||||
|
{
|
||||||
|
ZSTDMT_CCtx* cctx;
|
||||||
|
U32 const minNbJobs = nbThreads + 2;
|
||||||
|
U32 const nbJobsLog2 = ZSTD_highbit32(minNbJobs) + 1;
|
||||||
|
U32 const nbJobs = 1 << nbJobsLog2;
|
||||||
|
DEBUGLOG(5, "nbThreads : %u ; minNbJobs : %u ; nbJobsLog2 : %u ; nbJobs : %u \n",
|
||||||
|
nbThreads, minNbJobs, nbJobsLog2, nbJobs);
|
||||||
|
if ((nbThreads < 1) | (nbThreads > ZSTDMT_NBTHREADS_MAX)) return NULL;
|
||||||
|
cctx = (ZSTDMT_CCtx*) calloc(1, sizeof(ZSTDMT_CCtx) + nbJobs*sizeof(ZSTDMT_jobDescription));
|
||||||
|
if (!cctx) return NULL;
|
||||||
|
cctx->nbThreads = nbThreads;
|
||||||
|
cctx->jobIDMask = nbJobs - 1;
|
||||||
|
cctx->allJobsCompleted = 1;
|
||||||
|
cctx->sectionSize = 0;
|
||||||
|
cctx->overlapRLog = 3;
|
||||||
|
cctx->factory = POOL_create(nbThreads, 1);
|
||||||
|
cctx->buffPool = ZSTDMT_createBufferPool(nbThreads);
|
||||||
|
cctx->cctxPool = ZSTDMT_createCCtxPool(nbThreads);
|
||||||
|
if (!cctx->factory | !cctx->buffPool | !cctx->cctxPool) { /* one object was not created */
|
||||||
|
ZSTDMT_freeCCtx(cctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (nbThreads==1) {
|
||||||
|
cctx->cstream = ZSTD_createCStream();
|
||||||
|
if (!cctx->cstream) {
|
||||||
|
ZSTDMT_freeCCtx(cctx); return NULL;
|
||||||
|
} }
|
||||||
|
pthread_mutex_init(&cctx->jobCompleted_mutex, NULL); /* Todo : check init function return */
|
||||||
|
pthread_cond_init(&cctx->jobCompleted_cond, NULL);
|
||||||
|
DEBUGLOG(4, "mt_cctx created, for %u threads \n", nbThreads);
|
||||||
|
return cctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ZSTDMT_releaseAllJobResources() :
|
||||||
|
* Ensure all workers are killed first. */
|
||||||
|
static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
|
||||||
|
{
|
||||||
|
unsigned jobID;
|
||||||
|
for (jobID=0; jobID <= mtctx->jobIDMask; jobID++) {
|
||||||
|
ZSTDMT_releaseBuffer(mtctx->buffPool, mtctx->jobs[jobID].dstBuff);
|
||||||
|
mtctx->jobs[jobID].dstBuff = g_nullBuffer;
|
||||||
|
ZSTDMT_releaseBuffer(mtctx->buffPool, mtctx->jobs[jobID].src);
|
||||||
|
mtctx->jobs[jobID].src = g_nullBuffer;
|
||||||
|
ZSTDMT_releaseCCtx(mtctx->cctxPool, mtctx->jobs[jobID].cctx);
|
||||||
|
mtctx->jobs[jobID].cctx = NULL;
|
||||||
|
}
|
||||||
|
memset(mtctx->jobs, 0, (mtctx->jobIDMask+1)*sizeof(ZSTDMT_jobDescription));
|
||||||
|
ZSTDMT_releaseBuffer(mtctx->buffPool, mtctx->inBuff.buffer);
|
||||||
|
mtctx->inBuff.buffer = g_nullBuffer;
|
||||||
|
mtctx->allJobsCompleted = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
|
||||||
|
{
|
||||||
|
if (mtctx==NULL) return 0; /* compatible with free on NULL */
|
||||||
|
POOL_free(mtctx->factory);
|
||||||
|
if (!mtctx->allJobsCompleted) ZSTDMT_releaseAllJobResources(mtctx); /* stop workers first */
|
||||||
|
ZSTDMT_freeBufferPool(mtctx->buffPool); /* release job resources into pools first */
|
||||||
|
ZSTDMT_freeCCtxPool(mtctx->cctxPool);
|
||||||
|
ZSTD_freeCDict(mtctx->cdict);
|
||||||
|
ZSTD_freeCStream(mtctx->cstream);
|
||||||
|
pthread_mutex_destroy(&mtctx->jobCompleted_mutex);
|
||||||
|
pthread_cond_destroy(&mtctx->jobCompleted_cond);
|
||||||
|
free(mtctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSDTMT_parameter parameter, unsigned value)
|
||||||
|
{
|
||||||
|
switch(parameter)
|
||||||
|
{
|
||||||
|
case ZSTDMT_p_sectionSize :
|
||||||
|
mtctx->sectionSize = value;
|
||||||
|
return 0;
|
||||||
|
case ZSTDMT_p_overlapSectionLog :
|
||||||
|
DEBUGLOG(4, "ZSTDMT_p_overlapSectionLog : %u", value);
|
||||||
|
mtctx->overlapRLog = (value >= 9) ? 0 : 9 - value;
|
||||||
|
return 0;
|
||||||
|
default :
|
||||||
|
return ERROR(compressionParameter_unsupported);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------ */
|
||||||
|
/* ===== Multi-threaded compression ===== */
|
||||||
|
/* ------------------------------------------ */
|
||||||
|
|
||||||
|
size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||||
|
void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
int compressionLevel)
|
||||||
|
{
|
||||||
|
ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, 0);
|
||||||
|
size_t const chunkTargetSize = (size_t)1 << (params.cParams.windowLog + 2);
|
||||||
|
unsigned const nbChunksMax = (unsigned)(srcSize / chunkTargetSize) + (srcSize < chunkTargetSize) /* min 1 */;
|
||||||
|
unsigned nbChunks = MIN(nbChunksMax, mtctx->nbThreads);
|
||||||
|
size_t const proposedChunkSize = (srcSize + (nbChunks-1)) / nbChunks;
|
||||||
|
size_t const avgChunkSize = ((proposedChunkSize & 0x1FFFF) < 0xFFFF) ? proposedChunkSize + 0xFFFF : proposedChunkSize; /* avoid too small last block */
|
||||||
|
size_t remainingSrcSize = srcSize;
|
||||||
|
const char* const srcStart = (const char*)src;
|
||||||
|
size_t frameStartPos = 0;
|
||||||
|
|
||||||
|
DEBUGLOG(3, "windowLog : %2u => chunkTargetSize : %u bytes ", params.cParams.windowLog, (U32)chunkTargetSize);
|
||||||
|
DEBUGLOG(2, "nbChunks : %2u (chunkSize : %u bytes) ", nbChunks, (U32)avgChunkSize);
|
||||||
|
params.fParams.contentSizeFlag = 1;
|
||||||
|
|
||||||
|
if (nbChunks==1) { /* fallback to single-thread mode */
|
||||||
|
ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0];
|
||||||
|
return ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ unsigned u;
|
||||||
|
for (u=0; u<nbChunks; u++) {
|
||||||
|
size_t const chunkSize = MIN(remainingSrcSize, avgChunkSize);
|
||||||
|
size_t const dstBufferCapacity = u ? ZSTD_compressBound(chunkSize) : dstCapacity;
|
||||||
|
buffer_t const dstAsBuffer = { dst, dstCapacity };
|
||||||
|
buffer_t const dstBuffer = u ? ZSTDMT_getBuffer(mtctx->buffPool, dstBufferCapacity) : dstAsBuffer;
|
||||||
|
ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(mtctx->cctxPool);
|
||||||
|
|
||||||
|
if ((cctx==NULL) || (dstBuffer.start==NULL)) {
|
||||||
|
mtctx->jobs[u].cSize = ERROR(memory_allocation); /* job result */
|
||||||
|
mtctx->jobs[u].jobCompleted = 1;
|
||||||
|
nbChunks = u+1;
|
||||||
|
break; /* let's wait for previous jobs to complete, but don't start new ones */
|
||||||
|
}
|
||||||
|
|
||||||
|
mtctx->jobs[u].srcStart = srcStart + frameStartPos;
|
||||||
|
mtctx->jobs[u].srcSize = chunkSize;
|
||||||
|
mtctx->jobs[u].fullFrameSize = srcSize;
|
||||||
|
mtctx->jobs[u].params = params;
|
||||||
|
mtctx->jobs[u].dstBuff = dstBuffer;
|
||||||
|
mtctx->jobs[u].cctx = cctx;
|
||||||
|
mtctx->jobs[u].firstChunk = (u==0);
|
||||||
|
mtctx->jobs[u].lastChunk = (u==nbChunks-1);
|
||||||
|
mtctx->jobs[u].jobCompleted = 0;
|
||||||
|
mtctx->jobs[u].jobCompleted_mutex = &mtctx->jobCompleted_mutex;
|
||||||
|
mtctx->jobs[u].jobCompleted_cond = &mtctx->jobCompleted_cond;
|
||||||
|
|
||||||
|
DEBUGLOG(3, "posting job %u (%u bytes)", u, (U32)chunkSize);
|
||||||
|
DEBUG_PRINTHEX(3, mtctx->jobs[u].srcStart, 12);
|
||||||
|
POOL_add(mtctx->factory, ZSTDMT_compressChunk, &mtctx->jobs[u]);
|
||||||
|
|
||||||
|
frameStartPos += chunkSize;
|
||||||
|
remainingSrcSize -= chunkSize;
|
||||||
|
} }
|
||||||
|
/* note : since nbChunks <= nbThreads, all jobs should be running immediately in parallel */
|
||||||
|
|
||||||
|
{ unsigned chunkID;
|
||||||
|
size_t error = 0, dstPos = 0;
|
||||||
|
for (chunkID=0; chunkID<nbChunks; chunkID++) {
|
||||||
|
DEBUGLOG(3, "waiting for chunk %u ", chunkID);
|
||||||
|
PTHREAD_MUTEX_LOCK(&mtctx->jobCompleted_mutex);
|
||||||
|
while (mtctx->jobs[chunkID].jobCompleted==0) {
|
||||||
|
DEBUGLOG(4, "waiting for jobCompleted signal from chunk %u", chunkID);
|
||||||
|
pthread_cond_wait(&mtctx->jobCompleted_cond, &mtctx->jobCompleted_mutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mtctx->jobCompleted_mutex);
|
||||||
|
DEBUGLOG(3, "ready to write chunk %u ", chunkID);
|
||||||
|
|
||||||
|
ZSTDMT_releaseCCtx(mtctx->cctxPool, mtctx->jobs[chunkID].cctx);
|
||||||
|
mtctx->jobs[chunkID].cctx = NULL;
|
||||||
|
mtctx->jobs[chunkID].srcStart = NULL;
|
||||||
|
{ size_t const cSize = mtctx->jobs[chunkID].cSize;
|
||||||
|
if (ZSTD_isError(cSize)) error = cSize;
|
||||||
|
if ((!error) && (dstPos + cSize > dstCapacity)) error = ERROR(dstSize_tooSmall);
|
||||||
|
if (chunkID) { /* note : chunk 0 is already written directly into dst */
|
||||||
|
if (!error) memcpy((char*)dst + dstPos, mtctx->jobs[chunkID].dstBuff.start, cSize);
|
||||||
|
ZSTDMT_releaseBuffer(mtctx->buffPool, mtctx->jobs[chunkID].dstBuff);
|
||||||
|
mtctx->jobs[chunkID].dstBuff = g_nullBuffer;
|
||||||
|
}
|
||||||
|
dstPos += cSize ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!error) DEBUGLOG(3, "compressed size : %u ", (U32)dstPos);
|
||||||
|
return error ? error : dstPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ====================================== */
|
||||||
|
/* ======= Streaming API ======= */
|
||||||
|
/* ====================================== */
|
||||||
|
|
||||||
|
static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* zcs) {
|
||||||
|
while (zcs->doneJobID < zcs->nextJobID) {
|
||||||
|
unsigned const jobID = zcs->doneJobID & zcs->jobIDMask;
|
||||||
|
PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
|
||||||
|
while (zcs->jobs[jobID].jobCompleted==0) {
|
||||||
|
DEBUGLOG(4, "waiting for jobCompleted signal from chunk %u", zcs->doneJobID); /* we want to block when waiting for data to flush */
|
||||||
|
pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&zcs->jobCompleted_mutex);
|
||||||
|
zcs->doneJobID++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
|
||||||
|
const void* dict, size_t dictSize, unsigned updateDict,
|
||||||
|
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||||
|
{
|
||||||
|
ZSTD_customMem const cmem = { NULL, NULL, NULL };
|
||||||
|
DEBUGLOG(3, "Started new compression, with windowLog : %u", params.cParams.windowLog);
|
||||||
|
if (zcs->nbThreads==1) return ZSTD_initCStream_advanced(zcs->cstream, dict, dictSize, params, pledgedSrcSize);
|
||||||
|
if (zcs->allJobsCompleted == 0) { /* previous job not correctly finished */
|
||||||
|
ZSTDMT_waitForAllJobsCompleted(zcs);
|
||||||
|
ZSTDMT_releaseAllJobResources(zcs);
|
||||||
|
zcs->allJobsCompleted = 1;
|
||||||
|
}
|
||||||
|
zcs->params = params;
|
||||||
|
if (updateDict) {
|
||||||
|
ZSTD_freeCDict(zcs->cdict); zcs->cdict = NULL;
|
||||||
|
if (dict && dictSize) {
|
||||||
|
zcs->cdict = ZSTD_createCDict_advanced(dict, dictSize, 0, params, cmem);
|
||||||
|
if (zcs->cdict == NULL) return ERROR(memory_allocation);
|
||||||
|
} }
|
||||||
|
zcs->frameContentSize = pledgedSrcSize;
|
||||||
|
zcs->targetDictSize = (zcs->overlapRLog>=9) ? 0 : (size_t)1 << (zcs->params.cParams.windowLog - zcs->overlapRLog);
|
||||||
|
DEBUGLOG(4, "overlapRLog : %u ", zcs->overlapRLog);
|
||||||
|
DEBUGLOG(3, "overlap Size : %u KB", (U32)(zcs->targetDictSize>>10));
|
||||||
|
zcs->targetSectionSize = zcs->sectionSize ? zcs->sectionSize : (size_t)1 << (zcs->params.cParams.windowLog + 2);
|
||||||
|
zcs->targetSectionSize = MAX(ZSTDMT_SECTION_SIZE_MIN, zcs->targetSectionSize);
|
||||||
|
zcs->targetSectionSize = MAX(zcs->targetDictSize, zcs->targetSectionSize);
|
||||||
|
DEBUGLOG(3, "Section Size : %u KB", (U32)(zcs->targetSectionSize>>10));
|
||||||
|
zcs->marginSize = zcs->targetSectionSize >> 2;
|
||||||
|
zcs->inBuffSize = zcs->targetDictSize + zcs->targetSectionSize + zcs->marginSize;
|
||||||
|
zcs->inBuff.buffer = ZSTDMT_getBuffer(zcs->buffPool, zcs->inBuffSize);
|
||||||
|
if (zcs->inBuff.buffer.start == NULL) return ERROR(memory_allocation);
|
||||||
|
zcs->inBuff.filled = 0;
|
||||||
|
zcs->dictSize = 0;
|
||||||
|
zcs->doneJobID = 0;
|
||||||
|
zcs->nextJobID = 0;
|
||||||
|
zcs->frameEnded = 0;
|
||||||
|
zcs->allJobsCompleted = 0;
|
||||||
|
if (params.fParams.checksumFlag) XXH64_reset(&zcs->xxhState, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* zcs,
|
||||||
|
const void* dict, size_t dictSize,
|
||||||
|
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||||
|
{
|
||||||
|
return ZSTDMT_initCStream_internal(zcs, dict, dictSize, 1, params, pledgedSrcSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ZSTDMT_resetCStream() :
|
||||||
|
* pledgedSrcSize is optional and can be zero == unknown */
|
||||||
|
size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* zcs, unsigned long long pledgedSrcSize)
|
||||||
|
{
|
||||||
|
if (zcs->nbThreads==1) return ZSTD_resetCStream(zcs->cstream, pledgedSrcSize);
|
||||||
|
return ZSTDMT_initCStream_internal(zcs, NULL, 0, 0, zcs->params, pledgedSrcSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZSTDMT_initCStream(ZSTDMT_CCtx* zcs, int compressionLevel) {
|
||||||
|
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
|
||||||
|
return ZSTDMT_initCStream_internal(zcs, NULL, 0, 1, params, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* zcs, size_t srcSize, unsigned endFrame)
|
||||||
|
{
|
||||||
|
size_t const dstBufferCapacity = ZSTD_compressBound(srcSize);
|
||||||
|
buffer_t const dstBuffer = ZSTDMT_getBuffer(zcs->buffPool, dstBufferCapacity);
|
||||||
|
ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(zcs->cctxPool);
|
||||||
|
unsigned const jobID = zcs->nextJobID & zcs->jobIDMask;
|
||||||
|
|
||||||
|
if ((cctx==NULL) || (dstBuffer.start==NULL)) {
|
||||||
|
zcs->jobs[jobID].jobCompleted = 1;
|
||||||
|
zcs->nextJobID++;
|
||||||
|
ZSTDMT_waitForAllJobsCompleted(zcs);
|
||||||
|
ZSTDMT_releaseAllJobResources(zcs);
|
||||||
|
return ERROR(memory_allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGLOG(4, "preparing job %u to compress %u bytes with %u preload ", zcs->nextJobID, (U32)srcSize, (U32)zcs->dictSize);
|
||||||
|
zcs->jobs[jobID].src = zcs->inBuff.buffer;
|
||||||
|
zcs->jobs[jobID].srcStart = zcs->inBuff.buffer.start;
|
||||||
|
zcs->jobs[jobID].srcSize = srcSize;
|
||||||
|
zcs->jobs[jobID].dictSize = zcs->dictSize; /* note : zcs->inBuff.filled is presumed >= srcSize + dictSize */
|
||||||
|
zcs->jobs[jobID].params = zcs->params;
|
||||||
|
if (zcs->nextJobID) zcs->jobs[jobID].params.fParams.checksumFlag = 0; /* do not calculate checksum within sections, just keep it in header for first section */
|
||||||
|
zcs->jobs[jobID].cdict = zcs->nextJobID==0 ? zcs->cdict : NULL;
|
||||||
|
zcs->jobs[jobID].fullFrameSize = zcs->frameContentSize;
|
||||||
|
zcs->jobs[jobID].dstBuff = dstBuffer;
|
||||||
|
zcs->jobs[jobID].cctx = cctx;
|
||||||
|
zcs->jobs[jobID].firstChunk = (zcs->nextJobID==0);
|
||||||
|
zcs->jobs[jobID].lastChunk = endFrame;
|
||||||
|
zcs->jobs[jobID].jobCompleted = 0;
|
||||||
|
zcs->jobs[jobID].dstFlushed = 0;
|
||||||
|
zcs->jobs[jobID].jobCompleted_mutex = &zcs->jobCompleted_mutex;
|
||||||
|
zcs->jobs[jobID].jobCompleted_cond = &zcs->jobCompleted_cond;
|
||||||
|
|
||||||
|
/* get a new buffer for next input */
|
||||||
|
if (!endFrame) {
|
||||||
|
size_t const newDictSize = MIN(srcSize + zcs->dictSize, zcs->targetDictSize);
|
||||||
|
zcs->inBuff.buffer = ZSTDMT_getBuffer(zcs->buffPool, zcs->inBuffSize);
|
||||||
|
if (zcs->inBuff.buffer.start == NULL) { /* not enough memory to allocate next input buffer */
|
||||||
|
zcs->jobs[jobID].jobCompleted = 1;
|
||||||
|
zcs->nextJobID++;
|
||||||
|
ZSTDMT_waitForAllJobsCompleted(zcs);
|
||||||
|
ZSTDMT_releaseAllJobResources(zcs);
|
||||||
|
return ERROR(memory_allocation);
|
||||||
|
}
|
||||||
|
DEBUGLOG(5, "inBuff filled to %u", (U32)zcs->inBuff.filled);
|
||||||
|
zcs->inBuff.filled -= srcSize + zcs->dictSize - newDictSize;
|
||||||
|
DEBUGLOG(5, "new job : filled to %u, with %u dict and %u src", (U32)zcs->inBuff.filled, (U32)newDictSize, (U32)(zcs->inBuff.filled - newDictSize));
|
||||||
|
memmove(zcs->inBuff.buffer.start, (const char*)zcs->jobs[jobID].srcStart + zcs->dictSize + srcSize - newDictSize, zcs->inBuff.filled);
|
||||||
|
DEBUGLOG(5, "new inBuff pre-filled");
|
||||||
|
zcs->dictSize = newDictSize;
|
||||||
|
} else {
|
||||||
|
zcs->inBuff.buffer = g_nullBuffer;
|
||||||
|
zcs->inBuff.filled = 0;
|
||||||
|
zcs->dictSize = 0;
|
||||||
|
zcs->frameEnded = 1;
|
||||||
|
if (zcs->nextJobID == 0)
|
||||||
|
zcs->params.fParams.checksumFlag = 0; /* single chunk : checksum is calculated directly within worker thread */
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGLOG(3, "posting job %u : %u bytes (end:%u) (note : doneJob = %u=>%u)", zcs->nextJobID, (U32)zcs->jobs[jobID].srcSize, zcs->jobs[jobID].lastChunk, zcs->doneJobID, zcs->doneJobID & zcs->jobIDMask);
|
||||||
|
POOL_add(zcs->factory, ZSTDMT_compressChunk, &zcs->jobs[jobID]); /* this call is blocking when thread worker pool is exhausted */
|
||||||
|
zcs->nextJobID++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ZSTDMT_flushNextJob() :
|
||||||
|
* output : will be updated with amount of data flushed .
|
||||||
|
* blockToFlush : if >0, the function will block and wait if there is no data available to flush .
|
||||||
|
* @return : amount of data remaining within internal buffer, 1 if unknown but > 0, 0 if no more, or an error code */
|
||||||
|
static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsigned blockToFlush)
|
||||||
|
{
|
||||||
|
unsigned const wJobID = zcs->doneJobID & zcs->jobIDMask;
|
||||||
|
if (zcs->doneJobID == zcs->nextJobID) return 0; /* all flushed ! */
|
||||||
|
PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
|
||||||
|
while (zcs->jobs[wJobID].jobCompleted==0) {
|
||||||
|
DEBUGLOG(5, "waiting for jobCompleted signal from job %u", zcs->doneJobID);
|
||||||
|
if (!blockToFlush) { pthread_mutex_unlock(&zcs->jobCompleted_mutex); return 0; } /* nothing ready to be flushed => skip */
|
||||||
|
pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex); /* block when nothing available to flush */
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&zcs->jobCompleted_mutex);
|
||||||
|
/* compression job completed : output can be flushed */
|
||||||
|
{ ZSTDMT_jobDescription job = zcs->jobs[wJobID];
|
||||||
|
if (!job.jobScanned) {
|
||||||
|
if (ZSTD_isError(job.cSize)) {
|
||||||
|
DEBUGLOG(5, "compression error detected ");
|
||||||
|
ZSTDMT_waitForAllJobsCompleted(zcs);
|
||||||
|
ZSTDMT_releaseAllJobResources(zcs);
|
||||||
|
return job.cSize;
|
||||||
|
}
|
||||||
|
ZSTDMT_releaseCCtx(zcs->cctxPool, job.cctx);
|
||||||
|
zcs->jobs[wJobID].cctx = NULL;
|
||||||
|
DEBUGLOG(5, "zcs->params.fParams.checksumFlag : %u ", zcs->params.fParams.checksumFlag);
|
||||||
|
if (zcs->params.fParams.checksumFlag) {
|
||||||
|
XXH64_update(&zcs->xxhState, (const char*)job.srcStart + job.dictSize, job.srcSize);
|
||||||
|
if (zcs->frameEnded && (zcs->doneJobID+1 == zcs->nextJobID)) { /* write checksum at end of last section */
|
||||||
|
U32 const checksum = (U32)XXH64_digest(&zcs->xxhState);
|
||||||
|
DEBUGLOG(4, "writing checksum : %08X \n", checksum);
|
||||||
|
MEM_writeLE32((char*)job.dstBuff.start + job.cSize, checksum);
|
||||||
|
job.cSize += 4;
|
||||||
|
zcs->jobs[wJobID].cSize += 4;
|
||||||
|
} }
|
||||||
|
ZSTDMT_releaseBuffer(zcs->buffPool, job.src);
|
||||||
|
zcs->jobs[wJobID].srcStart = NULL;
|
||||||
|
zcs->jobs[wJobID].src = g_nullBuffer;
|
||||||
|
zcs->jobs[wJobID].jobScanned = 1;
|
||||||
|
}
|
||||||
|
{ size_t const toWrite = MIN(job.cSize - job.dstFlushed, output->size - output->pos);
|
||||||
|
DEBUGLOG(4, "Flushing %u bytes from job %u ", (U32)toWrite, zcs->doneJobID);
|
||||||
|
memcpy((char*)output->dst + output->pos, (const char*)job.dstBuff.start + job.dstFlushed, toWrite);
|
||||||
|
output->pos += toWrite;
|
||||||
|
job.dstFlushed += toWrite;
|
||||||
|
}
|
||||||
|
if (job.dstFlushed == job.cSize) { /* output buffer fully flushed => move to next one */
|
||||||
|
ZSTDMT_releaseBuffer(zcs->buffPool, job.dstBuff);
|
||||||
|
zcs->jobs[wJobID].dstBuff = g_nullBuffer;
|
||||||
|
zcs->jobs[wJobID].jobCompleted = 0;
|
||||||
|
zcs->doneJobID++;
|
||||||
|
} else {
|
||||||
|
zcs->jobs[wJobID].dstFlushed = job.dstFlushed;
|
||||||
|
}
|
||||||
|
/* return value : how many bytes left in buffer ; fake it to 1 if unknown but >0 */
|
||||||
|
if (job.cSize > job.dstFlushed) return (job.cSize - job.dstFlushed);
|
||||||
|
if (zcs->doneJobID < zcs->nextJobID) return 1; /* still some buffer to flush */
|
||||||
|
zcs->allJobsCompleted = zcs->frameEnded; /* frame completed and entirely flushed */
|
||||||
|
return 0; /* everything flushed */
|
||||||
|
} }
|
||||||
|
|
||||||
|
|
||||||
|
size_t ZSTDMT_compressStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
||||||
|
{
|
||||||
|
size_t const newJobThreshold = zcs->dictSize + zcs->targetSectionSize + zcs->marginSize;
|
||||||
|
if (zcs->frameEnded) return ERROR(stage_wrong); /* current frame being ended. Only flush is allowed. Restart with init */
|
||||||
|
if (zcs->nbThreads==1) return ZSTD_compressStream(zcs->cstream, output, input);
|
||||||
|
|
||||||
|
/* fill input buffer */
|
||||||
|
{ size_t const toLoad = MIN(input->size - input->pos, zcs->inBuffSize - zcs->inBuff.filled);
|
||||||
|
memcpy((char*)zcs->inBuff.buffer.start + zcs->inBuff.filled, input->src, toLoad);
|
||||||
|
input->pos += toLoad;
|
||||||
|
zcs->inBuff.filled += toLoad;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (zcs->inBuff.filled >= newJobThreshold) /* filled enough : let's compress */
|
||||||
|
&& (zcs->nextJobID <= zcs->doneJobID + zcs->jobIDMask) ) { /* avoid overwriting job round buffer */
|
||||||
|
CHECK_F( ZSTDMT_createCompressionJob(zcs, zcs->targetSectionSize, 0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for data to flush */
|
||||||
|
CHECK_F( ZSTDMT_flushNextJob(zcs, output, (zcs->inBuff.filled == zcs->inBuffSize)) ); /* block if it wasn't possible to create new job due to saturation */
|
||||||
|
|
||||||
|
/* recommended next input size : fill current input buffer */
|
||||||
|
return zcs->inBuffSize - zcs->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsigned endFrame)
|
||||||
|
{
|
||||||
|
size_t const srcSize = zcs->inBuff.filled - zcs->dictSize;
|
||||||
|
|
||||||
|
if (srcSize) DEBUGLOG(4, "flushing : %u bytes left to compress", (U32)srcSize);
|
||||||
|
if ( ((srcSize > 0) || (endFrame && !zcs->frameEnded))
|
||||||
|
&& (zcs->nextJobID <= zcs->doneJobID + zcs->jobIDMask) ) {
|
||||||
|
CHECK_F( ZSTDMT_createCompressionJob(zcs, srcSize, endFrame) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if there is any data available to flush */
|
||||||
|
DEBUGLOG(5, "zcs->doneJobID : %u ; zcs->nextJobID : %u ", zcs->doneJobID, zcs->nextJobID);
|
||||||
|
return ZSTDMT_flushNextJob(zcs, output, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t ZSTDMT_flushStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
|
||||||
|
{
|
||||||
|
if (zcs->nbThreads==1) return ZSTD_flushStream(zcs->cstream, output);
|
||||||
|
return ZSTDMT_flushStream_internal(zcs, output, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZSTDMT_endStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
|
||||||
|
{
|
||||||
|
if (zcs->nbThreads==1) return ZSTD_endStream(zcs->cstream, output);
|
||||||
|
return ZSTDMT_flushStream_internal(zcs, output, 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZSTDMT_COMPRESS_H
|
||||||
|
#define ZSTDMT_COMPRESS_H
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Note : All prototypes defined in this file shall be considered experimental.
|
||||||
|
* There is no guarantee of API continuity (yet) on any of these prototypes */
|
||||||
|
|
||||||
|
/* === Dependencies === */
|
||||||
|
#include <stddef.h> /* size_t */
|
||||||
|
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */
|
||||||
|
#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
|
||||||
|
|
||||||
|
|
||||||
|
/* === Simple one-pass functions === */
|
||||||
|
|
||||||
|
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
|
||||||
|
ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbThreads);
|
||||||
|
ZSTDLIB_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* cctx);
|
||||||
|
|
||||||
|
ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* cctx,
|
||||||
|
void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
int compressionLevel);
|
||||||
|
|
||||||
|
|
||||||
|
/* === Streaming functions === */
|
||||||
|
|
||||||
|
ZSTDLIB_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
|
||||||
|
ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be zero == unknown */
|
||||||
|
|
||||||
|
ZSTDLIB_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
||||||
|
|
||||||
|
ZSTDLIB_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
||||||
|
ZSTDLIB_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
||||||
|
|
||||||
|
|
||||||
|
/* === Advanced functions and parameters === */
|
||||||
|
|
||||||
|
#ifndef ZSTDMT_SECTION_SIZE_MIN
|
||||||
|
# define ZSTDMT_SECTION_SIZE_MIN (1U << 20) /* 1 MB - Minimum size of each compression job */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ZSTDLIB_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx, const void* dict, size_t dictSize, /**< dict can be released after init, a local copy is preserved within zcs */
|
||||||
|
ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be zero == unknown */
|
||||||
|
|
||||||
|
/* ZSDTMT_parameter :
|
||||||
|
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
|
||||||
|
typedef enum {
|
||||||
|
ZSTDMT_p_sectionSize, /* size of input "section". Each section is compressed in parallel. 0 means default, which is dynamically determined within compression functions */
|
||||||
|
ZSTDMT_p_overlapSectionLog /* Log of overlapped section; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window */
|
||||||
|
} ZSDTMT_parameter;
|
||||||
|
|
||||||
|
/* ZSTDMT_setMTCtxParameter() :
|
||||||
|
* allow setting individual parameters, one at a time, among a list of enums defined in ZSTDMT_parameter.
|
||||||
|
* The function must be called typically after ZSTD_createCCtx().
|
||||||
|
* Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
|
||||||
|
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
||||||
|
ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSDTMT_parameter parameter, unsigned value);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZSTDMT_COMPRESS_H */
|
||||||
@@ -1444,7 +1444,7 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
|||||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
|
||||||
if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, dict, dictSize);
|
if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, dict, dictSize);
|
||||||
#endif
|
#endif
|
||||||
ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
|
CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
||||||
ZSTD_checkContinuity(dctx, dst);
|
ZSTD_checkContinuity(dctx, dst);
|
||||||
return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
|
return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
|
||||||
}
|
}
|
||||||
@@ -1671,9 +1671,9 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
||||||
dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
|
dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
|
||||||
dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
|
dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
|
||||||
dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
|
dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
|
||||||
dictPtr += 12;
|
dictPtr += 12;
|
||||||
|
|
||||||
dctx->litEntropy = dctx->fseEntropy = 1;
|
dctx->litEntropy = dctx->fseEntropy = 1;
|
||||||
@@ -1713,39 +1713,44 @@ size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t
|
|||||||
/* ====== ZSTD_DDict ====== */
|
/* ====== ZSTD_DDict ====== */
|
||||||
|
|
||||||
struct ZSTD_DDict_s {
|
struct ZSTD_DDict_s {
|
||||||
void* dict;
|
void* dictBuffer;
|
||||||
|
const void* dictContent;
|
||||||
size_t dictSize;
|
size_t dictSize;
|
||||||
ZSTD_DCtx* refContext;
|
ZSTD_DCtx* refContext;
|
||||||
}; /* typedef'd to ZSTD_DDict within "zstd.h" */
|
}; /* typedef'd to ZSTD_DDict within "zstd.h" */
|
||||||
|
|
||||||
ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_customMem customMem)
|
ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
|
||||||
{
|
{
|
||||||
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
||||||
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
||||||
|
|
||||||
{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
|
{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
|
||||||
void* const dictContent = ZSTD_malloc(dictSize, customMem);
|
|
||||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(customMem);
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(customMem);
|
||||||
|
|
||||||
if (!dictContent || !ddict || !dctx) {
|
if (!ddict || !dctx) {
|
||||||
ZSTD_free(dictContent, customMem);
|
|
||||||
ZSTD_free(ddict, customMem);
|
ZSTD_free(ddict, customMem);
|
||||||
ZSTD_free(dctx, customMem);
|
ZSTD_free(dctx, customMem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dictSize) {
|
if ((byReference) || (!dict) || (!dictSize)) {
|
||||||
memcpy(dictContent, dict, dictSize);
|
ddict->dictBuffer = NULL;
|
||||||
|
ddict->dictContent = dict;
|
||||||
|
} else {
|
||||||
|
void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
|
||||||
|
if (!internalBuffer) { ZSTD_free(dctx, customMem); ZSTD_free(ddict, customMem); return NULL; }
|
||||||
|
memcpy(internalBuffer, dict, dictSize);
|
||||||
|
ddict->dictBuffer = internalBuffer;
|
||||||
|
ddict->dictContent = internalBuffer;
|
||||||
}
|
}
|
||||||
{ size_t const errorCode = ZSTD_decompressBegin_usingDict(dctx, dictContent, dictSize);
|
{ size_t const errorCode = ZSTD_decompressBegin_usingDict(dctx, ddict->dictContent, dictSize);
|
||||||
if (ZSTD_isError(errorCode)) {
|
if (ZSTD_isError(errorCode)) {
|
||||||
ZSTD_free(dictContent, customMem);
|
ZSTD_free(ddict->dictBuffer, customMem);
|
||||||
ZSTD_free(ddict, customMem);
|
ZSTD_free(ddict, customMem);
|
||||||
ZSTD_free(dctx, customMem);
|
ZSTD_free(dctx, customMem);
|
||||||
return NULL;
|
return NULL;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
ddict->dict = dictContent;
|
|
||||||
ddict->dictSize = dictSize;
|
ddict->dictSize = dictSize;
|
||||||
ddict->refContext = dctx;
|
ddict->refContext = dctx;
|
||||||
return ddict;
|
return ddict;
|
||||||
@@ -1758,15 +1763,27 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_cu
|
|||||||
ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
||||||
{
|
{
|
||||||
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
||||||
return ZSTD_createDDict_advanced(dict, dictSize, allocator);
|
return ZSTD_createDDict_advanced(dict, dictSize, 0, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ZSTD_createDDict_byReference() :
|
||||||
|
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||||
|
* Dictionary content is simply referenced, and therefore stays in dictBuffer.
|
||||||
|
* It is important that dictBuffer outlives DDict, it must remain read accessible throughout the lifetime of DDict */
|
||||||
|
ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
|
||||||
|
{
|
||||||
|
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
||||||
|
return ZSTD_createDDict_advanced(dictBuffer, dictSize, 1, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
||||||
{
|
{
|
||||||
if (ddict==NULL) return 0; /* support free on NULL */
|
if (ddict==NULL) return 0; /* support free on NULL */
|
||||||
{ ZSTD_customMem const cMem = ddict->refContext->customMem;
|
{ ZSTD_customMem const cMem = ddict->refContext->customMem;
|
||||||
ZSTD_freeDCtx(ddict->refContext);
|
ZSTD_freeDCtx(ddict->refContext);
|
||||||
ZSTD_free(ddict->dict, cMem);
|
ZSTD_free(ddict->dictBuffer, cMem);
|
||||||
ZSTD_free(ddict, cMem);
|
ZSTD_free(ddict, cMem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1775,7 +1792,7 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
|||||||
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
||||||
{
|
{
|
||||||
if (ddict==NULL) return 0; /* support sizeof on NULL */
|
if (ddict==NULL) return 0; /* support sizeof on NULL */
|
||||||
return sizeof(*ddict) + sizeof(ddict->refContext) + ddict->dictSize;
|
return sizeof(*ddict) + ZSTD_sizeof_DCtx(ddict->refContext) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! ZSTD_getDictID_fromDict() :
|
/*! ZSTD_getDictID_fromDict() :
|
||||||
@@ -1796,7 +1813,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|||||||
unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
|
unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
|
||||||
{
|
{
|
||||||
if (ddict==NULL) return 0;
|
if (ddict==NULL) return 0;
|
||||||
return ZSTD_getDictID_fromDict(ddict->dict, ddict->dictSize);
|
return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! ZSTD_getDictID_fromFrame() :
|
/*! ZSTD_getDictID_fromFrame() :
|
||||||
@@ -1827,7 +1844,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|||||||
const ZSTD_DDict* ddict)
|
const ZSTD_DDict* ddict)
|
||||||
{
|
{
|
||||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
|
||||||
if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, ddict->dict, ddict->dictSize);
|
if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, ddict->dictContent, ddict->dictSize);
|
||||||
#endif
|
#endif
|
||||||
ZSTD_refDCtx(dctx, ddict->refContext);
|
ZSTD_refDCtx(dctx, ddict->refContext);
|
||||||
ZSTD_checkContinuity(dctx, dst);
|
ZSTD_checkContinuity(dctx, dst);
|
||||||
@@ -1919,7 +1936,7 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
|||||||
zds->stage = zdss_loadHeader;
|
zds->stage = zdss_loadHeader;
|
||||||
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
||||||
ZSTD_freeDDict(zds->ddictLocal);
|
ZSTD_freeDDict(zds->ddictLocal);
|
||||||
if (dict) {
|
if (dict && dictSize >= 8) {
|
||||||
zds->ddictLocal = ZSTD_createDDict(dict, dictSize);
|
zds->ddictLocal = ZSTD_createDDict(dict, dictSize);
|
||||||
if (zds->ddictLocal == NULL) return ERROR(memory_allocation);
|
if (zds->ddictLocal == NULL) return ERROR(memory_allocation);
|
||||||
} else zds->ddictLocal = NULL;
|
} else zds->ddictLocal = NULL;
|
||||||
@@ -1956,7 +1973,7 @@ size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
|
|||||||
switch(paramType)
|
switch(paramType)
|
||||||
{
|
{
|
||||||
default : return ERROR(parameter_unknown);
|
default : return ERROR(parameter_unknown);
|
||||||
case ZSTDdsp_maxWindowSize : zds->maxWindowSize = paramValue ? paramValue : (U32)(-1); break;
|
case DStream_p_maxWindowSize : zds->maxWindowSize = paramValue ? paramValue : (U32)(-1); break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2007,7 +2024,7 @@ 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 ? zds->ddict->dict : NULL;
|
const void* const dict = zds->ddict ? zds->ddict->dictContent : NULL;
|
||||||
size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0;
|
size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0;
|
||||||
CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion,
|
CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion,
|
||||||
dict, dictSize));
|
dict, dictSize));
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-*************************************
|
||||||
|
* Dependencies
|
||||||
|
***************************************/
|
||||||
|
#include "error_private.h"
|
||||||
|
#include "zbuff.h"
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* ZBUFF Error Management (deprecated)
|
||||||
|
******************************************/
|
||||||
|
|
||||||
|
/*! ZBUFF_isError() :
|
||||||
|
* tells if a return value is an error code */
|
||||||
|
unsigned ZBUFF_isError(size_t errorCode) { return ERR_isError(errorCode); }
|
||||||
|
/*! ZBUFF_getErrorName() :
|
||||||
|
* provides error code string from function result (useful for debugging) */
|
||||||
|
const char* ZBUFF_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
|
||||||
|
|
||||||
@@ -0,0 +1,1021 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-*************************************
|
||||||
|
* Dependencies
|
||||||
|
***************************************/
|
||||||
|
#include <stdio.h> /* fprintf */
|
||||||
|
#include <stdlib.h> /* malloc, free, qsort */
|
||||||
|
#include <string.h> /* memset */
|
||||||
|
#include <time.h> /* clock */
|
||||||
|
|
||||||
|
#include "mem.h" /* read */
|
||||||
|
#include "pool.h"
|
||||||
|
#include "threading.h"
|
||||||
|
#include "zstd_internal.h" /* includes zstd.h */
|
||||||
|
#ifndef ZDICT_STATIC_LINKING_ONLY
|
||||||
|
#define ZDICT_STATIC_LINKING_ONLY
|
||||||
|
#endif
|
||||||
|
#include "zdict.h"
|
||||||
|
|
||||||
|
/*-*************************************
|
||||||
|
* Constants
|
||||||
|
***************************************/
|
||||||
|
#define COVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((U32)-1) : ((U32)1 GB))
|
||||||
|
|
||||||
|
/*-*************************************
|
||||||
|
* Console display
|
||||||
|
***************************************/
|
||||||
|
static int g_displayLevel = 2;
|
||||||
|
#define DISPLAY(...) \
|
||||||
|
{ \
|
||||||
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
|
fflush(stderr); \
|
||||||
|
}
|
||||||
|
#define LOCALDISPLAYLEVEL(displayLevel, l, ...) \
|
||||||
|
if (displayLevel >= l) { \
|
||||||
|
DISPLAY(__VA_ARGS__); \
|
||||||
|
} /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */
|
||||||
|
#define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \
|
||||||
|
if (displayLevel >= l) { \
|
||||||
|
if ((clock() - g_time > refreshRate) || (displayLevel >= 4)) { \
|
||||||
|
g_time = clock(); \
|
||||||
|
DISPLAY(__VA_ARGS__); \
|
||||||
|
if (displayLevel >= 4) \
|
||||||
|
fflush(stdout); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__)
|
||||||
|
static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
|
||||||
|
static clock_t g_time = 0;
|
||||||
|
|
||||||
|
/*-*************************************
|
||||||
|
* Hash table
|
||||||
|
***************************************
|
||||||
|
* A small specialized hash map for storing activeDmers.
|
||||||
|
* The map does not resize, so if it becomes full it will loop forever.
|
||||||
|
* Thus, the map must be large enough to store every value.
|
||||||
|
* The map implements linear probing and keeps its load less than 0.5.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAP_EMPTY_VALUE ((U32)-1)
|
||||||
|
typedef struct COVER_map_pair_t_s {
|
||||||
|
U32 key;
|
||||||
|
U32 value;
|
||||||
|
} COVER_map_pair_t;
|
||||||
|
|
||||||
|
typedef struct COVER_map_s {
|
||||||
|
COVER_map_pair_t *data;
|
||||||
|
U32 sizeLog;
|
||||||
|
U32 size;
|
||||||
|
U32 sizeMask;
|
||||||
|
} COVER_map_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the map.
|
||||||
|
*/
|
||||||
|
static void COVER_map_clear(COVER_map_t *map) {
|
||||||
|
memset(map->data, MAP_EMPTY_VALUE, map->size * sizeof(COVER_map_pair_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a map of the given size.
|
||||||
|
* Returns 1 on success and 0 on failure.
|
||||||
|
* The map must be destroyed with COVER_map_destroy().
|
||||||
|
* The map is only guaranteed to be large enough to hold size elements.
|
||||||
|
*/
|
||||||
|
static int COVER_map_init(COVER_map_t *map, U32 size) {
|
||||||
|
map->sizeLog = ZSTD_highbit32(size) + 2;
|
||||||
|
map->size = (U32)1 << map->sizeLog;
|
||||||
|
map->sizeMask = map->size - 1;
|
||||||
|
map->data = (COVER_map_pair_t *)malloc(map->size * sizeof(COVER_map_pair_t));
|
||||||
|
if (!map->data) {
|
||||||
|
map->sizeLog = 0;
|
||||||
|
map->size = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COVER_map_clear(map);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal hash function
|
||||||
|
*/
|
||||||
|
static const U32 prime4bytes = 2654435761U;
|
||||||
|
static U32 COVER_map_hash(COVER_map_t *map, U32 key) {
|
||||||
|
return (key * prime4bytes) >> (32 - map->sizeLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function that returns the index that a key should be placed into.
|
||||||
|
*/
|
||||||
|
static U32 COVER_map_index(COVER_map_t *map, U32 key) {
|
||||||
|
const U32 hash = COVER_map_hash(map, key);
|
||||||
|
U32 i;
|
||||||
|
for (i = hash;; i = (i + 1) & map->sizeMask) {
|
||||||
|
COVER_map_pair_t *pos = &map->data[i];
|
||||||
|
if (pos->value == MAP_EMPTY_VALUE) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
if (pos->key == key) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the pointer to the value for key.
|
||||||
|
* If key is not in the map, it is inserted and the value is set to 0.
|
||||||
|
* The map must not be full.
|
||||||
|
*/
|
||||||
|
static U32 *COVER_map_at(COVER_map_t *map, U32 key) {
|
||||||
|
COVER_map_pair_t *pos = &map->data[COVER_map_index(map, key)];
|
||||||
|
if (pos->value == MAP_EMPTY_VALUE) {
|
||||||
|
pos->key = key;
|
||||||
|
pos->value = 0;
|
||||||
|
}
|
||||||
|
return &pos->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes key from the map if present.
|
||||||
|
*/
|
||||||
|
static void COVER_map_remove(COVER_map_t *map, U32 key) {
|
||||||
|
U32 i = COVER_map_index(map, key);
|
||||||
|
COVER_map_pair_t *del = &map->data[i];
|
||||||
|
U32 shift = 1;
|
||||||
|
if (del->value == MAP_EMPTY_VALUE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = (i + 1) & map->sizeMask;; i = (i + 1) & map->sizeMask) {
|
||||||
|
COVER_map_pair_t *const pos = &map->data[i];
|
||||||
|
/* If the position is empty we are done */
|
||||||
|
if (pos->value == MAP_EMPTY_VALUE) {
|
||||||
|
del->value = MAP_EMPTY_VALUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* If pos can be moved to del do so */
|
||||||
|
if (((i - COVER_map_hash(map, pos->key)) & map->sizeMask) >= shift) {
|
||||||
|
del->key = pos->key;
|
||||||
|
del->value = pos->value;
|
||||||
|
del = pos;
|
||||||
|
shift = 1;
|
||||||
|
} else {
|
||||||
|
++shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroyes a map that is inited with COVER_map_init().
|
||||||
|
*/
|
||||||
|
static void COVER_map_destroy(COVER_map_t *map) {
|
||||||
|
if (map->data) {
|
||||||
|
free(map->data);
|
||||||
|
}
|
||||||
|
map->data = NULL;
|
||||||
|
map->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-*************************************
|
||||||
|
* Context
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const BYTE *samples;
|
||||||
|
size_t *offsets;
|
||||||
|
const size_t *samplesSizes;
|
||||||
|
size_t nbSamples;
|
||||||
|
U32 *suffix;
|
||||||
|
size_t suffixSize;
|
||||||
|
U32 *freqs;
|
||||||
|
U32 *dmerAt;
|
||||||
|
unsigned d;
|
||||||
|
} COVER_ctx_t;
|
||||||
|
|
||||||
|
/* We need a global context for qsort... */
|
||||||
|
static COVER_ctx_t *g_ctx = NULL;
|
||||||
|
|
||||||
|
/*-*************************************
|
||||||
|
* Helper functions
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sum of the sample sizes.
|
||||||
|
*/
|
||||||
|
static size_t COVER_sum(const size_t *samplesSizes, unsigned nbSamples) {
|
||||||
|
size_t sum = 0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < nbSamples; ++i) {
|
||||||
|
sum += samplesSizes[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns -1 if the dmer at lp is less than the dmer at rp.
|
||||||
|
* Return 0 if the dmers at lp and rp are equal.
|
||||||
|
* Returns 1 if the dmer at lp is greater than the dmer at rp.
|
||||||
|
*/
|
||||||
|
static int COVER_cmp(COVER_ctx_t *ctx, const void *lp, const void *rp) {
|
||||||
|
const U32 lhs = *(const U32 *)lp;
|
||||||
|
const U32 rhs = *(const U32 *)rp;
|
||||||
|
return memcmp(ctx->samples + lhs, ctx->samples + rhs, ctx->d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as COVER_cmp() except ties are broken by pointer value
|
||||||
|
* NOTE: g_ctx must be set to call this function. A global is required because
|
||||||
|
* qsort doesn't take an opaque pointer.
|
||||||
|
*/
|
||||||
|
static int COVER_strict_cmp(const void *lp, const void *rp) {
|
||||||
|
int result = COVER_cmp(g_ctx, lp, rp);
|
||||||
|
if (result == 0) {
|
||||||
|
result = lp < rp ? -1 : 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first pointer in [first, last) whose element does not compare
|
||||||
|
* less than value. If no such element exists it returns last.
|
||||||
|
*/
|
||||||
|
static const size_t *COVER_lower_bound(const size_t *first, const size_t *last,
|
||||||
|
size_t value) {
|
||||||
|
size_t count = last - first;
|
||||||
|
while (count != 0) {
|
||||||
|
size_t step = count / 2;
|
||||||
|
const size_t *ptr = first;
|
||||||
|
ptr += step;
|
||||||
|
if (*ptr < value) {
|
||||||
|
first = ++ptr;
|
||||||
|
count -= step + 1;
|
||||||
|
} else {
|
||||||
|
count = step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic groupBy function.
|
||||||
|
* Groups an array sorted by cmp into groups with equivalent values.
|
||||||
|
* Calls grp for each group.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
COVER_groupBy(const void *data, size_t count, size_t size, COVER_ctx_t *ctx,
|
||||||
|
int (*cmp)(COVER_ctx_t *, const void *, const void *),
|
||||||
|
void (*grp)(COVER_ctx_t *, const void *, const void *)) {
|
||||||
|
const BYTE *ptr = (const BYTE *)data;
|
||||||
|
size_t num = 0;
|
||||||
|
while (num < count) {
|
||||||
|
const BYTE *grpEnd = ptr + size;
|
||||||
|
++num;
|
||||||
|
while (num < count && cmp(ctx, ptr, grpEnd) == 0) {
|
||||||
|
grpEnd += size;
|
||||||
|
++num;
|
||||||
|
}
|
||||||
|
grp(ctx, ptr, grpEnd);
|
||||||
|
ptr = grpEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-*************************************
|
||||||
|
* Cover functions
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on each group of positions with the same dmer.
|
||||||
|
* Counts the frequency of each dmer and saves it in the suffix array.
|
||||||
|
* Fills `ctx->dmerAt`.
|
||||||
|
*/
|
||||||
|
static void COVER_group(COVER_ctx_t *ctx, const void *group,
|
||||||
|
const void *groupEnd) {
|
||||||
|
/* The group consists of all the positions with the same first d bytes. */
|
||||||
|
const U32 *grpPtr = (const U32 *)group;
|
||||||
|
const U32 *grpEnd = (const U32 *)groupEnd;
|
||||||
|
/* The dmerId is how we will reference this dmer.
|
||||||
|
* This allows us to map the whole dmer space to a much smaller space, the
|
||||||
|
* size of the suffix array.
|
||||||
|
*/
|
||||||
|
const U32 dmerId = (U32)(grpPtr - ctx->suffix);
|
||||||
|
/* Count the number of samples this dmer shows up in */
|
||||||
|
U32 freq = 0;
|
||||||
|
/* Details */
|
||||||
|
const size_t *curOffsetPtr = ctx->offsets;
|
||||||
|
const size_t *offsetsEnd = ctx->offsets + ctx->nbSamples;
|
||||||
|
/* Once *grpPtr >= curSampleEnd this occurrence of the dmer is in a
|
||||||
|
* different sample than the last.
|
||||||
|
*/
|
||||||
|
size_t curSampleEnd = ctx->offsets[0];
|
||||||
|
for (; grpPtr != grpEnd; ++grpPtr) {
|
||||||
|
/* Save the dmerId for this position so we can get back to it. */
|
||||||
|
ctx->dmerAt[*grpPtr] = dmerId;
|
||||||
|
/* Dictionaries only help for the first reference to the dmer.
|
||||||
|
* After that zstd can reference the match from the previous reference.
|
||||||
|
* So only count each dmer once for each sample it is in.
|
||||||
|
*/
|
||||||
|
if (*grpPtr < curSampleEnd) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
freq += 1;
|
||||||
|
/* Binary search to find the end of the sample *grpPtr is in.
|
||||||
|
* In the common case that grpPtr + 1 == grpEnd we can skip the binary
|
||||||
|
* search because the loop is over.
|
||||||
|
*/
|
||||||
|
if (grpPtr + 1 != grpEnd) {
|
||||||
|
const size_t *sampleEndPtr =
|
||||||
|
COVER_lower_bound(curOffsetPtr, offsetsEnd, *grpPtr);
|
||||||
|
curSampleEnd = *sampleEndPtr;
|
||||||
|
curOffsetPtr = sampleEndPtr + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* At this point we are never going to look at this segment of the suffix
|
||||||
|
* array again. We take advantage of this fact to save memory.
|
||||||
|
* We store the frequency of the dmer in the first position of the group,
|
||||||
|
* which is dmerId.
|
||||||
|
*/
|
||||||
|
ctx->suffix[dmerId] = freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A segment is a range in the source as well as the score of the segment.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
U32 begin;
|
||||||
|
U32 end;
|
||||||
|
double score;
|
||||||
|
} COVER_segment_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the best segment in an epoch.
|
||||||
|
* Segments of are scored according to the function:
|
||||||
|
*
|
||||||
|
* Let F(d) be the frequency of dmer d.
|
||||||
|
* Let S_i be the dmer at position i of segment S which has length k.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs,
|
||||||
|
COVER_map_t *activeDmers, U32 begin,
|
||||||
|
U32 end, COVER_params_t parameters) {
|
||||||
|
/* Constants */
|
||||||
|
const U32 k = parameters.k;
|
||||||
|
const U32 d = parameters.d;
|
||||||
|
const U32 dmersInK = k - d + 1;
|
||||||
|
/* Try each segment (activeSegment) and save the best (bestSegment) */
|
||||||
|
COVER_segment_t bestSegment = {0, 0, 0};
|
||||||
|
COVER_segment_t activeSegment;
|
||||||
|
/* Reset the activeDmers in the segment */
|
||||||
|
COVER_map_clear(activeDmers);
|
||||||
|
/* The activeSegment starts at the beginning of the epoch. */
|
||||||
|
activeSegment.begin = begin;
|
||||||
|
activeSegment.end = begin;
|
||||||
|
activeSegment.score = 0;
|
||||||
|
/* Slide the activeSegment through the whole epoch.
|
||||||
|
* Save the best segment in bestSegment.
|
||||||
|
*/
|
||||||
|
while (activeSegment.end < end) {
|
||||||
|
/* The dmerId for the dmer at the next position */
|
||||||
|
U32 newDmer = ctx->dmerAt[activeSegment.end];
|
||||||
|
/* The entry in activeDmers for this dmerId */
|
||||||
|
U32 *newDmerOcc = COVER_map_at(activeDmers, newDmer);
|
||||||
|
/* If the dmer isn't already present in the segment add its score. */
|
||||||
|
if (*newDmerOcc == 0) {
|
||||||
|
/* The paper suggest using the L-0.5 norm, but experiments show that it
|
||||||
|
* doesn't help.
|
||||||
|
*/
|
||||||
|
activeSegment.score += freqs[newDmer];
|
||||||
|
}
|
||||||
|
/* Add the dmer to the segment */
|
||||||
|
activeSegment.end += 1;
|
||||||
|
*newDmerOcc += 1;
|
||||||
|
|
||||||
|
/* If the window is now too large, drop the first position */
|
||||||
|
if (activeSegment.end - activeSegment.begin == dmersInK + 1) {
|
||||||
|
U32 delDmer = ctx->dmerAt[activeSegment.begin];
|
||||||
|
U32 *delDmerOcc = COVER_map_at(activeDmers, delDmer);
|
||||||
|
activeSegment.begin += 1;
|
||||||
|
*delDmerOcc -= 1;
|
||||||
|
/* If this is the last occurence of the dmer, subtract its score */
|
||||||
|
if (*delDmerOcc == 0) {
|
||||||
|
COVER_map_remove(activeDmers, delDmer);
|
||||||
|
activeSegment.score -= freqs[delDmer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this segment is the best so far save it */
|
||||||
|
if (activeSegment.score > bestSegment.score) {
|
||||||
|
bestSegment = activeSegment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Trim off the zero frequency head and tail from the segment. */
|
||||||
|
U32 newBegin = bestSegment.end;
|
||||||
|
U32 newEnd = bestSegment.begin;
|
||||||
|
U32 pos;
|
||||||
|
for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) {
|
||||||
|
U32 freq = freqs[ctx->dmerAt[pos]];
|
||||||
|
if (freq != 0) {
|
||||||
|
newBegin = MIN(newBegin, pos);
|
||||||
|
newEnd = pos + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bestSegment.begin = newBegin;
|
||||||
|
bestSegment.end = newEnd;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Zero out the frequency of each dmer covered by the chosen segment. */
|
||||||
|
U32 pos;
|
||||||
|
for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) {
|
||||||
|
freqs[ctx->dmerAt[pos]] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestSegment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the validity of the parameters.
|
||||||
|
* Returns non-zero if the parameters are valid and 0 otherwise.
|
||||||
|
*/
|
||||||
|
static int COVER_checkParameters(COVER_params_t parameters) {
|
||||||
|
/* k and d are required parameters */
|
||||||
|
if (parameters.d == 0 || parameters.k == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* d <= k */
|
||||||
|
if (parameters.d > parameters.k) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up a context initialized with `COVER_ctx_init()`.
|
||||||
|
*/
|
||||||
|
static void COVER_ctx_destroy(COVER_ctx_t *ctx) {
|
||||||
|
if (!ctx) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ctx->suffix) {
|
||||||
|
free(ctx->suffix);
|
||||||
|
ctx->suffix = NULL;
|
||||||
|
}
|
||||||
|
if (ctx->freqs) {
|
||||||
|
free(ctx->freqs);
|
||||||
|
ctx->freqs = NULL;
|
||||||
|
}
|
||||||
|
if (ctx->dmerAt) {
|
||||||
|
free(ctx->dmerAt);
|
||||||
|
ctx->dmerAt = NULL;
|
||||||
|
}
|
||||||
|
if (ctx->offsets) {
|
||||||
|
free(ctx->offsets);
|
||||||
|
ctx->offsets = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare a context for dictionary building.
|
||||||
|
* The context is only dependent on the parameter `d` and can used multiple
|
||||||
|
* times.
|
||||||
|
* Returns 1 on success or zero on error.
|
||||||
|
* The context must be destroyed with `COVER_ctx_destroy()`.
|
||||||
|
*/
|
||||||
|
static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||||
|
const size_t *samplesSizes, unsigned nbSamples,
|
||||||
|
unsigned d) {
|
||||||
|
const BYTE *const samples = (const BYTE *)samplesBuffer;
|
||||||
|
const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples);
|
||||||
|
/* Checks */
|
||||||
|
if (totalSamplesSize < d ||
|
||||||
|
totalSamplesSize >= (size_t)COVER_MAX_SAMPLES_SIZE) {
|
||||||
|
DISPLAYLEVEL(1, "Total samples size is too large, maximum size is %u MB\n",
|
||||||
|
(COVER_MAX_SAMPLES_SIZE >> 20));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Zero the context */
|
||||||
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
|
DISPLAYLEVEL(2, "Training on %u samples of total size %u\n", nbSamples,
|
||||||
|
(U32)totalSamplesSize);
|
||||||
|
ctx->samples = samples;
|
||||||
|
ctx->samplesSizes = samplesSizes;
|
||||||
|
ctx->nbSamples = nbSamples;
|
||||||
|
/* Partial suffix array */
|
||||||
|
ctx->suffixSize = totalSamplesSize - d + 1;
|
||||||
|
ctx->suffix = (U32 *)malloc(ctx->suffixSize * sizeof(U32));
|
||||||
|
/* Maps index to the dmerID */
|
||||||
|
ctx->dmerAt = (U32 *)malloc(ctx->suffixSize * sizeof(U32));
|
||||||
|
/* The offsets of each file */
|
||||||
|
ctx->offsets = (size_t *)malloc((nbSamples + 1) * sizeof(size_t));
|
||||||
|
if (!ctx->suffix || !ctx->dmerAt || !ctx->offsets) {
|
||||||
|
DISPLAYLEVEL(1, "Failed to allocate scratch buffers\n");
|
||||||
|
COVER_ctx_destroy(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ctx->freqs = NULL;
|
||||||
|
ctx->d = d;
|
||||||
|
|
||||||
|
/* Fill offsets from the samlesSizes */
|
||||||
|
{
|
||||||
|
U32 i;
|
||||||
|
ctx->offsets[0] = 0;
|
||||||
|
for (i = 1; i <= nbSamples; ++i) {
|
||||||
|
ctx->offsets[i] = ctx->offsets[i - 1] + samplesSizes[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(2, "Constructing partial suffix array\n");
|
||||||
|
{
|
||||||
|
/* suffix is a partial suffix array.
|
||||||
|
* It only sorts suffixes by their first parameters.d bytes.
|
||||||
|
* The sort is stable, so each dmer group is sorted by position in input.
|
||||||
|
*/
|
||||||
|
U32 i;
|
||||||
|
for (i = 0; i < ctx->suffixSize; ++i) {
|
||||||
|
ctx->suffix[i] = i;
|
||||||
|
}
|
||||||
|
/* qsort doesn't take an opaque pointer, so pass as a global */
|
||||||
|
g_ctx = ctx;
|
||||||
|
qsort(ctx->suffix, ctx->suffixSize, sizeof(U32), &COVER_strict_cmp);
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(2, "Computing frequencies\n");
|
||||||
|
/* For each dmer group (group of positions with the same first d bytes):
|
||||||
|
* 1. For each position we set dmerAt[position] = dmerID. The dmerID is
|
||||||
|
* (groupBeginPtr - suffix). This allows us to go from position to
|
||||||
|
* dmerID so we can look up values in freq.
|
||||||
|
* 2. We calculate how many samples the dmer occurs in and save it in
|
||||||
|
* freqs[dmerId].
|
||||||
|
*/
|
||||||
|
COVER_groupBy(ctx->suffix, ctx->suffixSize, sizeof(U32), ctx, &COVER_cmp,
|
||||||
|
&COVER_group);
|
||||||
|
ctx->freqs = ctx->suffix;
|
||||||
|
ctx->suffix = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the prepared context build the dictionary.
|
||||||
|
*/
|
||||||
|
static size_t COVER_buildDictionary(const COVER_ctx_t *ctx, U32 *freqs,
|
||||||
|
COVER_map_t *activeDmers, void *dictBuffer,
|
||||||
|
size_t dictBufferCapacity,
|
||||||
|
COVER_params_t parameters) {
|
||||||
|
BYTE *const dict = (BYTE *)dictBuffer;
|
||||||
|
size_t tail = dictBufferCapacity;
|
||||||
|
/* Divide the data up into epochs of equal size.
|
||||||
|
* We will select at least one segment from each epoch.
|
||||||
|
*/
|
||||||
|
const U32 epochs = (U32)(dictBufferCapacity / parameters.k);
|
||||||
|
const U32 epochSize = (U32)(ctx->suffixSize / epochs);
|
||||||
|
size_t epoch;
|
||||||
|
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n", epochs,
|
||||||
|
epochSize);
|
||||||
|
/* Loop through the epochs until there are no more segments or the dictionary
|
||||||
|
* is full.
|
||||||
|
*/
|
||||||
|
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs) {
|
||||||
|
const U32 epochBegin = (U32)(epoch * epochSize);
|
||||||
|
const U32 epochEnd = epochBegin + epochSize;
|
||||||
|
size_t segmentSize;
|
||||||
|
/* Select a segment */
|
||||||
|
COVER_segment_t segment = COVER_selectSegment(
|
||||||
|
ctx, freqs, activeDmers, epochBegin, epochEnd, parameters);
|
||||||
|
/* Trim the segment if necessary and if it is empty then we are done */
|
||||||
|
segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);
|
||||||
|
if (segmentSize == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* We fill the dictionary from the back to allow the best segments to be
|
||||||
|
* referenced with the smallest offsets.
|
||||||
|
*/
|
||||||
|
tail -= segmentSize;
|
||||||
|
memcpy(dict + tail, ctx->samples + segment.begin, segmentSize);
|
||||||
|
DISPLAYUPDATE(
|
||||||
|
2, "\r%u%% ",
|
||||||
|
(U32)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity));
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(2, "\r%79s\r", "");
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate from COVER_params_t to ZDICT_params_t required for finalizing the
|
||||||
|
* dictionary.
|
||||||
|
*/
|
||||||
|
static ZDICT_params_t COVER_translateParams(COVER_params_t parameters) {
|
||||||
|
ZDICT_params_t zdictParams;
|
||||||
|
memset(&zdictParams, 0, sizeof(zdictParams));
|
||||||
|
zdictParams.notificationLevel = 1;
|
||||||
|
zdictParams.dictID = parameters.dictID;
|
||||||
|
zdictParams.compressionLevel = parameters.compressionLevel;
|
||||||
|
return zdictParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a dictionary using a heuristic based on the following paper:
|
||||||
|
*
|
||||||
|
* Liao, Petri, Moffat, Wirth
|
||||||
|
* Effective Construction of Relative Lempel-Ziv Dictionaries
|
||||||
|
* Published in WWW 2016.
|
||||||
|
*/
|
||||||
|
ZDICTLIB_API size_t COVER_trainFromBuffer(
|
||||||
|
void *dictBuffer, size_t dictBufferCapacity, const void *samplesBuffer,
|
||||||
|
const size_t *samplesSizes, unsigned nbSamples, COVER_params_t parameters) {
|
||||||
|
BYTE *const dict = (BYTE *)dictBuffer;
|
||||||
|
COVER_ctx_t ctx;
|
||||||
|
COVER_map_t activeDmers;
|
||||||
|
/* Checks */
|
||||||
|
if (!COVER_checkParameters(parameters)) {
|
||||||
|
DISPLAYLEVEL(1, "Cover parameters incorrect\n");
|
||||||
|
return ERROR(GENERIC);
|
||||||
|
}
|
||||||
|
if (nbSamples == 0) {
|
||||||
|
DISPLAYLEVEL(1, "Cover must have at least one input file\n");
|
||||||
|
return ERROR(GENERIC);
|
||||||
|
}
|
||||||
|
if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {
|
||||||
|
DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n",
|
||||||
|
ZDICT_DICTSIZE_MIN);
|
||||||
|
return ERROR(dstSize_tooSmall);
|
||||||
|
}
|
||||||
|
/* Initialize global data */
|
||||||
|
g_displayLevel = parameters.notificationLevel;
|
||||||
|
/* Initialize context and activeDmers */
|
||||||
|
if (!COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples,
|
||||||
|
parameters.d)) {
|
||||||
|
return ERROR(GENERIC);
|
||||||
|
}
|
||||||
|
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
|
||||||
|
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
|
||||||
|
COVER_ctx_destroy(&ctx);
|
||||||
|
return ERROR(GENERIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
DISPLAYLEVEL(2, "Building dictionary\n");
|
||||||
|
{
|
||||||
|
const size_t tail =
|
||||||
|
COVER_buildDictionary(&ctx, ctx.freqs, &activeDmers, dictBuffer,
|
||||||
|
dictBufferCapacity, parameters);
|
||||||
|
ZDICT_params_t zdictParams = COVER_translateParams(parameters);
|
||||||
|
const size_t dictionarySize = ZDICT_finalizeDictionary(
|
||||||
|
dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail,
|
||||||
|
samplesBuffer, samplesSizes, nbSamples, zdictParams);
|
||||||
|
if (!ZSTD_isError(dictionarySize)) {
|
||||||
|
DISPLAYLEVEL(2, "Constructed dictionary of size %u\n",
|
||||||
|
(U32)dictionarySize);
|
||||||
|
}
|
||||||
|
COVER_ctx_destroy(&ctx);
|
||||||
|
COVER_map_destroy(&activeDmers);
|
||||||
|
return dictionarySize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COVER_best_t is used for two purposes:
|
||||||
|
* 1. Synchronizing threads.
|
||||||
|
* 2. Saving the best parameters and dictionary.
|
||||||
|
*
|
||||||
|
* All of the methods except COVER_best_init() are thread safe if zstd is
|
||||||
|
* compiled with multithreaded support.
|
||||||
|
*/
|
||||||
|
typedef struct COVER_best_s {
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
size_t liveJobs;
|
||||||
|
void *dict;
|
||||||
|
size_t dictSize;
|
||||||
|
COVER_params_t parameters;
|
||||||
|
size_t compressedSize;
|
||||||
|
} COVER_best_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the `COVER_best_t`.
|
||||||
|
*/
|
||||||
|
static void COVER_best_init(COVER_best_t *best) {
|
||||||
|
if (!best) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pthread_mutex_init(&best->mutex, NULL);
|
||||||
|
pthread_cond_init(&best->cond, NULL);
|
||||||
|
best->liveJobs = 0;
|
||||||
|
best->dict = NULL;
|
||||||
|
best->dictSize = 0;
|
||||||
|
best->compressedSize = (size_t)-1;
|
||||||
|
memset(&best->parameters, 0, sizeof(best->parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until liveJobs == 0.
|
||||||
|
*/
|
||||||
|
static void COVER_best_wait(COVER_best_t *best) {
|
||||||
|
if (!best) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&best->mutex);
|
||||||
|
while (best->liveJobs != 0) {
|
||||||
|
pthread_cond_wait(&best->cond, &best->mutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&best->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call COVER_best_wait() and then destroy the COVER_best_t.
|
||||||
|
*/
|
||||||
|
static void COVER_best_destroy(COVER_best_t *best) {
|
||||||
|
if (!best) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
COVER_best_wait(best);
|
||||||
|
if (best->dict) {
|
||||||
|
free(best->dict);
|
||||||
|
}
|
||||||
|
pthread_mutex_destroy(&best->mutex);
|
||||||
|
pthread_cond_destroy(&best->cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a thread is about to be launched.
|
||||||
|
* Increments liveJobs.
|
||||||
|
*/
|
||||||
|
static void COVER_best_start(COVER_best_t *best) {
|
||||||
|
if (!best) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&best->mutex);
|
||||||
|
++best->liveJobs;
|
||||||
|
pthread_mutex_unlock(&best->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a thread finishes executing, both on error or success.
|
||||||
|
* Decrements liveJobs and signals any waiting threads if liveJobs == 0.
|
||||||
|
* If this dictionary is the best so far save it and its parameters.
|
||||||
|
*/
|
||||||
|
static void COVER_best_finish(COVER_best_t *best, size_t compressedSize,
|
||||||
|
COVER_params_t parameters, void *dict,
|
||||||
|
size_t dictSize) {
|
||||||
|
if (!best) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
size_t liveJobs;
|
||||||
|
pthread_mutex_lock(&best->mutex);
|
||||||
|
--best->liveJobs;
|
||||||
|
liveJobs = best->liveJobs;
|
||||||
|
/* If the new dictionary is better */
|
||||||
|
if (compressedSize < best->compressedSize) {
|
||||||
|
/* Allocate space if necessary */
|
||||||
|
if (!best->dict || best->dictSize < dictSize) {
|
||||||
|
if (best->dict) {
|
||||||
|
free(best->dict);
|
||||||
|
}
|
||||||
|
best->dict = malloc(dictSize);
|
||||||
|
if (!best->dict) {
|
||||||
|
best->compressedSize = ERROR(GENERIC);
|
||||||
|
best->dictSize = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Save the dictionary, parameters, and size */
|
||||||
|
memcpy(best->dict, dict, dictSize);
|
||||||
|
best->dictSize = dictSize;
|
||||||
|
best->parameters = parameters;
|
||||||
|
best->compressedSize = compressedSize;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&best->mutex);
|
||||||
|
if (liveJobs == 0) {
|
||||||
|
pthread_cond_broadcast(&best->cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters for COVER_tryParameters().
|
||||||
|
*/
|
||||||
|
typedef struct COVER_tryParameters_data_s {
|
||||||
|
const COVER_ctx_t *ctx;
|
||||||
|
COVER_best_t *best;
|
||||||
|
size_t dictBufferCapacity;
|
||||||
|
COVER_params_t parameters;
|
||||||
|
} COVER_tryParameters_data_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries a set of parameters and upates the COVER_best_t with the results.
|
||||||
|
* This function is thread safe if zstd is compiled with multithreaded support.
|
||||||
|
* It takes its parameters as an *OWNING* opaque pointer to support threading.
|
||||||
|
*/
|
||||||
|
static void COVER_tryParameters(void *opaque) {
|
||||||
|
/* Save parameters as local variables */
|
||||||
|
COVER_tryParameters_data_t *const data = (COVER_tryParameters_data_t *)opaque;
|
||||||
|
const COVER_ctx_t *const ctx = data->ctx;
|
||||||
|
const COVER_params_t parameters = data->parameters;
|
||||||
|
size_t dictBufferCapacity = data->dictBufferCapacity;
|
||||||
|
size_t totalCompressedSize = ERROR(GENERIC);
|
||||||
|
/* Allocate space for hash table, dict, and freqs */
|
||||||
|
COVER_map_t activeDmers;
|
||||||
|
BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity);
|
||||||
|
U32 *freqs = (U32 *)malloc(ctx->suffixSize * sizeof(U32));
|
||||||
|
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
|
||||||
|
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
|
||||||
|
goto _cleanup;
|
||||||
|
}
|
||||||
|
if (!dict || !freqs) {
|
||||||
|
DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n");
|
||||||
|
goto _cleanup;
|
||||||
|
}
|
||||||
|
/* Copy the frequencies because we need to modify them */
|
||||||
|
memcpy(freqs, ctx->freqs, ctx->suffixSize * sizeof(U32));
|
||||||
|
/* Build the dictionary */
|
||||||
|
{
|
||||||
|
const size_t tail = COVER_buildDictionary(ctx, freqs, &activeDmers, dict,
|
||||||
|
dictBufferCapacity, parameters);
|
||||||
|
const ZDICT_params_t zdictParams = COVER_translateParams(parameters);
|
||||||
|
dictBufferCapacity = ZDICT_finalizeDictionary(
|
||||||
|
dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail,
|
||||||
|
ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbSamples, zdictParams);
|
||||||
|
if (ZDICT_isError(dictBufferCapacity)) {
|
||||||
|
DISPLAYLEVEL(1, "Failed to finalize dictionary\n");
|
||||||
|
goto _cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check total compressed size */
|
||||||
|
{
|
||||||
|
/* Pointers */
|
||||||
|
ZSTD_CCtx *cctx;
|
||||||
|
ZSTD_CDict *cdict;
|
||||||
|
void *dst;
|
||||||
|
/* Local variables */
|
||||||
|
size_t dstCapacity;
|
||||||
|
size_t i;
|
||||||
|
/* Allocate dst with enough space to compress the maximum sized sample */
|
||||||
|
{
|
||||||
|
size_t maxSampleSize = 0;
|
||||||
|
for (i = 0; i < ctx->nbSamples; ++i) {
|
||||||
|
maxSampleSize = MAX(ctx->samplesSizes[i], maxSampleSize);
|
||||||
|
}
|
||||||
|
dstCapacity = ZSTD_compressBound(maxSampleSize);
|
||||||
|
dst = malloc(dstCapacity);
|
||||||
|
}
|
||||||
|
/* Create the cctx and cdict */
|
||||||
|
cctx = ZSTD_createCCtx();
|
||||||
|
cdict =
|
||||||
|
ZSTD_createCDict(dict, dictBufferCapacity, parameters.compressionLevel);
|
||||||
|
if (!dst || !cctx || !cdict) {
|
||||||
|
goto _compressCleanup;
|
||||||
|
}
|
||||||
|
/* Compress each sample and sum their sizes (or error) */
|
||||||
|
totalCompressedSize = 0;
|
||||||
|
for (i = 0; i < ctx->nbSamples; ++i) {
|
||||||
|
const size_t size = ZSTD_compress_usingCDict(
|
||||||
|
cctx, dst, dstCapacity, ctx->samples + ctx->offsets[i],
|
||||||
|
ctx->samplesSizes[i], cdict);
|
||||||
|
if (ZSTD_isError(size)) {
|
||||||
|
totalCompressedSize = ERROR(GENERIC);
|
||||||
|
goto _compressCleanup;
|
||||||
|
}
|
||||||
|
totalCompressedSize += size;
|
||||||
|
}
|
||||||
|
_compressCleanup:
|
||||||
|
ZSTD_freeCCtx(cctx);
|
||||||
|
ZSTD_freeCDict(cdict);
|
||||||
|
if (dst) {
|
||||||
|
free(dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_cleanup:
|
||||||
|
COVER_best_finish(data->best, totalCompressedSize, parameters, dict,
|
||||||
|
dictBufferCapacity);
|
||||||
|
free(data);
|
||||||
|
COVER_map_destroy(&activeDmers);
|
||||||
|
if (dict) {
|
||||||
|
free(dict);
|
||||||
|
}
|
||||||
|
if (freqs) {
|
||||||
|
free(freqs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer,
|
||||||
|
size_t dictBufferCapacity,
|
||||||
|
const void *samplesBuffer,
|
||||||
|
const size_t *samplesSizes,
|
||||||
|
unsigned nbSamples,
|
||||||
|
COVER_params_t *parameters) {
|
||||||
|
/* constants */
|
||||||
|
const unsigned nbThreads = parameters->nbThreads;
|
||||||
|
const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d;
|
||||||
|
const unsigned kMaxD = parameters->d == 0 ? 16 : parameters->d;
|
||||||
|
const unsigned kMinK = parameters->k == 0 ? kMaxD : parameters->k;
|
||||||
|
const unsigned kMaxK = parameters->k == 0 ? 2048 : parameters->k;
|
||||||
|
const unsigned kSteps = parameters->steps == 0 ? 32 : parameters->steps;
|
||||||
|
const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1);
|
||||||
|
const unsigned kIterations =
|
||||||
|
(1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize);
|
||||||
|
/* Local variables */
|
||||||
|
const int displayLevel = parameters->notificationLevel;
|
||||||
|
unsigned iteration = 1;
|
||||||
|
unsigned d;
|
||||||
|
unsigned k;
|
||||||
|
COVER_best_t best;
|
||||||
|
POOL_ctx *pool = NULL;
|
||||||
|
/* Checks */
|
||||||
|
if (kMinK < kMaxD || kMaxK < kMinK) {
|
||||||
|
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect parameters\n");
|
||||||
|
return ERROR(GENERIC);
|
||||||
|
}
|
||||||
|
if (nbSamples == 0) {
|
||||||
|
DISPLAYLEVEL(1, "Cover must have at least one input file\n");
|
||||||
|
return ERROR(GENERIC);
|
||||||
|
}
|
||||||
|
if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {
|
||||||
|
DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n",
|
||||||
|
ZDICT_DICTSIZE_MIN);
|
||||||
|
return ERROR(dstSize_tooSmall);
|
||||||
|
}
|
||||||
|
if (nbThreads > 1) {
|
||||||
|
pool = POOL_create(nbThreads, 1);
|
||||||
|
if (!pool) {
|
||||||
|
return ERROR(memory_allocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Initialization */
|
||||||
|
COVER_best_init(&best);
|
||||||
|
/* Turn down global display level to clean up display at level 2 and below */
|
||||||
|
g_displayLevel = parameters->notificationLevel - 1;
|
||||||
|
/* Loop through d first because each new value needs a new context */
|
||||||
|
LOCALDISPLAYLEVEL(displayLevel, 2, "Trying %u different sets of parameters\n",
|
||||||
|
kIterations);
|
||||||
|
for (d = kMinD; d <= kMaxD; d += 2) {
|
||||||
|
/* Initialize the context for this value of d */
|
||||||
|
COVER_ctx_t ctx;
|
||||||
|
LOCALDISPLAYLEVEL(displayLevel, 3, "d=%u\n", d);
|
||||||
|
if (!COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d)) {
|
||||||
|
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n");
|
||||||
|
COVER_best_destroy(&best);
|
||||||
|
return ERROR(GENERIC);
|
||||||
|
}
|
||||||
|
/* Loop through k reusing the same context */
|
||||||
|
for (k = kMinK; k <= kMaxK; k += kStepSize) {
|
||||||
|
/* Prepare the arguments */
|
||||||
|
COVER_tryParameters_data_t *data = (COVER_tryParameters_data_t *)malloc(
|
||||||
|
sizeof(COVER_tryParameters_data_t));
|
||||||
|
LOCALDISPLAYLEVEL(displayLevel, 3, "k=%u\n", k);
|
||||||
|
if (!data) {
|
||||||
|
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to allocate parameters\n");
|
||||||
|
COVER_best_destroy(&best);
|
||||||
|
COVER_ctx_destroy(&ctx);
|
||||||
|
return ERROR(GENERIC);
|
||||||
|
}
|
||||||
|
data->ctx = &ctx;
|
||||||
|
data->best = &best;
|
||||||
|
data->dictBufferCapacity = dictBufferCapacity;
|
||||||
|
data->parameters = *parameters;
|
||||||
|
data->parameters.k = k;
|
||||||
|
data->parameters.d = d;
|
||||||
|
data->parameters.steps = kSteps;
|
||||||
|
/* Check the parameters */
|
||||||
|
if (!COVER_checkParameters(data->parameters)) {
|
||||||
|
DISPLAYLEVEL(1, "Cover parameters incorrect\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Call the function and pass ownership of data to it */
|
||||||
|
COVER_best_start(&best);
|
||||||
|
if (pool) {
|
||||||
|
POOL_add(pool, &COVER_tryParameters, data);
|
||||||
|
} else {
|
||||||
|
COVER_tryParameters(data);
|
||||||
|
}
|
||||||
|
/* Print status */
|
||||||
|
LOCALDISPLAYUPDATE(displayLevel, 2, "\r%u%% ",
|
||||||
|
(U32)((iteration * 100) / kIterations));
|
||||||
|
++iteration;
|
||||||
|
}
|
||||||
|
COVER_best_wait(&best);
|
||||||
|
COVER_ctx_destroy(&ctx);
|
||||||
|
}
|
||||||
|
LOCALDISPLAYLEVEL(displayLevel, 2, "\r%79s\r", "");
|
||||||
|
/* Fill the output buffer and parameters with output of the best parameters */
|
||||||
|
{
|
||||||
|
const size_t dictSize = best.dictSize;
|
||||||
|
if (ZSTD_isError(best.compressedSize)) {
|
||||||
|
COVER_best_destroy(&best);
|
||||||
|
return best.compressedSize;
|
||||||
|
}
|
||||||
|
*parameters = best.parameters;
|
||||||
|
memcpy(dictBuffer, best.dict, dictSize);
|
||||||
|
COVER_best_destroy(&best);
|
||||||
|
POOL_free(pool);
|
||||||
|
return dictSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
-12
@@ -36,12 +36,11 @@
|
|||||||
#include <time.h> /* clock */
|
#include <time.h> /* clock */
|
||||||
|
|
||||||
#include "mem.h" /* read */
|
#include "mem.h" /* read */
|
||||||
#include "error_private.h"
|
|
||||||
#include "fse.h" /* FSE_normalizeCount, FSE_writeNCount */
|
#include "fse.h" /* FSE_normalizeCount, FSE_writeNCount */
|
||||||
#define HUF_STATIC_LINKING_ONLY
|
#define HUF_STATIC_LINKING_ONLY
|
||||||
#include "huf.h"
|
#include "huf.h" /* HUF_buildCTable, HUF_writeCTable */
|
||||||
#include "zstd_internal.h" /* includes zstd.h */
|
#include "zstd_internal.h" /* includes zstd.h */
|
||||||
#include "xxhash.h"
|
#include "xxhash.h" /* XXH64 */
|
||||||
#include "divsufsort.h"
|
#include "divsufsort.h"
|
||||||
#ifndef ZDICT_STATIC_LINKING_ONLY
|
#ifndef ZDICT_STATIC_LINKING_ONLY
|
||||||
# define ZDICT_STATIC_LINKING_ONLY
|
# define ZDICT_STATIC_LINKING_ONLY
|
||||||
@@ -61,7 +60,7 @@
|
|||||||
#define NOISELENGTH 32
|
#define NOISELENGTH 32
|
||||||
|
|
||||||
#define MINRATIO 4
|
#define MINRATIO 4
|
||||||
static const int g_compressionLevel_default = 5;
|
static const int g_compressionLevel_default = 6;
|
||||||
static const U32 g_selectivity_default = 9;
|
static const U32 g_selectivity_default = 9;
|
||||||
static const size_t g_provision_entropySize = 200;
|
static const size_t g_provision_entropySize = 200;
|
||||||
static const size_t g_min_fast_dictContent = 192;
|
static const size_t g_min_fast_dictContent = 192;
|
||||||
@@ -307,13 +306,13 @@ static dictItem ZDICT_analyzePos(
|
|||||||
} while (length >=MINMATCHLENGTH);
|
} while (length >=MINMATCHLENGTH);
|
||||||
|
|
||||||
/* look backward */
|
/* look backward */
|
||||||
length = MINMATCHLENGTH;
|
length = MINMATCHLENGTH;
|
||||||
while ((length >= MINMATCHLENGTH) & (start > 0)) {
|
while ((length >= MINMATCHLENGTH) & (start > 0)) {
|
||||||
length = ZDICT_count(b + pos, b + suffix[start - 1]);
|
length = ZDICT_count(b + pos, b + suffix[start - 1]);
|
||||||
if (length >= LLIMIT) length = LLIMIT - 1;
|
if (length >= LLIMIT) length = LLIMIT - 1;
|
||||||
lengthList[length]++;
|
lengthList[length]++;
|
||||||
if (length >= MINMATCHLENGTH) start--;
|
if (length >= MINMATCHLENGTH) start--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* largest useful length */
|
/* largest useful length */
|
||||||
memset(cumulLength, 0, sizeof(cumulLength));
|
memset(cumulLength, 0, sizeof(cumulLength));
|
||||||
@@ -570,7 +569,7 @@ static void ZDICT_countEStats(EStats_ress_t esr, ZSTD_parameters params,
|
|||||||
if (ZSTD_isError(errorCode)) { DISPLAYLEVEL(1, "warning : ZSTD_copyCCtx failed \n"); return; }
|
if (ZSTD_isError(errorCode)) { DISPLAYLEVEL(1, "warning : ZSTD_copyCCtx failed \n"); return; }
|
||||||
}
|
}
|
||||||
cSize = ZSTD_compressBlock(esr.zc, esr.workPlace, ZSTD_BLOCKSIZE_ABSOLUTEMAX, src, srcSize);
|
cSize = ZSTD_compressBlock(esr.zc, esr.workPlace, ZSTD_BLOCKSIZE_ABSOLUTEMAX, src, srcSize);
|
||||||
if (ZSTD_isError(cSize)) { DISPLAYLEVEL(1, "warning : could not compress sample size %u \n", (U32)srcSize); return; }
|
if (ZSTD_isError(cSize)) { DISPLAYLEVEL(3, "warning : could not compress sample size %u \n", (U32)srcSize); return; }
|
||||||
|
|
||||||
if (cSize) { /* if == 0; block is not compressible */
|
if (cSize) { /* if == 0; block is not compressible */
|
||||||
const seqStore_t* seqStorePtr = ZSTD_getSeqStore(esr.zc);
|
const seqStore_t* seqStorePtr = ZSTD_getSeqStore(esr.zc);
|
||||||
@@ -825,6 +824,55 @@ _cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
|
||||||
|
const void* customDictContent, size_t dictContentSize,
|
||||||
|
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
||||||
|
ZDICT_params_t params)
|
||||||
|
{
|
||||||
|
size_t hSize;
|
||||||
|
#define HBUFFSIZE 256
|
||||||
|
BYTE header[HBUFFSIZE];
|
||||||
|
int const compressionLevel = (params.compressionLevel <= 0) ? g_compressionLevel_default : params.compressionLevel;
|
||||||
|
U32 const notificationLevel = params.notificationLevel;
|
||||||
|
|
||||||
|
/* check conditions */
|
||||||
|
if (dictBufferCapacity < dictContentSize) return ERROR(dstSize_tooSmall);
|
||||||
|
if (dictContentSize < ZDICT_CONTENTSIZE_MIN) return ERROR(srcSize_wrong);
|
||||||
|
if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) return ERROR(dstSize_tooSmall);
|
||||||
|
|
||||||
|
/* dictionary header */
|
||||||
|
MEM_writeLE32(header, ZSTD_DICT_MAGIC);
|
||||||
|
{ U64 const randomID = XXH64(customDictContent, dictContentSize, 0);
|
||||||
|
U32 const compliantID = (randomID % ((1U<<31)-32768)) + 32768;
|
||||||
|
U32 const dictID = params.dictID ? params.dictID : compliantID;
|
||||||
|
MEM_writeLE32(header+4, dictID);
|
||||||
|
}
|
||||||
|
hSize = 8;
|
||||||
|
|
||||||
|
/* entropy tables */
|
||||||
|
DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */
|
||||||
|
DISPLAYLEVEL(2, "statistics ... \n");
|
||||||
|
{ size_t const eSize = ZDICT_analyzeEntropy(header+hSize, HBUFFSIZE-hSize,
|
||||||
|
compressionLevel,
|
||||||
|
samplesBuffer, samplesSizes, nbSamples,
|
||||||
|
customDictContent, dictContentSize,
|
||||||
|
notificationLevel);
|
||||||
|
if (ZDICT_isError(eSize)) return eSize;
|
||||||
|
hSize += eSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy elements in final buffer ; note : src and dst buffer can overlap */
|
||||||
|
if (hSize + dictContentSize > dictBufferCapacity) dictContentSize = dictBufferCapacity - hSize;
|
||||||
|
{ size_t const dictSize = hSize + dictContentSize;
|
||||||
|
char* dictEnd = (char*)dictBuffer + dictSize;
|
||||||
|
memmove(dictEnd - dictContentSize, customDictContent, dictContentSize);
|
||||||
|
memcpy(dictBuffer, header, hSize);
|
||||||
|
return dictSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t ZDICT_addEntropyTablesFromBuffer_advanced(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity,
|
size_t ZDICT_addEntropyTablesFromBuffer_advanced(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity,
|
||||||
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
||||||
ZDICT_params_t params)
|
ZDICT_params_t params)
|
||||||
|
|||||||
+112
-22
@@ -19,15 +19,18 @@ extern "C" {
|
|||||||
#include <stddef.h> /* size_t */
|
#include <stddef.h> /* size_t */
|
||||||
|
|
||||||
|
|
||||||
/*====== Export for Windows ======*/
|
/* ===== ZDICTLIB_API : control library symbols visibility ===== */
|
||||||
/*!
|
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
* ZSTD_DLL_EXPORT :
|
# define ZDICTLIB_VISIBILITY __attribute__ ((visibility ("default")))
|
||||||
* Enable exporting of functions when building a Windows DLL
|
|
||||||
*/
|
|
||||||
#if defined(_WIN32) && defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
|
||||||
# define ZDICTLIB_API __declspec(dllexport)
|
|
||||||
#else
|
#else
|
||||||
# define ZDICTLIB_API
|
# define ZDICTLIB_VISIBILITY
|
||||||
|
#endif
|
||||||
|
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||||
|
# define ZDICTLIB_API __declspec(dllexport) ZDICTLIB_VISIBILITY
|
||||||
|
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||||
|
# define ZDICTLIB_API __declspec(dllimport) ZDICTLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||||
|
#else
|
||||||
|
# define ZDICTLIB_API ZDICTLIB_VISIBILITY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -79,27 +82,114 @@ typedef struct {
|
|||||||
or an error code, which can be tested by ZDICT_isError().
|
or an error code, which can be tested by ZDICT_isError().
|
||||||
note : ZDICT_trainFromBuffer_advanced() will send notifications into stderr if instructed to, using notificationLevel>0.
|
note : ZDICT_trainFromBuffer_advanced() will send notifications into stderr if instructed to, using notificationLevel>0.
|
||||||
*/
|
*/
|
||||||
size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dictBufferCapacity,
|
ZDICTLIB_API size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dictBufferCapacity,
|
||||||
|
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
||||||
|
ZDICT_params_t parameters);
|
||||||
|
|
||||||
|
/*! COVER_params_t :
|
||||||
|
For all values 0 means default.
|
||||||
|
kMin and d are the only required parameters.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
unsigned k; /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */
|
||||||
|
unsigned d; /* dmer size : constraint: 0 < d <= k : Reasonable range [6, 16] */
|
||||||
|
unsigned steps; /* Number of steps : Only used for optimization : 0 means default (32) : Higher means more parameters checked */
|
||||||
|
|
||||||
|
unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */
|
||||||
|
unsigned notificationLevel; /* Write to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */
|
||||||
|
unsigned dictID; /* 0 means auto mode (32-bits random value); other : force dictID value */
|
||||||
|
int compressionLevel; /* 0 means default; target a specific zstd compression level */
|
||||||
|
} COVER_params_t;
|
||||||
|
|
||||||
|
|
||||||
|
/*! COVER_trainFromBuffer() :
|
||||||
|
Train a dictionary from an array of samples using the COVER algorithm.
|
||||||
|
Samples must be stored concatenated in a single flat buffer `samplesBuffer`,
|
||||||
|
supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order.
|
||||||
|
The resulting dictionary will be saved into `dictBuffer`.
|
||||||
|
@return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||||
|
or an error code, which can be tested with ZDICT_isError().
|
||||||
|
Note : COVER_trainFromBuffer() requires about 9 bytes of memory for each input byte.
|
||||||
|
Tips : In general, a reasonable dictionary has a size of ~ 100 KB.
|
||||||
|
It's obviously possible to target smaller or larger ones, just by specifying different `dictBufferCapacity`.
|
||||||
|
In general, it's recommended to provide a few thousands samples, but this can vary a lot.
|
||||||
|
It's recommended that total size of all samples be about ~x100 times the target size of dictionary.
|
||||||
|
*/
|
||||||
|
ZDICTLIB_API size_t COVER_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,
|
||||||
|
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
||||||
|
COVER_params_t parameters);
|
||||||
|
|
||||||
|
/*! COVER_optimizeTrainFromBuffer() :
|
||||||
|
The same requirements as above hold for all the parameters except `parameters`.
|
||||||
|
This function tries many parameter combinations and picks the best parameters.
|
||||||
|
`*parameters` is filled with the best parameters found, and the dictionary
|
||||||
|
constructed with those parameters is stored in `dictBuffer`.
|
||||||
|
|
||||||
|
All of the parameters d, k, steps are optional.
|
||||||
|
If d is non-zero then we don't check multiple values of d, otherwise we check d = {6, 8, 10, 12, 14, 16}.
|
||||||
|
if steps is zero it defaults to its default value.
|
||||||
|
If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [16, 2048].
|
||||||
|
|
||||||
|
@return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
|
||||||
|
or an error code, which can be tested with ZDICT_isError().
|
||||||
|
On success `*parameters` contains the parameters selected.
|
||||||
|
Note : COVER_optimizeTrainFromBuffer() 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 COVER_optimizeTrainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,
|
||||||
|
const void* samplesBuffer, const size_t *samplesSizes, unsigned nbSamples,
|
||||||
|
COVER_params_t *parameters);
|
||||||
|
|
||||||
|
/*! ZDICT_finalizeDictionary() :
|
||||||
|
|
||||||
|
Given a custom content as a basis for dictionary, and a set of samples,
|
||||||
|
finalize dictionary by adding headers and statistics.
|
||||||
|
|
||||||
|
Samples must be stored concatenated in a flat buffer `samplesBuffer`,
|
||||||
|
supplied with an array of sizes `samplesSizes`, providing the size of each sample in order.
|
||||||
|
|
||||||
|
dictContentSize must be > ZDICT_CONTENTSIZE_MIN bytes.
|
||||||
|
maxDictSize must be >= dictContentSize, and must be > ZDICT_DICTSIZE_MIN bytes.
|
||||||
|
|
||||||
|
@return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`),
|
||||||
|
or an error code, which can be tested by ZDICT_isError().
|
||||||
|
note : ZDICT_finalizeDictionary() will push notifications into stderr if instructed to, using notificationLevel>0.
|
||||||
|
note 2 : dictBuffer and customDictContent can overlap
|
||||||
|
*/
|
||||||
|
#define ZDICT_CONTENTSIZE_MIN 256
|
||||||
|
#define ZDICT_DICTSIZE_MIN 512
|
||||||
|
ZDICTLIB_API size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
|
||||||
|
const void* customDictContent, size_t dictContentSize,
|
||||||
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
||||||
ZDICT_params_t parameters);
|
ZDICT_params_t parameters);
|
||||||
|
|
||||||
|
|
||||||
/*! ZDICT_addEntropyTablesFromBuffer() :
|
|
||||||
|
|
||||||
Given a content-only dictionary (built using any 3rd party algorithm),
|
/* Deprecation warnings */
|
||||||
add entropy tables computed from an array of samples.
|
/* It is generally possible to disable deprecation warnings from compiler,
|
||||||
Samples must be stored concatenated in a flat buffer `samplesBuffer`,
|
for example with -Wno-deprecated-declarations for gcc
|
||||||
supplied with an array of sizes `samplesSizes`, providing the size of each sample in order.
|
or _CRT_SECURE_NO_WARNINGS in Visual.
|
||||||
|
Otherwise, it's also possible to manually define ZDICT_DISABLE_DEPRECATE_WARNINGS */
|
||||||
|
#ifdef ZDICT_DISABLE_DEPRECATE_WARNINGS
|
||||||
|
# define ZDICT_DEPRECATED(message) ZDICTLIB_API /* disable deprecation warnings */
|
||||||
|
#else
|
||||||
|
# define ZDICT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||||
|
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
||||||
|
# define ZDICT_DEPRECATED(message) ZDICTLIB_API [[deprecated(message)]]
|
||||||
|
# elif (ZDICT_GCC_VERSION >= 405) || defined(__clang__)
|
||||||
|
# define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated(message)))
|
||||||
|
# elif (ZDICT_GCC_VERSION >= 301)
|
||||||
|
# define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated))
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
# define ZDICT_DEPRECATED(message) ZDICTLIB_API __declspec(deprecated(message))
|
||||||
|
# else
|
||||||
|
# pragma message("WARNING: You need to implement ZDICT_DEPRECATED for this compiler")
|
||||||
|
# define ZDICT_DEPRECATED(message) ZDICTLIB_API
|
||||||
|
# endif
|
||||||
|
#endif /* ZDICT_DISABLE_DEPRECATE_WARNINGS */
|
||||||
|
|
||||||
The input dictionary content must be stored *at the end* of `dictBuffer`.
|
ZDICT_DEPRECATED("use ZDICT_finalizeDictionary() instead")
|
||||||
Its size is `dictContentSize`.
|
|
||||||
The resulting dictionary with added entropy tables will be *written back to `dictBuffer`*,
|
|
||||||
starting from its beginning.
|
|
||||||
@return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`).
|
|
||||||
*/
|
|
||||||
size_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity,
|
size_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity,
|
||||||
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples);
|
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* ZDICT_STATIC_LINKING_ONLY */
|
#endif /* ZDICT_STATIC_LINKING_ONLY */
|
||||||
|
|||||||
@@ -100,6 +100,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)..\dll;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)..\dll;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@@ -141,6 +142,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)..\dll;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)..\dll;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
|||||||
+13
-19
@@ -3012,21 +3012,19 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
|||||||
/* Literal length */
|
/* Literal length */
|
||||||
litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));
|
litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));
|
||||||
prevOffset = litLength ? seq->offset : seqState->prevOffset;
|
prevOffset = litLength ? seq->offset : seqState->prevOffset;
|
||||||
if (litLength == MaxLL)
|
if (litLength == MaxLL) {
|
||||||
{
|
|
||||||
U32 add = *dumps++;
|
U32 add = *dumps++;
|
||||||
if (add < 255) litLength += add;
|
if (add < 255) litLength += add;
|
||||||
else
|
else {
|
||||||
{
|
litLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16);
|
||||||
litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
|
||||||
dumps += 3;
|
dumps += 3;
|
||||||
}
|
}
|
||||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
if (dumps > de) { litLength = MaxLL+255; } /* late correction, to avoid using uninitialized memory */
|
||||||
|
if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Offset */
|
/* Offset */
|
||||||
{
|
{ static const U32 offsetPrefix[MaxOff+1] = {
|
||||||
static const U32 offsetPrefix[MaxOff+1] = {
|
|
||||||
1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,
|
1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,
|
||||||
512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,
|
512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,
|
||||||
524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };
|
524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };
|
||||||
@@ -3043,16 +3041,15 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
|
|||||||
|
|
||||||
/* MatchLength */
|
/* MatchLength */
|
||||||
matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
|
matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
|
||||||
if (matchLength == MaxML)
|
if (matchLength == MaxML) {
|
||||||
{
|
|
||||||
U32 add = *dumps++;
|
U32 add = *dumps++;
|
||||||
if (add < 255) matchLength += add;
|
if (add < 255) matchLength += add;
|
||||||
else
|
else {
|
||||||
{
|
matchLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16);
|
||||||
matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
|
||||||
dumps += 3;
|
dumps += 3;
|
||||||
}
|
}
|
||||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
if (dumps > de) { matchLength = MaxML+255; } /* late correction, to avoid using uninitialized memory */
|
||||||
|
if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||||
}
|
}
|
||||||
matchLength += MINMATCH;
|
matchLength += MINMATCH;
|
||||||
|
|
||||||
@@ -3116,8 +3113,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
|||||||
/* Requirement: op <= oend_8 */
|
/* Requirement: op <= oend_8 */
|
||||||
|
|
||||||
/* match within prefix */
|
/* match within prefix */
|
||||||
if (sequence.offset < 8)
|
if (sequence.offset < 8) {
|
||||||
{
|
|
||||||
/* close range match, overlap */
|
/* close range match, overlap */
|
||||||
const int sub2 = dec64table[sequence.offset];
|
const int sub2 = dec64table[sequence.offset];
|
||||||
op[0] = match[0];
|
op[0] = match[0];
|
||||||
@@ -3127,9 +3123,7 @@ static size_t ZSTD_execSequence(BYTE* op,
|
|||||||
match += dec32table[sequence.offset];
|
match += dec32table[sequence.offset];
|
||||||
ZSTD_copy4(op+4, match);
|
ZSTD_copy4(op+4, match);
|
||||||
match -= sub2;
|
match -= sub2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ZSTD_copy8(op, match);
|
ZSTD_copy8(op, match);
|
||||||
}
|
}
|
||||||
op += 8; match += 8;
|
op += 8; match += 8;
|
||||||
|
|||||||
@@ -3230,7 +3230,8 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)
|
|||||||
if (litLength&1) litLength>>=1, dumps += 3;
|
if (litLength&1) litLength>>=1, dumps += 3;
|
||||||
else litLength = (U16)(litLength)>>1, dumps += 2;
|
else litLength = (U16)(litLength)>>1, dumps += 2;
|
||||||
}
|
}
|
||||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
if (dumps > de) { litLength = MaxLL+255; } /* late correction, to avoid using uninitialized memory */
|
||||||
|
if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Offset */
|
/* Offset */
|
||||||
@@ -3263,7 +3264,8 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)
|
|||||||
if (matchLength&1) matchLength>>=1, dumps += 3;
|
if (matchLength&1) matchLength>>=1, dumps += 3;
|
||||||
else matchLength = (U16)(matchLength)>>1, dumps += 2;
|
else matchLength = (U16)(matchLength)>>1, dumps += 2;
|
||||||
}
|
}
|
||||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
if (dumps > de) { matchLength = MaxML+255; } /* late correction, to avoid using uninitialized memory */
|
||||||
|
if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||||
}
|
}
|
||||||
matchLength += MINMATCH;
|
matchLength += MINMATCH;
|
||||||
|
|
||||||
|
|||||||
@@ -4134,9 +4134,9 @@ static size_t ZSTDv07_loadEntropy(ZSTDv07_DCtx* dctx, const void* const dict, si
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
||||||
dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
|
dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
|
||||||
dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
|
dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
|
||||||
dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
|
dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
|
||||||
dictPtr += 12;
|
dictPtr += 12;
|
||||||
|
|
||||||
dctx->litEntropy = dctx->fseEntropy = 1;
|
dctx->litEntropy = dctx->fseEntropy = 1;
|
||||||
|
|||||||
+54
-26
@@ -20,13 +20,16 @@ extern "C" {
|
|||||||
|
|
||||||
/* ===== ZSTDLIB_API : control library symbols visibility ===== */
|
/* ===== ZSTDLIB_API : control library symbols visibility ===== */
|
||||||
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
# define ZSTDLIB_API __attribute__ ((visibility ("default")))
|
# define ZSTDLIB_VISIBILITY __attribute__ ((visibility ("default")))
|
||||||
#elif defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
|
||||||
# define ZSTDLIB_API __declspec(dllexport)
|
|
||||||
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
|
||||||
# define ZSTDLIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
|
||||||
#else
|
#else
|
||||||
# define ZSTDLIB_API
|
# define ZSTDLIB_VISIBILITY
|
||||||
|
#endif
|
||||||
|
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||||
|
# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBILITY
|
||||||
|
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||||
|
# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||||
|
#else
|
||||||
|
# define ZSTDLIB_API ZSTDLIB_VISIBILITY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -53,7 +56,7 @@ extern "C" {
|
|||||||
/*------ Version ------*/
|
/*------ Version ------*/
|
||||||
#define ZSTD_VERSION_MAJOR 1
|
#define ZSTD_VERSION_MAJOR 1
|
||||||
#define ZSTD_VERSION_MINOR 1
|
#define ZSTD_VERSION_MINOR 1
|
||||||
#define ZSTD_VERSION_RELEASE 2
|
#define ZSTD_VERSION_RELEASE 3
|
||||||
|
|
||||||
#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
|
#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
|
||||||
#define ZSTD_QUOTE(str) #str
|
#define ZSTD_QUOTE(str) #str
|
||||||
@@ -170,8 +173,8 @@ typedef struct ZSTD_CDict_s ZSTD_CDict;
|
|||||||
* When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once.
|
* When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once.
|
||||||
* ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.
|
* ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.
|
||||||
* ZSTD_CDict can be created once and used by multiple threads concurrently, as its usage is read-only.
|
* ZSTD_CDict can be created once and used by multiple threads concurrently, as its usage is read-only.
|
||||||
* `dict` can be released after ZSTD_CDict creation. */
|
* `dictBuffer` can be released after ZSTD_CDict creation, as its content is copied within CDict */
|
||||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel);
|
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||||
|
|
||||||
/*! ZSTD_freeCDict() :
|
/*! ZSTD_freeCDict() :
|
||||||
* Function frees memory allocated by ZSTD_createCDict(). */
|
* Function frees memory allocated by ZSTD_createCDict(). */
|
||||||
@@ -191,8 +194,8 @@ typedef struct ZSTD_DDict_s ZSTD_DDict;
|
|||||||
|
|
||||||
/*! ZSTD_createDDict() :
|
/*! ZSTD_createDDict() :
|
||||||
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||||
* `dict` can be released after creation. */
|
* dictBuffer can be released after DDict creation, as its content is copied inside DDict */
|
||||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize);
|
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
|
||||||
|
|
||||||
/*! ZSTD_freeDDict() :
|
/*! ZSTD_freeDDict() :
|
||||||
* Function frees memory allocated with ZSTD_createDDict() */
|
* Function frees memory allocated with ZSTD_createDDict() */
|
||||||
@@ -325,7 +328,7 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output
|
|||||||
* ***************************************************************************************/
|
* ***************************************************************************************/
|
||||||
|
|
||||||
/* --- Constants ---*/
|
/* --- Constants ---*/
|
||||||
#define ZSTD_MAGICNUMBER 0xFD2FB528 /* v0.8 */
|
#define ZSTD_MAGICNUMBER 0xFD2FB528 /* >= v0.8.0 */
|
||||||
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U
|
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U
|
||||||
|
|
||||||
#define ZSTD_WINDOWLOG_MAX_32 25
|
#define ZSTD_WINDOWLOG_MAX_32 25
|
||||||
@@ -345,8 +348,9 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output
|
|||||||
#define ZSTD_TARGETLENGTH_MAX 999
|
#define ZSTD_TARGETLENGTH_MAX 999
|
||||||
|
|
||||||
#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* for static allocation */
|
#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* for static allocation */
|
||||||
|
#define ZSTD_FRAMEHEADERSIZE_MIN 6
|
||||||
static const size_t ZSTD_frameHeaderSize_prefix = 5;
|
static const size_t ZSTD_frameHeaderSize_prefix = 5;
|
||||||
static const size_t ZSTD_frameHeaderSize_min = 6;
|
static const size_t ZSTD_frameHeaderSize_min = ZSTD_FRAMEHEADERSIZE_MIN;
|
||||||
static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX;
|
static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX;
|
||||||
static const size_t ZSTD_skippableHeaderSize = 8; /* magic number + skippable frame length */
|
static const size_t ZSTD_skippableHeaderSize = 8; /* magic number + skippable frame length */
|
||||||
|
|
||||||
@@ -365,9 +369,9 @@ typedef struct {
|
|||||||
} ZSTD_compressionParameters;
|
} ZSTD_compressionParameters;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned contentSizeFlag; /**< 1: content size will be in frame header (if known). */
|
unsigned contentSizeFlag; /**< 1: content size will be in frame header (when known) */
|
||||||
unsigned checksumFlag; /**< 1: will generate a 22-bits checksum at end of frame, to be used for error detection by decompressor */
|
unsigned checksumFlag; /**< 1: generate a 32-bits checksum at end of frame, for error detection */
|
||||||
unsigned noDictIDFlag; /**< 1: no dict ID will be saved into frame header (if dictionary compression) */
|
unsigned noDictIDFlag; /**< 1: no dictID will be saved into frame header (if dictionary compression) */
|
||||||
} ZSTD_frameParameters;
|
} ZSTD_frameParameters;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -397,9 +401,23 @@ ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
|
|||||||
* Gives the amount of memory used by a given ZSTD_CCtx */
|
* Gives the amount of memory used by a given ZSTD_CCtx */
|
||||||
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
|
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ZSTD_p_forceWindow /* Force back-references to remain < windowSize, even when referencing Dictionary content (default:0)*/
|
||||||
|
} ZSTD_CCtxParameter;
|
||||||
|
/*! ZSTD_setCCtxParameter() :
|
||||||
|
* Set advanced parameters, selected through enum ZSTD_CCtxParameter
|
||||||
|
* @result : 0, or an error code (which can be tested with ZSTD_isError()) */
|
||||||
|
ZSTDLIB_API size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value);
|
||||||
|
|
||||||
|
/*! ZSTD_createCDict_byReference() :
|
||||||
|
* Create a digested dictionary for compression
|
||||||
|
* Dictionary content is simply referenced, and therefore stays in dictBuffer.
|
||||||
|
* It is important that dictBuffer outlives CDict, it must remain read accessible throughout the lifetime of CDict */
|
||||||
|
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||||
|
|
||||||
/*! ZSTD_createCDict_advanced() :
|
/*! ZSTD_createCDict_advanced() :
|
||||||
* Create a ZSTD_CDict using external alloc and free, and customized compression parameters */
|
* Create a ZSTD_CDict using external alloc and free, and customized compression parameters */
|
||||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
|
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, unsigned byReference,
|
||||||
ZSTD_parameters params, ZSTD_customMem customMem);
|
ZSTD_parameters params, ZSTD_customMem customMem);
|
||||||
|
|
||||||
/*! ZSTD_sizeof_CDict() :
|
/*! ZSTD_sizeof_CDict() :
|
||||||
@@ -455,6 +473,15 @@ ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
|
|||||||
* Gives the amount of memory used by a given ZSTD_DCtx */
|
* Gives the amount of memory used by a given ZSTD_DCtx */
|
||||||
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
|
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
|
||||||
|
|
||||||
|
/*! ZSTD_createDDict_byReference() :
|
||||||
|
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||||
|
* Dictionary content is simply referenced, and therefore stays in dictBuffer.
|
||||||
|
* It is important that dictBuffer outlives DDict, it must remain read accessible throughout the lifetime of DDict */
|
||||||
|
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
|
||||||
|
|
||||||
|
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
|
||||||
|
unsigned byReference, ZSTD_customMem customMem);
|
||||||
|
|
||||||
/*! ZSTD_sizeof_DDict() :
|
/*! ZSTD_sizeof_DDict() :
|
||||||
* Gives the amount of memory used by a given ZSTD_DDict */
|
* Gives the amount of memory used by a given ZSTD_DDict */
|
||||||
ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||||
@@ -463,13 +490,13 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
|||||||
* Provides the dictID stored within dictionary.
|
* Provides the dictID stored within dictionary.
|
||||||
* if @return == 0, the dictionary is not conformant with Zstandard specification.
|
* if @return == 0, the dictionary is not conformant with Zstandard specification.
|
||||||
* It can still be loaded, but as a content-only dictionary. */
|
* It can still be loaded, but as a content-only dictionary. */
|
||||||
unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
|
ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
|
||||||
|
|
||||||
/*! ZSTD_getDictID_fromDDict() :
|
/*! ZSTD_getDictID_fromDDict() :
|
||||||
* Provides the dictID of the dictionary loaded into `ddict`.
|
* Provides the dictID of the dictionary loaded into `ddict`.
|
||||||
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
||||||
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
||||||
unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
||||||
|
|
||||||
/*! ZSTD_getDictID_fromFrame() :
|
/*! ZSTD_getDictID_fromFrame() :
|
||||||
* Provides the dictID required to decompressed the frame stored within `src`.
|
* Provides the dictID required to decompressed the frame stored within `src`.
|
||||||
@@ -481,7 +508,7 @@ unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
|||||||
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
|
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
|
||||||
* - This is not a Zstandard frame.
|
* - This is not a Zstandard frame.
|
||||||
* When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
|
* When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
|
||||||
unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
@@ -491,7 +518,7 @@ unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
|||||||
/*===== Advanced Streaming compression functions =====*/
|
/*===== Advanced Streaming compression functions =====*/
|
||||||
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
|
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
|
||||||
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct */
|
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct */
|
||||||
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel);
|
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */
|
||||||
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
|
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
|
||||||
ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be zero == unknown */
|
ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be zero == unknown */
|
||||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */
|
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */
|
||||||
@@ -500,9 +527,9 @@ ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
|
|||||||
|
|
||||||
|
|
||||||
/*===== Advanced Streaming decompression functions =====*/
|
/*===== Advanced Streaming decompression functions =====*/
|
||||||
typedef enum { ZSTDdsp_maxWindowSize } ZSTD_DStreamParameter_e;
|
typedef enum { DStream_p_maxWindowSize } ZSTD_DStreamParameter_e;
|
||||||
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
|
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
|
||||||
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
|
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */
|
||||||
ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue);
|
ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue);
|
||||||
ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict will just be referenced, and must outlive decompression session */
|
ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict will just be referenced, and must outlive decompression session */
|
||||||
ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */
|
ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */
|
||||||
@@ -542,10 +569,10 @@ ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
|
|||||||
In which case, it will "discard" the relevant memory section from its history.
|
In which case, it will "discard" the relevant memory section from its history.
|
||||||
|
|
||||||
Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.
|
Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.
|
||||||
It's possible to use a NULL,0 src content, in which case, it will write a final empty block to end the frame,
|
It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.
|
||||||
Without last block mark, frames will be considered unfinished (broken) by decoders.
|
Without last block mark, frames will be considered unfinished (corrupted) by decoders.
|
||||||
|
|
||||||
You can then reuse `ZSTD_CCtx` (ZSTD_compressBegin()) to compress some new frame.
|
`ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress some new frame.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*===== Buffer-less streaming compression functions =====*/
|
/*===== Buffer-less streaming compression functions =====*/
|
||||||
@@ -553,6 +580,7 @@ ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
|
|||||||
ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
|
ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
|
||||||
ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize);
|
ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize);
|
||||||
ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize);
|
ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize);
|
||||||
|
ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize);
|
||||||
ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||||
ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ zstd-decompress
|
|||||||
*.o
|
*.o
|
||||||
*.ko
|
*.ko
|
||||||
default.profraw
|
default.profraw
|
||||||
|
have_zlib
|
||||||
|
|
||||||
# Executables
|
# Executables
|
||||||
*.exe
|
*.exe
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
cxx_binary(
|
||||||
|
name='zstd',
|
||||||
|
headers=glob(['*.h'], excludes=['datagen.h', 'platform.h', 'util.h']),
|
||||||
|
srcs=glob(['*.c'], excludes=['datagen.c']),
|
||||||
|
deps=[
|
||||||
|
':datagen',
|
||||||
|
':util',
|
||||||
|
'//lib:zstd',
|
||||||
|
'//lib:zdict',
|
||||||
|
'//lib:mem',
|
||||||
|
'//lib:xxhash',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_binary(
|
||||||
|
name='zstdmt',
|
||||||
|
headers=glob(['*.h'], excludes=['datagen.h', 'platform.h', 'util.h']),
|
||||||
|
srcs=glob(['*.c'], excludes=['datagen.c']),
|
||||||
|
deps=[
|
||||||
|
':datagen',
|
||||||
|
':util',
|
||||||
|
'//lib:zstd',
|
||||||
|
'//lib:zdict',
|
||||||
|
'//lib:mem',
|
||||||
|
'//lib:xxhash',
|
||||||
|
],
|
||||||
|
preprocessor_flags=['-DZSTD_MULTITHREAD'],
|
||||||
|
linker_flags=['-lpthread'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_binary(
|
||||||
|
name='gzstd',
|
||||||
|
headers=glob(['*.h'], excludes=['datagen.h', 'platform.h', 'util.h']),
|
||||||
|
srcs=glob(['*.c'], excludes=['datagen.c']),
|
||||||
|
deps=[
|
||||||
|
':datagen',
|
||||||
|
':util',
|
||||||
|
'//lib:zstd',
|
||||||
|
'//lib:zdict',
|
||||||
|
'//lib:mem',
|
||||||
|
'//lib:xxhash',
|
||||||
|
],
|
||||||
|
preprocessor_flags=['-DZSTD_GZDECOMPRESS'],
|
||||||
|
linker_flags=['-lz'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='datagen',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='',
|
||||||
|
exported_headers=['datagen.h'],
|
||||||
|
srcs=['datagen.c'],
|
||||||
|
deps=['//lib:mem'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='util',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
header_namespace='',
|
||||||
|
exported_headers=['util.h', 'platform.h'],
|
||||||
|
deps=['//lib:mem'],
|
||||||
|
)
|
||||||
+79
-49
@@ -1,7 +1,9 @@
|
|||||||
# ##########################################################################
|
# ##########################################################################
|
||||||
# Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
# Copyright (c) 2015-present, Yann Collet, Facebook, Inc.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
# This Makefile is validated for Linux, macOS, *BSD, Hurd, Solaris, MSYS2 targets
|
||||||
|
#
|
||||||
# This source code is licensed under the BSD-style license found in the
|
# This source code is licensed under the BSD-style license found in the
|
||||||
# LICENSE file in the root directory of this source tree. An additional grant
|
# LICENSE file in the root directory of this source tree. An additional grant
|
||||||
# of patent rights can be found in the PATENTS file in the same directory.
|
# of patent rights can be found in the PATENTS file in the same directory.
|
||||||
@@ -14,11 +16,6 @@
|
|||||||
# zstd-decompress : decompressor-only version of zstd
|
# zstd-decompress : decompressor-only version of zstd
|
||||||
# ##########################################################################
|
# ##########################################################################
|
||||||
|
|
||||||
DESTDIR?=
|
|
||||||
PREFIX ?= /usr/local
|
|
||||||
BINDIR = $(PREFIX)/bin
|
|
||||||
MANDIR = $(PREFIX)/share/man/man1
|
|
||||||
|
|
||||||
ZSTDDIR = ../lib
|
ZSTDDIR = ../lib
|
||||||
|
|
||||||
ifeq ($(shell $(CC) -v 2>&1 | grep -c "gcc version "), 1)
|
ifeq ($(shell $(CC) -v 2>&1 | grep -c "gcc version "), 1)
|
||||||
@@ -27,24 +24,23 @@ else
|
|||||||
ALIGN_LOOP =
|
ALIGN_LOOP =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/dictBuilder
|
CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress -I$(ZSTDDIR)/dictBuilder
|
||||||
CFLAGS ?= -O3
|
CFLAGS ?= -O3
|
||||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 \
|
DEBUGFLAGS = -g -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||||
-Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wundef \
|
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||||
-Wpointer-arith
|
-Wstrict-prototypes -Wundef -Wpointer-arith
|
||||||
CFLAGS += $(MOREFLAGS)
|
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||||
FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||||
|
|
||||||
|
|
||||||
ZSTDCOMMON_FILES := $(ZSTDDIR)/common/*.c
|
ZSTDCOMMON_FILES := $(ZSTDDIR)/common/*.c
|
||||||
ZSTDCOMP_FILES := $(ZSTDDIR)/compress/zstd_compress.c $(ZSTDDIR)/compress/fse_compress.c $(ZSTDDIR)/compress/huf_compress.c
|
ZSTDCOMP_FILES := $(ZSTDDIR)/compress/*.c
|
||||||
ZSTDDECOMP_FILES := $(ZSTDDIR)/decompress/huf_decompress.c
|
ZSTDDECOMP_FILES := $(ZSTDDIR)/decompress/*.c
|
||||||
ZSTD_FILES := $(ZSTDDECOMP_FILES) $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES)
|
ZSTD_FILES := $(ZSTDDECOMP_FILES) $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES)
|
||||||
ZDICT_FILES := $(ZSTDDIR)/dictBuilder/*.c
|
ZDICT_FILES := $(ZSTDDIR)/dictBuilder/*.c
|
||||||
ZSTDDECOMP_O = $(ZSTDDIR)/decompress/zstd_decompress.o
|
ZSTDDECOMP_O = $(ZSTDDIR)/decompress/zstd_decompress.o
|
||||||
|
|
||||||
ifeq ($(ZSTD_LEGACY_SUPPORT), 0)
|
ifeq ($(ZSTD_LEGACY_SUPPORT), 0)
|
||||||
CPPFLAGS += -DZSTD_LEGACY_SUPPORT=0
|
|
||||||
ZSTDLEGACY_FILES:=
|
ZSTDLEGACY_FILES:=
|
||||||
else
|
else
|
||||||
ZSTD_LEGACY_SUPPORT:=1
|
ZSTD_LEGACY_SUPPORT:=1
|
||||||
@@ -52,6 +48,8 @@ CPPFLAGS += -I$(ZSTDDIR)/legacy
|
|||||||
ZSTDLEGACY_FILES:= $(ZSTDDIR)/legacy/*.c
|
ZSTDLEGACY_FILES:= $(ZSTDDIR)/legacy/*.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ZSTDLIB_FILES := $(wildcard $(ZSTD_FILES)) $(wildcard $(ZSTDLEGACY_FILES)) $(wildcard $(ZDICT_FILES))
|
||||||
|
ZSTDLIB_OBJ := $(patsubst %.c,%.o,$(ZSTDLIB_FILES))
|
||||||
|
|
||||||
# Define *.exe as extension for Windows systems
|
# Define *.exe as extension for Windows systems
|
||||||
ifneq (,$(filter Windows%,$(OS)))
|
ifneq (,$(filter Windows%,$(OS)))
|
||||||
@@ -67,27 +65,46 @@ else
|
|||||||
EXT =
|
EXT =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# zlib detection
|
||||||
|
VOID = /dev/null
|
||||||
|
HAVE_ZLIB := $(shell echo "int main(){}" | $(CC) -o $(VOID) -x c - -lz 2> $(VOID) && echo 1 || echo 0)
|
||||||
|
ifeq ($(HAVE_ZLIB), 1)
|
||||||
|
ZLIBCPP = -DZSTD_GZDECOMPRESS
|
||||||
|
ZLIBLD = -lz
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: default all clean clean_decomp_o install uninstall generate_res
|
.PHONY: default all clean clean_decomp_o install uninstall generate_res
|
||||||
|
|
||||||
default: zstd
|
default: zstd-release
|
||||||
|
|
||||||
all: zstd
|
all: zstd
|
||||||
|
|
||||||
$(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP)
|
$(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP)
|
||||||
|
|
||||||
zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
zstd-internal : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
||||||
zstd : $(ZSTDDECOMP_O) $(ZSTD_FILES) $(ZSTDLEGACY_FILES) $(ZDICT_FILES) \
|
zstd-internal : $(ZSTDLIB_OBJ) zstdcli.o fileio.o bench.o datagen.o dibio.o
|
||||||
zstdcli.c fileio.c bench.c datagen.c dibio.c
|
ifeq ($(HAVE_ZLIB), 1)
|
||||||
|
@echo "==> building zstd with .gz decompression support "
|
||||||
|
else
|
||||||
|
@echo "==> no zlib, building zstd with .zst support only (no .gz support) "
|
||||||
|
endif
|
||||||
ifneq (,$(filter Windows%,$(OS)))
|
ifneq (,$(filter Windows%,$(OS)))
|
||||||
windres/generate_res.bat
|
windres/generate_res.bat
|
||||||
endif
|
endif
|
||||||
$(CC) $(FLAGS) $^ $(RES_FILE) -o $@$(EXT) $(LDFLAGS)
|
$(CC) $(FLAGS) $^ $(RES_FILE) -o zstd$(EXT) $(LDFLAGS)
|
||||||
|
|
||||||
|
zstd-nogz : HAVE_ZLIB=0
|
||||||
|
zstd-nogz : zstd-internal
|
||||||
|
|
||||||
|
zstd : CPPFLAGS += $(ZLIBCPP)
|
||||||
|
zstd : LDFLAGS += $(ZLIBLD)
|
||||||
|
zstd : zstd-internal
|
||||||
|
|
||||||
|
zstd-release: DEBUGFLAGS :=
|
||||||
|
zstd-release: zstd
|
||||||
|
|
||||||
zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
||||||
zstd32 : $(ZSTDDIR)/decompress/zstd_decompress.c $(ZSTD_FILES) $(ZSTDLEGACY_FILES) $(ZDICT_FILES) \
|
zstd32 : $(ZSTDLIB_FILES) zstdcli.c fileio.c bench.c datagen.c dibio.c
|
||||||
zstdcli.c fileio.c bench.c datagen.c dibio.c
|
|
||||||
ifneq (,$(filter Windows%,$(OS)))
|
ifneq (,$(filter Windows%,$(OS)))
|
||||||
windres/generate_res.bat
|
windres/generate_res.bat
|
||||||
endif
|
endif
|
||||||
@@ -109,31 +126,23 @@ zstd-pgo : clean zstd
|
|||||||
$(RM) $(ZSTDDECOMP_O)
|
$(RM) $(ZSTDDECOMP_O)
|
||||||
$(MAKE) zstd MOREFLAGS=-fprofile-use
|
$(MAKE) zstd MOREFLAGS=-fprofile-use
|
||||||
|
|
||||||
zstd-frugal: $(ZSTDDECOMP_O) $(ZSTD_FILES) zstdcli.c fileio.c
|
zstd-frugal: $(ZSTD_FILES) zstdcli.c fileio.c
|
||||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o zstd$(EXT)
|
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o zstd$(EXT)
|
||||||
|
|
||||||
zstd-small: clean_decomp_o
|
zstd-small:
|
||||||
ZSTD_LEGACY_SUPPORT=0 CFLAGS="-Os -s" $(MAKE) zstd-frugal
|
CFLAGS="-Os -s" $(MAKE) zstd-frugal
|
||||||
|
|
||||||
zstd-decompress-clean: $(ZSTDDECOMP_O) $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c fileio.c
|
zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c fileio.c
|
||||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o zstd-decompress$(EXT)
|
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o $@$(EXT)
|
||||||
|
|
||||||
zstd-decompress: clean_decomp_o
|
|
||||||
ZSTD_LEGACY_SUPPORT=0 $(MAKE) zstd-decompress-clean
|
|
||||||
|
|
||||||
zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c fileio.c
|
zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c fileio.c
|
||||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT)
|
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT)
|
||||||
|
|
||||||
gzstd: clean_decomp_o
|
zstdmt: CPPFLAGS += -DZSTD_MULTITHREAD
|
||||||
@echo "int main(){}" | $(CC) -o have_zlib -x c - -lz && echo found zlib || echo did not found zlib
|
ifeq (,$(filter Windows%,$(OS)))
|
||||||
@if [ -s have_zlib ]; then \
|
zstdmt: LDFLAGS += -lpthread
|
||||||
echo building gzstd with .gz decompression support \
|
endif
|
||||||
&& rm have_zlib$(EXT) \
|
zstdmt: zstd
|
||||||
&& CPPFLAGS=-DZSTD_GZDECOMPRESS LDFLAGS="-lz" $(MAKE) zstd; \
|
|
||||||
else \
|
|
||||||
echo "WARNING : no zlib, building gzstd with only .zst files support : NO .gz SUPPORT !!!" \
|
|
||||||
&& $(MAKE) zstd; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
generate_res:
|
generate_res:
|
||||||
windres/generate_res.bat
|
windres/generate_res.bat
|
||||||
@@ -143,27 +152,48 @@ clean:
|
|||||||
@$(RM) $(ZSTDDIR)/decompress/*.o $(ZSTDDIR)/decompress/zstd_decompress.gcda
|
@$(RM) $(ZSTDDIR)/decompress/*.o $(ZSTDDIR)/decompress/zstd_decompress.gcda
|
||||||
@$(RM) core *.o tmp* result* *.gcda dictionary *.zst \
|
@$(RM) core *.o tmp* result* *.gcda dictionary *.zst \
|
||||||
zstd$(EXT) zstd32$(EXT) zstd-compress$(EXT) zstd-decompress$(EXT) \
|
zstd$(EXT) zstd32$(EXT) zstd-compress$(EXT) zstd-decompress$(EXT) \
|
||||||
*.gcda default.profraw
|
*.gcda default.profraw have_zlib
|
||||||
@echo Cleaning completed
|
@echo Cleaning completed
|
||||||
|
|
||||||
clean_decomp_o:
|
clean_decomp_o:
|
||||||
@$(RM) $(ZSTDDECOMP_O)
|
@$(RM) $(ZSTDDECOMP_O)
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
#make install is validated only for Linux, OSX, kFreeBSD, Hurd and some BSD targets
|
# make install is validated only for Linux, OSX, BSD, Hurd and Solaris targets
|
||||||
#----------------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD DragonFly NetBSD))
|
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS))
|
||||||
|
|
||||||
|
ifneq (,$(filter $(shell uname),SunOS))
|
||||||
|
INSTALL ?= ginstall
|
||||||
|
else
|
||||||
|
INSTALL ?= install
|
||||||
|
endif
|
||||||
|
|
||||||
|
PREFIX ?= /usr/local
|
||||||
|
DESTDIR ?=
|
||||||
|
BINDIR ?= $(PREFIX)/bin
|
||||||
|
|
||||||
|
ifneq (,$(filter $(shell uname),OpenBSD FreeBSD NetBSD DragonFly SunOS))
|
||||||
|
MANDIR ?= $(PREFIX)/man/man1
|
||||||
|
else
|
||||||
|
MANDIR ?= $(PREFIX)/share/man/man1
|
||||||
|
endif
|
||||||
|
|
||||||
|
INSTALL_PROGRAM ?= $(INSTALL) -m 755
|
||||||
|
INSTALL_SCRIPT ?= $(INSTALL) -m 755
|
||||||
|
INSTALL_MAN ?= $(INSTALL) -m 644
|
||||||
|
|
||||||
install: zstd
|
install: zstd
|
||||||
@echo Installing binaries
|
@echo Installing binaries
|
||||||
@install -d -m 755 $(DESTDIR)$(BINDIR)/ $(DESTDIR)$(MANDIR)/
|
@$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)/ $(DESTDIR)$(MANDIR)/
|
||||||
@install -m 755 zstd $(DESTDIR)$(BINDIR)/zstd
|
@$(INSTALL_PROGRAM) zstd $(DESTDIR)$(BINDIR)/zstd
|
||||||
@ln -sf zstd $(DESTDIR)$(BINDIR)/zstdcat
|
@ln -sf zstd $(DESTDIR)$(BINDIR)/zstdcat
|
||||||
@ln -sf zstd $(DESTDIR)$(BINDIR)/unzstd
|
@ln -sf zstd $(DESTDIR)$(BINDIR)/unzstd
|
||||||
@install -m 755 zstdless $(DESTDIR)$(BINDIR)/zstdless
|
@$(INSTALL_SCRIPT) zstdless $(DESTDIR)$(BINDIR)/zstdless
|
||||||
@install -m 755 zstdgrep $(DESTDIR)$(BINDIR)/zstdgrep
|
@$(INSTALL_SCRIPT) zstdgrep $(DESTDIR)$(BINDIR)/zstdgrep
|
||||||
@echo Installing man pages
|
@echo Installing man pages
|
||||||
@install -m 644 zstd.1 $(DESTDIR)$(MANDIR)/zstd.1
|
@$(INSTALL_MAN) zstd.1 $(DESTDIR)$(MANDIR)/zstd.1
|
||||||
@ln -sf zstd.1 $(DESTDIR)$(MANDIR)/zstdcat.1
|
@ln -sf zstd.1 $(DESTDIR)$(MANDIR)/zstdcat.1
|
||||||
@ln -sf zstd.1 $(DESTDIR)$(MANDIR)/unzstd.1
|
@ln -sf zstd.1 $(DESTDIR)$(MANDIR)/unzstd.1
|
||||||
@echo zstd installation completed
|
@echo zstd installation completed
|
||||||
|
|||||||
+104
-42
@@ -8,13 +8,31 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* **************************************
|
||||||
|
* Tuning parameters
|
||||||
|
****************************************/
|
||||||
|
#ifndef BMK_TIMETEST_DEFAULT_S /* default minimum time per test */
|
||||||
|
#define BMK_TIMETEST_DEFAULT_S 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* **************************************
|
||||||
|
* Compiler Warnings
|
||||||
|
****************************************/
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* *************************************
|
/* *************************************
|
||||||
* Includes
|
* Includes
|
||||||
***************************************/
|
***************************************/
|
||||||
#include "util.h" /* Compiler options, UTIL_GetFileSize, UTIL_sleep */
|
#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, ftello64 */
|
#include <stdio.h> /* fprintf, fopen */
|
||||||
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
|
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
|
||||||
|
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
@@ -22,6 +40,7 @@
|
|||||||
#include "zstd.h"
|
#include "zstd.h"
|
||||||
#include "datagen.h" /* RDG_genBuffer */
|
#include "datagen.h" /* RDG_genBuffer */
|
||||||
#include "xxhash.h"
|
#include "xxhash.h"
|
||||||
|
#include "zstdmt_compress.h"
|
||||||
|
|
||||||
|
|
||||||
/* *************************************
|
/* *************************************
|
||||||
@@ -33,7 +52,6 @@
|
|||||||
# define ZSTD_GIT_COMMIT_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_GIT_COMMIT)
|
# define ZSTD_GIT_COMMIT_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_GIT_COMMIT)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NBSECONDS 3
|
|
||||||
#define TIMELOOP_MICROSEC 1*1000000ULL /* 1 second */
|
#define TIMELOOP_MICROSEC 1*1000000ULL /* 1 second */
|
||||||
#define ACTIVEPERIOD_MICROSEC 70*1000000ULL /* 70 seconds */
|
#define ACTIVEPERIOD_MICROSEC 70*1000000ULL /* 70 seconds */
|
||||||
#define COOLPERIOD_SEC 10
|
#define COOLPERIOD_SEC 10
|
||||||
@@ -82,8 +100,6 @@ static clock_t g_time = 0;
|
|||||||
/* *************************************
|
/* *************************************
|
||||||
* Benchmark Parameters
|
* Benchmark Parameters
|
||||||
***************************************/
|
***************************************/
|
||||||
static U32 g_nbSeconds = NBSECONDS;
|
|
||||||
static size_t g_blockSize = 0;
|
|
||||||
static int g_additionalParam = 0;
|
static int g_additionalParam = 0;
|
||||||
static U32 g_decodeOnly = 0;
|
static U32 g_decodeOnly = 0;
|
||||||
|
|
||||||
@@ -91,19 +107,30 @@ void BMK_setNotificationLevel(unsigned level) { g_displayLevel=level; }
|
|||||||
|
|
||||||
void BMK_setAdditionalParam(int additionalParam) { g_additionalParam=additionalParam; }
|
void BMK_setAdditionalParam(int additionalParam) { g_additionalParam=additionalParam; }
|
||||||
|
|
||||||
void BMK_SetNbSeconds(unsigned nbSeconds)
|
static U32 g_nbSeconds = BMK_TIMETEST_DEFAULT_S;
|
||||||
|
void BMK_setNbSeconds(unsigned nbSeconds)
|
||||||
{
|
{
|
||||||
g_nbSeconds = nbSeconds;
|
g_nbSeconds = nbSeconds;
|
||||||
DISPLAYLEVEL(3, "- test >= %u seconds per compression / decompression -\n", g_nbSeconds);
|
DISPLAYLEVEL(3, "- test >= %u seconds per compression / decompression - \n", g_nbSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BMK_SetBlockSize(size_t blockSize)
|
static size_t g_blockSize = 0;
|
||||||
|
void BMK_setBlockSize(size_t blockSize)
|
||||||
{
|
{
|
||||||
g_blockSize = blockSize;
|
g_blockSize = blockSize;
|
||||||
DISPLAYLEVEL(2, "using blocks of size %u KB \n", (U32)(blockSize>>10));
|
if (g_blockSize) DISPLAYLEVEL(2, "using blocks of size %u KB \n", (U32)(blockSize>>10));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BMK_setDecodeOnlyMode(unsigned decodeFlag) { g_decodeOnly = (decodeFlag>0); }
|
||||||
|
|
||||||
|
static U32 g_nbThreads = 1;
|
||||||
|
void BMK_setNbThreads(unsigned nbThreads) {
|
||||||
|
#ifndef ZSTD_MULTITHREAD
|
||||||
|
if (nbThreads > 1) DISPLAYLEVEL(2, "Note : multi-threading is disabled \n");
|
||||||
|
#endif
|
||||||
|
g_nbThreads = nbThreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BMK_setDecodeOnly(unsigned decodeFlag) { g_decodeOnly = (decodeFlag>0); }
|
|
||||||
|
|
||||||
/* ********************************************************
|
/* ********************************************************
|
||||||
* Bench functions
|
* Bench functions
|
||||||
@@ -125,7 +152,8 @@ typedef struct {
|
|||||||
static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
||||||
const char* displayName, int cLevel,
|
const char* displayName, int cLevel,
|
||||||
const size_t* fileSizes, U32 nbFiles,
|
const size_t* fileSizes, U32 nbFiles,
|
||||||
const void* dictBuffer, size_t dictBufferSize)
|
const void* dictBuffer, size_t dictBufferSize,
|
||||||
|
ZSTD_compressionParameters *comprParams)
|
||||||
{
|
{
|
||||||
size_t const blockSize = ((g_blockSize>=32 && !g_decodeOnly) ? g_blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ;
|
size_t const blockSize = ((g_blockSize>=32 && !g_decodeOnly) ? g_blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ;
|
||||||
size_t const avgSize = MIN(g_blockSize, (srcSize / nbFiles));
|
size_t const avgSize = MIN(g_blockSize, (srcSize / nbFiles));
|
||||||
@@ -134,6 +162,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
|||||||
size_t const maxCompressedSize = ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024); /* add some room for safety */
|
size_t const maxCompressedSize = ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024); /* add some room for safety */
|
||||||
void* const compressedBuffer = malloc(maxCompressedSize);
|
void* const compressedBuffer = malloc(maxCompressedSize);
|
||||||
void* resultBuffer = malloc(srcSize);
|
void* resultBuffer = malloc(srcSize);
|
||||||
|
ZSTDMT_CCtx* const mtctx = ZSTDMT_createCCtx(g_nbThreads);
|
||||||
ZSTD_CCtx* const ctx = ZSTD_createCCtx();
|
ZSTD_CCtx* const ctx = ZSTD_createCCtx();
|
||||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||||
size_t const loadedCompressedSize = srcSize;
|
size_t const loadedCompressedSize = srcSize;
|
||||||
@@ -201,7 +230,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
|||||||
/* Bench */
|
/* Bench */
|
||||||
{ U64 fastestC = (U64)(-1LL), fastestD = (U64)(-1LL);
|
{ U64 fastestC = (U64)(-1LL), fastestD = (U64)(-1LL);
|
||||||
U64 const crcOrig = g_decodeOnly ? 0 : XXH64(srcBuffer, srcSize, 0);
|
U64 const crcOrig = g_decodeOnly ? 0 : XXH64(srcBuffer, srcSize, 0);
|
||||||
UTIL_time_t coolTime;
|
UTIL_time_t coolTime, coolTick;
|
||||||
U64 const maxTime = (g_nbSeconds * TIMELOOP_MICROSEC) + 1;
|
U64 const maxTime = (g_nbSeconds * TIMELOOP_MICROSEC) + 1;
|
||||||
U64 totalCTime=0, totalDTime=0;
|
U64 totalCTime=0, totalDTime=0;
|
||||||
U32 cCompleted=g_decodeOnly, dCompleted=0;
|
U32 cCompleted=g_decodeOnly, dCompleted=0;
|
||||||
@@ -209,34 +238,43 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
|||||||
const char* const marks[NB_MARKS] = { " |", " /", " =", "\\" };
|
const char* const marks[NB_MARKS] = { " |", " /", " =", "\\" };
|
||||||
U32 markNb = 0;
|
U32 markNb = 0;
|
||||||
|
|
||||||
|
UTIL_initTimer(&coolTick);
|
||||||
UTIL_getTime(&coolTime);
|
UTIL_getTime(&coolTime);
|
||||||
DISPLAYLEVEL(2, "\r%79s\r", "");
|
DISPLAYLEVEL(2, "\r%79s\r", "");
|
||||||
while (!cCompleted || !dCompleted) {
|
while (!cCompleted || !dCompleted) {
|
||||||
UTIL_time_t clockStart;
|
|
||||||
|
|
||||||
/* overheat protection */
|
/* overheat protection */
|
||||||
if (UTIL_clockSpanMicro(coolTime, ticksPerSecond) > ACTIVEPERIOD_MICROSEC) {
|
if (UTIL_clockSpanMicro(coolTime, coolTick) > ACTIVEPERIOD_MICROSEC) {
|
||||||
DISPLAYLEVEL(2, "\rcooling down ... \r");
|
DISPLAYLEVEL(2, "\rcooling down ... \r");
|
||||||
UTIL_sleep(COOLPERIOD_SEC);
|
UTIL_sleep(COOLPERIOD_SEC);
|
||||||
UTIL_getTime(&coolTime);
|
UTIL_getTime(&coolTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_decodeOnly) {
|
if (!g_decodeOnly) {
|
||||||
|
UTIL_time_t clockTick, clockStart;
|
||||||
/* Compression */
|
/* Compression */
|
||||||
DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->\r", marks[markNb], displayName, (U32)srcSize);
|
DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->\r", marks[markNb], displayName, (U32)srcSize);
|
||||||
if (!cCompleted) memset(compressedBuffer, 0xE5, maxCompressedSize); /* warm up and erase result buffer */
|
if (!cCompleted) memset(compressedBuffer, 0xE5, maxCompressedSize); /* warm up and erase result buffer */
|
||||||
|
|
||||||
UTIL_sleepMilli(1); /* give processor time to other processes */
|
UTIL_sleepMilli(1); /* give processor time to other processes */
|
||||||
UTIL_waitForNextTick(ticksPerSecond);
|
UTIL_waitForNextTick(ticksPerSecond);
|
||||||
|
UTIL_initTimer(&clockTick);
|
||||||
UTIL_getTime(&clockStart);
|
UTIL_getTime(&clockStart);
|
||||||
|
|
||||||
if (!cCompleted) { /* still some time to do compression tests */
|
if (!cCompleted) { /* still some time to do compression tests */
|
||||||
ZSTD_parameters const zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize);
|
ZSTD_parameters zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize);
|
||||||
ZSTD_customMem const cmem = { NULL, NULL, NULL };
|
ZSTD_customMem const cmem = { NULL, NULL, NULL };
|
||||||
U64 clockLoop = g_nbSeconds ? TIMELOOP_MICROSEC : 1;
|
U64 clockLoop = g_nbSeconds ? TIMELOOP_MICROSEC : 1;
|
||||||
U32 nbLoops = 0;
|
U32 nbLoops = 0;
|
||||||
ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, zparams, cmem);
|
ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, 1, zparams, cmem);
|
||||||
if (cdict==NULL) EXM_THROW(1, "ZSTD_createCDict_advanced() allocation failure");
|
if (cdict==NULL) EXM_THROW(1, "ZSTD_createCDict_advanced() allocation failure");
|
||||||
|
if (comprParams->windowLog) zparams.cParams.windowLog = comprParams->windowLog;
|
||||||
|
if (comprParams->chainLog) zparams.cParams.chainLog = comprParams->chainLog;
|
||||||
|
if (comprParams->hashLog) zparams.cParams.hashLog = comprParams->hashLog;
|
||||||
|
if (comprParams->searchLog) zparams.cParams.searchLog = comprParams->searchLog;
|
||||||
|
if (comprParams->searchLength) zparams.cParams.searchLength = comprParams->searchLength;
|
||||||
|
if (comprParams->targetLength) zparams.cParams.targetLength = comprParams->targetLength;
|
||||||
|
if (comprParams->strategy) zparams.cParams.strategy = (ZSTD_strategy)(comprParams->strategy - 1);
|
||||||
do {
|
do {
|
||||||
U32 blockNb;
|
U32 blockNb;
|
||||||
size_t rSize;
|
size_t rSize;
|
||||||
@@ -247,19 +285,26 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
|||||||
blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize,
|
blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize,
|
||||||
cdict);
|
cdict);
|
||||||
} else {
|
} else {
|
||||||
rSize = ZSTD_compressCCtx (ctx,
|
#ifdef ZSTD_MULTITHREAD /* note : limitation : MT single-pass does not support compression with dictionary */
|
||||||
|
rSize = ZSTDMT_compressCCtx(mtctx,
|
||||||
blockTable[blockNb].cPtr, blockTable[blockNb].cRoom,
|
blockTable[blockNb].cPtr, blockTable[blockNb].cRoom,
|
||||||
blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize, cLevel);
|
blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize,
|
||||||
|
cLevel);
|
||||||
|
#else
|
||||||
|
rSize = ZSTD_compress_advanced (ctx,
|
||||||
|
blockTable[blockNb].cPtr, blockTable[blockNb].cRoom,
|
||||||
|
blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize, NULL, 0, zparams);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (ZSTD_isError(rSize)) EXM_THROW(1, "ZSTD_compress_usingCDict() failed : %s", ZSTD_getErrorName(rSize));
|
if (ZSTD_isError(rSize)) EXM_THROW(1, "ZSTD_compress_usingCDict() failed : %s", ZSTD_getErrorName(rSize));
|
||||||
blockTable[blockNb].cSize = rSize;
|
blockTable[blockNb].cSize = rSize;
|
||||||
}
|
}
|
||||||
nbLoops++;
|
nbLoops++;
|
||||||
} while (UTIL_clockSpanMicro(clockStart, ticksPerSecond) < clockLoop);
|
} while (UTIL_clockSpanMicro(clockStart, clockTick) < clockLoop);
|
||||||
ZSTD_freeCDict(cdict);
|
ZSTD_freeCDict(cdict);
|
||||||
{ U64 const clockSpan = UTIL_clockSpanMicro(clockStart, ticksPerSecond);
|
{ U64 const clockSpanMicro = UTIL_clockSpanMicro(clockStart, clockTick);
|
||||||
if (clockSpan < fastestC*nbLoops) fastestC = clockSpan / nbLoops;
|
if (clockSpanMicro < fastestC*nbLoops) fastestC = clockSpanMicro / nbLoops;
|
||||||
totalCTime += clockSpan;
|
totalCTime += clockSpanMicro;
|
||||||
cCompleted = (totalCTime >= maxTime);
|
cCompleted = (totalCTime >= maxTime);
|
||||||
} }
|
} }
|
||||||
|
|
||||||
@@ -274,20 +319,24 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
|||||||
memcpy(compressedBuffer, srcBuffer, loadedCompressedSize);
|
memcpy(compressedBuffer, srcBuffer, loadedCompressedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)fastestD; (void)crcOrig; /* unused when decompression disabled */
|
#if 0 /* disable decompression test */
|
||||||
#if 1
|
dCompleted=1;
|
||||||
|
(void)totalDTime; (void)fastestD; (void)crcOrig; /* unused when decompression disabled */
|
||||||
|
#else
|
||||||
/* Decompression */
|
/* Decompression */
|
||||||
if (!dCompleted) memset(resultBuffer, 0xD6, srcSize); /* warm result buffer */
|
if (!dCompleted) memset(resultBuffer, 0xD6, srcSize); /* warm result buffer */
|
||||||
|
|
||||||
UTIL_sleepMilli(1); /* give processor time to other processes */
|
UTIL_sleepMilli(1); /* give processor time to other processes */
|
||||||
UTIL_waitForNextTick(ticksPerSecond);
|
UTIL_waitForNextTick(ticksPerSecond);
|
||||||
UTIL_getTime(&clockStart);
|
|
||||||
|
|
||||||
if (!dCompleted) {
|
if (!dCompleted) {
|
||||||
U64 clockLoop = g_nbSeconds ? TIMELOOP_MICROSEC : 1;
|
U64 clockLoop = g_nbSeconds ? TIMELOOP_MICROSEC : 1;
|
||||||
U32 nbLoops = 0;
|
U32 nbLoops = 0;
|
||||||
|
UTIL_time_t clockStart, clockTick;
|
||||||
ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictBufferSize);
|
ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictBufferSize);
|
||||||
if (!ddict) EXM_THROW(2, "ZSTD_createDDict() allocation failure");
|
if (!ddict) EXM_THROW(2, "ZSTD_createDDict() allocation failure");
|
||||||
|
UTIL_initTimer(&clockTick);
|
||||||
|
UTIL_getTime(&clockStart);
|
||||||
do {
|
do {
|
||||||
U32 blockNb;
|
U32 blockNb;
|
||||||
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
|
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
|
||||||
@@ -296,19 +345,19 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
|||||||
blockTable[blockNb].cPtr, blockTable[blockNb].cSize,
|
blockTable[blockNb].cPtr, blockTable[blockNb].cSize,
|
||||||
ddict);
|
ddict);
|
||||||
if (ZSTD_isError(regenSize)) {
|
if (ZSTD_isError(regenSize)) {
|
||||||
DISPLAY("ZSTD_decompress_usingDDict() failed on block %u : %s \n",
|
DISPLAY("ZSTD_decompress_usingDDict() failed on block %u of size %u : %s \n",
|
||||||
blockNb, ZSTD_getErrorName(regenSize));
|
blockNb, (U32)blockTable[blockNb].cSize, ZSTD_getErrorName(regenSize));
|
||||||
clockLoop = 0; /* force immediate test end */
|
clockLoop = 0; /* force immediate test end */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
blockTable[blockNb].resSize = regenSize;
|
blockTable[blockNb].resSize = regenSize;
|
||||||
}
|
}
|
||||||
nbLoops++;
|
nbLoops++;
|
||||||
} while (UTIL_clockSpanMicro(clockStart, ticksPerSecond) < clockLoop);
|
} while (UTIL_clockSpanMicro(clockStart, clockTick) < clockLoop);
|
||||||
ZSTD_freeDDict(ddict);
|
ZSTD_freeDDict(ddict);
|
||||||
{ U64 const clockSpan = UTIL_clockSpanMicro(clockStart, ticksPerSecond);
|
{ U64 const clockSpanMicro = UTIL_clockSpanMicro(clockStart, clockTick);
|
||||||
if (clockSpan < fastestD*nbLoops) fastestD = clockSpan / nbLoops;
|
if (clockSpanMicro < fastestD*nbLoops) fastestD = clockSpanMicro / nbLoops;
|
||||||
totalDTime += clockSpan;
|
totalDTime += clockSpanMicro;
|
||||||
dCompleted = (totalDTime >= maxTime);
|
dCompleted = (totalDTime >= maxTime);
|
||||||
} }
|
} }
|
||||||
|
|
||||||
@@ -335,6 +384,17 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
|||||||
pos = (U32)(u - bacc);
|
pos = (U32)(u - bacc);
|
||||||
bNb = pos / (128 KB);
|
bNb = pos / (128 KB);
|
||||||
DISPLAY("(block %u, sub %u, pos %u) \n", segNb, bNb, pos);
|
DISPLAY("(block %u, sub %u, pos %u) \n", segNb, bNb, pos);
|
||||||
|
if (u>5) {
|
||||||
|
int n;
|
||||||
|
for (n=-5; n<0; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]);
|
||||||
|
DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]);
|
||||||
|
for (n=1; n<3; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]);
|
||||||
|
DISPLAY(" \n");
|
||||||
|
for (n=-5; n<0; n++) DISPLAY("%02X ", ((const BYTE*)resultBuffer)[u+n]);
|
||||||
|
DISPLAY(" :%02X: ", ((const BYTE*)resultBuffer)[u]);
|
||||||
|
for (n=1; n<3; n++) DISPLAY("%02X ", ((const BYTE*)resultBuffer)[u+n]);
|
||||||
|
DISPLAY(" \n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (u==srcSize-1) { /* should never happen */
|
if (u==srcSize-1) { /* should never happen */
|
||||||
@@ -360,6 +420,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
|||||||
free(blockTable);
|
free(blockTable);
|
||||||
free(compressedBuffer);
|
free(compressedBuffer);
|
||||||
free(resultBuffer);
|
free(resultBuffer);
|
||||||
|
ZSTDMT_freeCCtx(mtctx);
|
||||||
ZSTD_freeCCtx(ctx);
|
ZSTD_freeCCtx(ctx);
|
||||||
ZSTD_freeDCtx(dctx);
|
ZSTD_freeDCtx(dctx);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -387,7 +448,8 @@ static size_t BMK_findMaxMem(U64 requiredMem)
|
|||||||
static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
|
static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
|
||||||
const char* displayName, int cLevel, int cLevelLast,
|
const char* displayName, int cLevel, int cLevelLast,
|
||||||
const size_t* fileSizes, unsigned nbFiles,
|
const size_t* fileSizes, unsigned nbFiles,
|
||||||
const void* dictBuffer, size_t dictBufferSize)
|
const void* dictBuffer, size_t dictBufferSize,
|
||||||
|
ZSTD_compressionParameters *compressionParams)
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
@@ -406,7 +468,7 @@ static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
|
|||||||
BMK_benchMem(srcBuffer, benchedSize,
|
BMK_benchMem(srcBuffer, benchedSize,
|
||||||
displayName, l,
|
displayName, l,
|
||||||
fileSizes, nbFiles,
|
fileSizes, nbFiles,
|
||||||
dictBuffer, dictBufferSize);
|
dictBuffer, dictBufferSize, compressionParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,8 +505,8 @@ static void BMK_loadFiles(void* buffer, size_t bufferSize,
|
|||||||
if (totalSize == 0) EXM_THROW(12, "no data to bench");
|
if (totalSize == 0) EXM_THROW(12, "no data to bench");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles,
|
static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles, const char* dictFileName,
|
||||||
const char* dictFileName, int cLevel, int cLevelLast)
|
int cLevel, int cLevelLast, ZSTD_compressionParameters *compressionParams)
|
||||||
{
|
{
|
||||||
void* srcBuffer;
|
void* srcBuffer;
|
||||||
size_t benchedSize;
|
size_t benchedSize;
|
||||||
@@ -483,7 +545,7 @@ static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles,
|
|||||||
BMK_benchCLevel(srcBuffer, benchedSize,
|
BMK_benchCLevel(srcBuffer, benchedSize,
|
||||||
displayName, cLevel, cLevelLast,
|
displayName, cLevel, cLevelLast,
|
||||||
fileSizes, nbFiles,
|
fileSizes, nbFiles,
|
||||||
dictBuffer, dictBufferSize);
|
dictBuffer, dictBufferSize, compressionParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
@@ -493,7 +555,7 @@ static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility)
|
static void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility, ZSTD_compressionParameters* compressionParams)
|
||||||
{
|
{
|
||||||
char name[20] = {0};
|
char name[20] = {0};
|
||||||
size_t benchedSize = 10000000;
|
size_t benchedSize = 10000000;
|
||||||
@@ -507,15 +569,15 @@ static void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility
|
|||||||
|
|
||||||
/* Bench */
|
/* Bench */
|
||||||
snprintf (name, sizeof(name), "Synthetic %2u%%", (unsigned)(compressibility*100));
|
snprintf (name, sizeof(name), "Synthetic %2u%%", (unsigned)(compressibility*100));
|
||||||
BMK_benchCLevel(srcBuffer, benchedSize, name, cLevel, cLevelLast, &benchedSize, 1, NULL, 0);
|
BMK_benchCLevel(srcBuffer, benchedSize, name, cLevel, cLevelLast, &benchedSize, 1, NULL, 0, compressionParams);
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
free(srcBuffer);
|
free(srcBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,
|
int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles, const char* dictFileName,
|
||||||
const char* dictFileName, int cLevel, int cLevelLast)
|
int cLevel, int cLevelLast, ZSTD_compressionParameters* compressionParams)
|
||||||
{
|
{
|
||||||
double const compressibility = (double)g_compressibilityDefault / 100;
|
double const compressibility = (double)g_compressibilityDefault / 100;
|
||||||
|
|
||||||
@@ -525,8 +587,8 @@ int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,
|
|||||||
if (cLevelLast > cLevel) DISPLAYLEVEL(2, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast);
|
if (cLevelLast > cLevel) DISPLAYLEVEL(2, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast);
|
||||||
|
|
||||||
if (nbFiles == 0)
|
if (nbFiles == 0)
|
||||||
BMK_syntheticTest(cLevel, cLevelLast, compressibility);
|
BMK_syntheticTest(cLevel, cLevelLast, compressibility, compressionParams);
|
||||||
else
|
else
|
||||||
BMK_benchFileTable(fileNamesTable, nbFiles, dictFileName, cLevel, cLevelLast);
|
BMK_benchFileTable(fileNamesTable, nbFiles, dictFileName, cLevel, cLevelLast, compressionParams);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-6
@@ -12,15 +12,18 @@
|
|||||||
#define BENCH_H_121279284357
|
#define BENCH_H_121279284357
|
||||||
|
|
||||||
#include <stddef.h> /* size_t */
|
#include <stddef.h> /* size_t */
|
||||||
|
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */
|
||||||
|
#include "zstd.h" /* ZSTD_compressionParameters */
|
||||||
|
|
||||||
int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,
|
int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,const char* dictFileName,
|
||||||
const char* dictFileName, int cLevel, int cLevelLast);
|
int cLevel, int cLevelLast, ZSTD_compressionParameters* compressionParams);
|
||||||
|
|
||||||
/* Set Parameters */
|
/* Set Parameters */
|
||||||
void BMK_SetNbSeconds(unsigned nbLoops);
|
void BMK_setNbSeconds(unsigned nbLoops);
|
||||||
void BMK_SetBlockSize(size_t blockSize);
|
void BMK_setBlockSize(size_t blockSize);
|
||||||
void BMK_setAdditionalParam(int additionalParam);
|
void BMK_setNbThreads(unsigned nbThreads);
|
||||||
void BMK_setNotificationLevel(unsigned level);
|
void BMK_setNotificationLevel(unsigned level);
|
||||||
void BMK_setDecodeOnly(unsigned decodeFlag);
|
void BMK_setAdditionalParam(int additionalParam);
|
||||||
|
void BMK_setDecodeOnlyMode(unsigned decodeFlag);
|
||||||
|
|
||||||
#endif /* BENCH_H_121279284357 */
|
#endif /* BENCH_H_121279284357 */
|
||||||
|
|||||||
+1
-20
@@ -9,35 +9,16 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* *************************************
|
|
||||||
* Compiler Options
|
|
||||||
***************************************/
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
# define _CRT_SECURE_NO_WARNINGS /* removes Visual warning on strerror() */
|
|
||||||
# define _CRT_SECURE_NO_DEPRECATE /* removes VS2005 warning on strerror() */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Dependencies
|
* Dependencies
|
||||||
**************************************/
|
**************************************/
|
||||||
|
#include "platform.h" /* SET_BINARY_MODE */
|
||||||
#include <stdlib.h> /* malloc, free */
|
#include <stdlib.h> /* malloc, free */
|
||||||
#include <stdio.h> /* FILE, fwrite, fprintf */
|
#include <stdio.h> /* FILE, fwrite, fprintf */
|
||||||
#include <string.h> /* memcpy */
|
#include <string.h> /* memcpy */
|
||||||
#include "mem.h" /* U32 */
|
#include "mem.h" /* U32 */
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
|
||||||
* OS-specific Includes
|
|
||||||
**************************************/
|
|
||||||
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
|
|
||||||
# include <fcntl.h> /* _O_BINARY */
|
|
||||||
# include <io.h> /* _setmode, _isatty */
|
|
||||||
# define SET_BINARY_MODE(file) {int unused = _setmode(_fileno(file), _O_BINARY); (void)unused; }
|
|
||||||
#else
|
|
||||||
# define SET_BINARY_MODE(file)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Macros
|
* Macros
|
||||||
**************************************/
|
**************************************/
|
||||||
|
|||||||
+91
-13
@@ -9,10 +9,19 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* **************************************
|
||||||
|
* Compiler Warnings
|
||||||
|
****************************************/
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************
|
/*-*************************************
|
||||||
* Includes
|
* Includes
|
||||||
***************************************/
|
***************************************/
|
||||||
#include "util.h" /* Compiler options, UTIL_GetFileSize, UTIL_getTotalFileSize */
|
#include "platform.h" /* Large Files support */
|
||||||
|
#include "util.h" /* UTIL_getFileSize, UTIL_getTotalFileSize */
|
||||||
#include <stdlib.h> /* malloc, free */
|
#include <stdlib.h> /* malloc, free */
|
||||||
#include <string.h> /* memset */
|
#include <string.h> /* memset */
|
||||||
#include <stdio.h> /* fprintf, fopen, ftello64 */
|
#include <stdio.h> /* fprintf, fopen, ftello64 */
|
||||||
@@ -31,7 +40,9 @@
|
|||||||
#define MB *(1 <<20)
|
#define MB *(1 <<20)
|
||||||
#define GB *(1U<<30)
|
#define GB *(1U<<30)
|
||||||
|
|
||||||
#define MEMMULT 11
|
#define SAMPLESIZE_MAX (128 KB)
|
||||||
|
#define MEMMULT 11 /* rough estimation : memory cost to analyze 1 byte of sample */
|
||||||
|
#define COVER_MEMMULT 9 /* rough estimation : memory cost to analyze 1 byte of sample */
|
||||||
static const size_t maxMemory = (sizeof(size_t) == 4) ? (2 GB - 64 MB) : ((size_t)(512 MB) << sizeof(size_t));
|
static const size_t maxMemory = (sizeof(size_t) == 4) ? (2 GB - 64 MB) : ((size_t)(512 MB) << sizeof(size_t));
|
||||||
|
|
||||||
#define NOISELENGTH 32
|
#define NOISELENGTH 32
|
||||||
@@ -97,7 +108,7 @@ static unsigned DiB_loadFiles(void* buffer, size_t* bufferSizePtr,
|
|||||||
for (n=0; n<nbFiles; n++) {
|
for (n=0; n<nbFiles; n++) {
|
||||||
const char* const fileName = fileNamesTable[n];
|
const char* const fileName = fileNamesTable[n];
|
||||||
unsigned long long const fs64 = UTIL_getFileSize(fileName);
|
unsigned long long const fs64 = UTIL_getFileSize(fileName);
|
||||||
size_t const fileSize = (size_t) MIN(fs64, 128 KB);
|
size_t const fileSize = (size_t) MIN(fs64, SAMPLESIZE_MAX);
|
||||||
if (fileSize > *bufferSizePtr-pos) break;
|
if (fileSize > *bufferSizePtr-pos) break;
|
||||||
{ FILE* const f = fopen(fileName, "rb");
|
{ FILE* const f = fopen(fileName, "rb");
|
||||||
if (f==NULL) EXM_THROW(10, "zstd: dictBuilder: %s %s ", fileName, strerror(errno));
|
if (f==NULL) EXM_THROW(10, "zstd: dictBuilder: %s %s ", fileName, strerror(errno));
|
||||||
@@ -108,10 +119,36 @@ static unsigned DiB_loadFiles(void* buffer, size_t* bufferSizePtr,
|
|||||||
fileSizes[n] = fileSize;
|
fileSizes[n] = fileSize;
|
||||||
fclose(f);
|
fclose(f);
|
||||||
} }
|
} }
|
||||||
|
DISPLAYLEVEL(2, "\r%79s\r", "");
|
||||||
*bufferSizePtr = pos;
|
*bufferSizePtr = pos;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DiB_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||||
|
static U32 DiB_rand(U32* src)
|
||||||
|
{
|
||||||
|
static const U32 prime1 = 2654435761U;
|
||||||
|
static const U32 prime2 = 2246822519U;
|
||||||
|
U32 rand32 = *src;
|
||||||
|
rand32 *= prime1;
|
||||||
|
rand32 ^= prime2;
|
||||||
|
rand32 = DiB_rotl32(rand32, 13);
|
||||||
|
*src = rand32;
|
||||||
|
return rand32 >> 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DiB_shuffle(const char** fileNamesTable, unsigned nbFiles) {
|
||||||
|
/* Initialize the pseudorandom number generator */
|
||||||
|
U32 seed = 0xFD2FB528;
|
||||||
|
unsigned i;
|
||||||
|
for (i = nbFiles - 1; i > 0; --i) {
|
||||||
|
unsigned const j = DiB_rand(&seed) % (i + 1);
|
||||||
|
const char* tmp = fileNamesTable[j];
|
||||||
|
fileNamesTable[j] = fileNamesTable[i];
|
||||||
|
fileNamesTable[i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-********************************************************
|
/*-********************************************************
|
||||||
* Dictionary training functions
|
* Dictionary training functions
|
||||||
@@ -163,6 +200,21 @@ static void DiB_saveDict(const char* dictFileName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int g_tooLargeSamples = 0;
|
||||||
|
static U64 DiB_getTotalCappedFileSize(const char** fileNamesTable, unsigned nbFiles)
|
||||||
|
{
|
||||||
|
U64 total = 0;
|
||||||
|
unsigned n;
|
||||||
|
for (n=0; n<nbFiles; n++) {
|
||||||
|
U64 const fileSize = UTIL_getFileSize(fileNamesTable[n]);
|
||||||
|
U64 const cappedFileSize = MIN(fileSize, SAMPLESIZE_MAX);
|
||||||
|
total += cappedFileSize;
|
||||||
|
g_tooLargeSamples |= (fileSize > 2*SAMPLESIZE_MAX);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! ZDICT_trainFromBuffer_unsafe() :
|
/*! ZDICT_trainFromBuffer_unsafe() :
|
||||||
Strictly Internal use only !!
|
Strictly Internal use only !!
|
||||||
Same as ZDICT_trainFromBuffer_advanced(), but does not control `samplesBuffer`.
|
Same as ZDICT_trainFromBuffer_advanced(), but does not control `samplesBuffer`.
|
||||||
@@ -177,20 +229,29 @@ size_t ZDICT_trainFromBuffer_unsafe(void* dictBuffer, size_t dictBufferCapacity,
|
|||||||
|
|
||||||
int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
||||||
const char** fileNamesTable, unsigned nbFiles,
|
const char** fileNamesTable, unsigned nbFiles,
|
||||||
ZDICT_params_t params)
|
ZDICT_params_t *params, COVER_params_t *coverParams,
|
||||||
|
int optimizeCover)
|
||||||
{
|
{
|
||||||
void* const dictBuffer = malloc(maxDictSize);
|
void* const dictBuffer = malloc(maxDictSize);
|
||||||
size_t* const fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t));
|
size_t* const fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t));
|
||||||
unsigned long long const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles);
|
unsigned long long const totalSizeToLoad = DiB_getTotalCappedFileSize(fileNamesTable, nbFiles);
|
||||||
size_t const maxMem = DiB_findMaxMem(totalSizeToLoad * MEMMULT) / MEMMULT;
|
size_t const memMult = params ? MEMMULT : COVER_MEMMULT;
|
||||||
size_t benchedSize = MIN (maxMem, (size_t)totalSizeToLoad);
|
size_t const maxMem = DiB_findMaxMem(totalSizeToLoad * memMult) / memMult;
|
||||||
|
size_t benchedSize = (size_t) MIN ((unsigned long long)maxMem, totalSizeToLoad);
|
||||||
void* const srcBuffer = malloc(benchedSize+NOISELENGTH);
|
void* const srcBuffer = malloc(benchedSize+NOISELENGTH);
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
/* Checks */
|
/* Checks */
|
||||||
|
if (params) g_displayLevel = params->notificationLevel;
|
||||||
|
else if (coverParams) g_displayLevel = coverParams->notificationLevel;
|
||||||
|
else EXM_THROW(13, "Neither dictionary algorith selected"); /* should not happen */
|
||||||
if ((!fileSizes) || (!srcBuffer) || (!dictBuffer)) EXM_THROW(12, "not enough memory for DiB_trainFiles"); /* should not happen */
|
if ((!fileSizes) || (!srcBuffer) || (!dictBuffer)) EXM_THROW(12, "not enough memory for DiB_trainFiles"); /* should not happen */
|
||||||
g_displayLevel = params.notificationLevel;
|
if (g_tooLargeSamples) {
|
||||||
if (nbFiles < 5) {
|
DISPLAYLEVEL(2, "! Warning : some samples are very large \n");
|
||||||
|
DISPLAYLEVEL(2, "! Note that dictionary is only useful for small files or beginning of large files. \n");
|
||||||
|
DISPLAYLEVEL(2, "! As a consequence, only the first %u bytes of each file are loaded \n", SAMPLESIZE_MAX);
|
||||||
|
}
|
||||||
|
if ((nbFiles < 5) || (totalSizeToLoad < 9 * (unsigned long long)maxDictSize)) {
|
||||||
DISPLAYLEVEL(2, "! Warning : nb of samples too low for proper processing ! \n");
|
DISPLAYLEVEL(2, "! Warning : nb of samples too low for proper processing ! \n");
|
||||||
DISPLAYLEVEL(2, "! Please provide _one file per sample_. \n");
|
DISPLAYLEVEL(2, "! Please provide _one file per sample_. \n");
|
||||||
DISPLAYLEVEL(2, "! Do not concatenate samples together into a single file, \n");
|
DISPLAYLEVEL(2, "! Do not concatenate samples together into a single file, \n");
|
||||||
@@ -203,12 +264,29 @@ int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
|||||||
DISPLAYLEVEL(1, "Not enough memory; training on %u MB only...\n", (unsigned)(benchedSize >> 20));
|
DISPLAYLEVEL(1, "Not enough memory; training on %u MB only...\n", (unsigned)(benchedSize >> 20));
|
||||||
|
|
||||||
/* Load input buffer */
|
/* Load input buffer */
|
||||||
|
DISPLAYLEVEL(3, "Shuffling input files\n");
|
||||||
|
DiB_shuffle(fileNamesTable, nbFiles);
|
||||||
nbFiles = DiB_loadFiles(srcBuffer, &benchedSize, fileSizes, fileNamesTable, nbFiles);
|
nbFiles = DiB_loadFiles(srcBuffer, &benchedSize, fileSizes, fileNamesTable, nbFiles);
|
||||||
DiB_fillNoise((char*)srcBuffer + benchedSize, NOISELENGTH); /* guard band, for end of buffer condition */
|
|
||||||
|
|
||||||
{ size_t const dictSize = ZDICT_trainFromBuffer_unsafe(dictBuffer, maxDictSize,
|
{
|
||||||
srcBuffer, fileSizes, nbFiles,
|
size_t dictSize;
|
||||||
params);
|
if (params) {
|
||||||
|
DiB_fillNoise((char*)srcBuffer + benchedSize, NOISELENGTH); /* guard band, for end of buffer condition */
|
||||||
|
dictSize = ZDICT_trainFromBuffer_unsafe(dictBuffer, maxDictSize,
|
||||||
|
srcBuffer, fileSizes, nbFiles,
|
||||||
|
*params);
|
||||||
|
} else if (optimizeCover) {
|
||||||
|
dictSize = COVER_optimizeTrainFromBuffer(
|
||||||
|
dictBuffer, maxDictSize, srcBuffer, fileSizes, nbFiles,
|
||||||
|
coverParams);
|
||||||
|
if (!ZDICT_isError(dictSize)) {
|
||||||
|
DISPLAYLEVEL(2, "k=%u\nd=%u\nsteps=%u\n", coverParams->k, coverParams->d, coverParams->steps);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dictSize = COVER_trainFromBuffer(dictBuffer, maxDictSize,
|
||||||
|
srcBuffer, fileSizes, nbFiles,
|
||||||
|
*coverParams);
|
||||||
|
}
|
||||||
if (ZDICT_isError(dictSize)) {
|
if (ZDICT_isError(dictSize)) {
|
||||||
DISPLAYLEVEL(1, "dictionary training failed : %s \n", ZDICT_getErrorName(dictSize)); /* should not happen */
|
DISPLAYLEVEL(1, "dictionary training failed : %s \n", ZDICT_getErrorName(dictSize)); /* should not happen */
|
||||||
result = 1;
|
result = 1;
|
||||||
|
|||||||
+2
-2
@@ -32,7 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
|
||||||
const char** fileNamesTable, unsigned nbFiles,
|
const char** fileNamesTable, unsigned nbFiles,
|
||||||
ZDICT_params_t parameters);
|
ZDICT_params_t *params, COVER_params_t *coverParams,
|
||||||
|
int optimizeCover);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+128
-59
@@ -7,11 +7,12 @@
|
|||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* *************************************
|
/* *************************************
|
||||||
* Compiler Options
|
* Compiler Options
|
||||||
***************************************/
|
***************************************/
|
||||||
#ifdef _MSC_VER /* Visual */
|
#ifdef _MSC_VER /* Visual */
|
||||||
# define _CRT_SECURE_NO_WARNINGS /* removes Visual warning on strerror() */
|
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||||
# pragma warning(disable : 4204) /* non-constant aggregate initializer */
|
# pragma warning(disable : 4204) /* non-constant aggregate initializer */
|
||||||
#endif
|
#endif
|
||||||
#if defined(__MINGW32__) && !defined(_POSIX_SOURCE)
|
#if defined(__MINGW32__) && !defined(_POSIX_SOURCE)
|
||||||
@@ -22,7 +23,8 @@
|
|||||||
/*-*************************************
|
/*-*************************************
|
||||||
* Includes
|
* Includes
|
||||||
***************************************/
|
***************************************/
|
||||||
#include "util.h" /* Compiler options, UTIL_GetFileSize, _LARGEFILE64_SOURCE */
|
#include "platform.h" /* Large Files support, SET_BINARY_MODE */
|
||||||
|
#include "util.h" /* UTIL_getFileSize */
|
||||||
#include <stdio.h> /* fprintf, fopen, fread, _fileno, stdin, stdout */
|
#include <stdio.h> /* fprintf, fopen, fread, _fileno, stdin, stdout */
|
||||||
#include <stdlib.h> /* malloc, free */
|
#include <stdlib.h> /* malloc, free */
|
||||||
#include <string.h> /* strcmp, strlen */
|
#include <string.h> /* strcmp, strlen */
|
||||||
@@ -33,24 +35,14 @@
|
|||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */
|
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */
|
||||||
#include "zstd.h"
|
#include "zstd.h"
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
# include "zstdmt_compress.h"
|
||||||
|
#endif
|
||||||
#ifdef ZSTD_GZDECOMPRESS
|
#ifdef ZSTD_GZDECOMPRESS
|
||||||
#include "zlib.h"
|
# include "zlib.h"
|
||||||
#if !defined(z_const)
|
# if !defined(z_const)
|
||||||
#define z_const
|
# define z_const
|
||||||
#endif
|
# endif
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************
|
|
||||||
* OS-specific Includes
|
|
||||||
***************************************/
|
|
||||||
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
|
|
||||||
# include <fcntl.h> /* _O_BINARY */
|
|
||||||
# include <io.h> /* _setmode, _isatty */
|
|
||||||
# define SET_BINARY_MODE(file) { if (_setmode(_fileno(file), _O_BINARY) == -1) perror("Cannot set _O_BINARY"); }
|
|
||||||
#else
|
|
||||||
# include <unistd.h> /* isatty */
|
|
||||||
# define SET_BINARY_MODE(file)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -86,14 +78,14 @@
|
|||||||
* Macros
|
* Macros
|
||||||
***************************************/
|
***************************************/
|
||||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||||
#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
|
#define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
|
||||||
static U32 g_displayLevel = 2; /* 0 : no display; 1: errors; 2 : + result + interaction + warnings; 3 : + progression; 4 : + information */
|
static U32 g_displayLevel = 2; /* 0 : no display; 1: errors; 2 : + result + interaction + warnings; 3 : + progression; 4 : + information */
|
||||||
void FIO_setNotificationLevel(unsigned level) { g_displayLevel=level; }
|
void FIO_setNotificationLevel(unsigned level) { g_displayLevel=level; }
|
||||||
|
|
||||||
#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
|
#define DISPLAYUPDATE(l, ...) { if (g_displayLevel>=l) { \
|
||||||
if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \
|
if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \
|
||||||
{ g_time = clock(); DISPLAY(__VA_ARGS__); \
|
{ g_time = clock(); DISPLAY(__VA_ARGS__); \
|
||||||
if (g_displayLevel>=4) fflush(stdout); } }
|
if (g_displayLevel>=4) fflush(stdout); } } }
|
||||||
static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
|
static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
|
||||||
static clock_t g_time = 0;
|
static clock_t g_time = 0;
|
||||||
|
|
||||||
@@ -115,7 +107,30 @@ static U32 g_removeSrcFile = 0;
|
|||||||
void FIO_setRemoveSrcFile(unsigned flag) { g_removeSrcFile = (flag>0); }
|
void FIO_setRemoveSrcFile(unsigned flag) { g_removeSrcFile = (flag>0); }
|
||||||
static U32 g_memLimit = 0;
|
static U32 g_memLimit = 0;
|
||||||
void FIO_setMemLimit(unsigned memLimit) { g_memLimit = memLimit; }
|
void FIO_setMemLimit(unsigned memLimit) { g_memLimit = memLimit; }
|
||||||
|
static U32 g_nbThreads = 1;
|
||||||
|
void FIO_setNbThreads(unsigned nbThreads) {
|
||||||
|
#ifndef ZSTD_MULTITHREAD
|
||||||
|
if (nbThreads > 1) DISPLAYLEVEL(2, "Note : multi-threading is disabled \n");
|
||||||
|
#endif
|
||||||
|
g_nbThreads = nbThreads;
|
||||||
|
}
|
||||||
|
static U32 g_blockSize = 0;
|
||||||
|
void FIO_setBlockSize(unsigned blockSize) {
|
||||||
|
if (blockSize && g_nbThreads==1)
|
||||||
|
DISPLAYLEVEL(2, "Setting block size is useless in single-thread mode \n");
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
if (blockSize-1 < ZSTDMT_SECTION_SIZE_MIN-1) /* intentional underflow */
|
||||||
|
DISPLAYLEVEL(2, "Note : minimum block size is %u KB \n", (ZSTDMT_SECTION_SIZE_MIN>>10));
|
||||||
|
#endif
|
||||||
|
g_blockSize = blockSize;
|
||||||
|
}
|
||||||
|
#define FIO_OVERLAP_LOG_NOTSET 9999
|
||||||
|
static U32 g_overlapLog = FIO_OVERLAP_LOG_NOTSET;
|
||||||
|
void FIO_setOverlapLog(unsigned overlapLog){
|
||||||
|
if (overlapLog && g_nbThreads==1)
|
||||||
|
DISPLAYLEVEL(2, "Setting overlapLog is useless in single-thread mode \n");
|
||||||
|
g_overlapLog = overlapLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************
|
/*-*************************************
|
||||||
@@ -150,6 +165,10 @@ static FILE* FIO_openSrcFile(const char* srcFileName)
|
|||||||
f = stdin;
|
f = stdin;
|
||||||
SET_BINARY_MODE(stdin);
|
SET_BINARY_MODE(stdin);
|
||||||
} else {
|
} else {
|
||||||
|
if (!UTIL_doesFileExists(srcFileName)) {
|
||||||
|
DISPLAYLEVEL(1, "zstd: %s is not a regular file -- ignored \n", srcFileName);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
f = fopen(srcFileName, "rb");
|
f = fopen(srcFileName, "rb");
|
||||||
if ( f==NULL ) DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno));
|
if ( f==NULL ) DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno));
|
||||||
}
|
}
|
||||||
@@ -238,22 +257,36 @@ static size_t FIO_loadFile(void** bufferPtr, const char* fileName)
|
|||||||
* Compression
|
* Compression
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
FILE* srcFile;
|
||||||
|
FILE* dstFile;
|
||||||
void* srcBuffer;
|
void* srcBuffer;
|
||||||
size_t srcBufferSize;
|
size_t srcBufferSize;
|
||||||
void* dstBuffer;
|
void* dstBuffer;
|
||||||
size_t dstBufferSize;
|
size_t dstBufferSize;
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
ZSTDMT_CCtx* cctx;
|
||||||
|
#else
|
||||||
ZSTD_CStream* cctx;
|
ZSTD_CStream* cctx;
|
||||||
FILE* dstFile;
|
#endif
|
||||||
FILE* srcFile;
|
|
||||||
} cRess_t;
|
} cRess_t;
|
||||||
|
|
||||||
static cRess_t FIO_createCResources(const char* dictFileName, int cLevel, U64 srcSize)
|
static cRess_t FIO_createCResources(const char* dictFileName, int cLevel,
|
||||||
|
U64 srcSize, ZSTD_compressionParameters* comprParams)
|
||||||
{
|
{
|
||||||
cRess_t ress;
|
cRess_t ress;
|
||||||
memset(&ress, 0, sizeof(ress));
|
memset(&ress, 0, sizeof(ress));
|
||||||
|
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
ress.cctx = ZSTDMT_createCCtx(g_nbThreads);
|
||||||
|
if (ress.cctx == NULL) EXM_THROW(30, "zstd: allocation error : can't create ZSTD_CStream");
|
||||||
|
if ((cLevel==ZSTD_maxCLevel()) && (g_overlapLog==FIO_OVERLAP_LOG_NOTSET))
|
||||||
|
ZSTDMT_setMTCtxParameter(ress.cctx, ZSTDMT_p_overlapSectionLog, 9); /* use complete window for overlap */
|
||||||
|
if (g_overlapLog != FIO_OVERLAP_LOG_NOTSET)
|
||||||
|
ZSTDMT_setMTCtxParameter(ress.cctx, ZSTDMT_p_overlapSectionLog, g_overlapLog);
|
||||||
|
#else
|
||||||
ress.cctx = ZSTD_createCStream();
|
ress.cctx = ZSTD_createCStream();
|
||||||
if (ress.cctx == NULL) EXM_THROW(30, "zstd: allocation error : can't create ZSTD_CStream");
|
if (ress.cctx == NULL) EXM_THROW(30, "zstd: allocation error : can't create ZSTD_CStream");
|
||||||
|
#endif
|
||||||
ress.srcBufferSize = ZSTD_CStreamInSize();
|
ress.srcBufferSize = ZSTD_CStreamInSize();
|
||||||
ress.srcBuffer = malloc(ress.srcBufferSize);
|
ress.srcBuffer = malloc(ress.srcBufferSize);
|
||||||
ress.dstBufferSize = ZSTD_CStreamOutSize();
|
ress.dstBufferSize = ZSTD_CStreamOutSize();
|
||||||
@@ -268,8 +301,21 @@ static cRess_t FIO_createCResources(const char* dictFileName, int cLevel, U64 sr
|
|||||||
params.fParams.contentSizeFlag = 1;
|
params.fParams.contentSizeFlag = 1;
|
||||||
params.fParams.checksumFlag = g_checksumFlag;
|
params.fParams.checksumFlag = g_checksumFlag;
|
||||||
params.fParams.noDictIDFlag = !g_dictIDFlag;
|
params.fParams.noDictIDFlag = !g_dictIDFlag;
|
||||||
|
if (comprParams->windowLog) params.cParams.windowLog = comprParams->windowLog;
|
||||||
|
if (comprParams->chainLog) params.cParams.chainLog = comprParams->chainLog;
|
||||||
|
if (comprParams->hashLog) params.cParams.hashLog = comprParams->hashLog;
|
||||||
|
if (comprParams->searchLog) params.cParams.searchLog = comprParams->searchLog;
|
||||||
|
if (comprParams->searchLength) params.cParams.searchLength = comprParams->searchLength;
|
||||||
|
if (comprParams->targetLength) params.cParams.targetLength = comprParams->targetLength;
|
||||||
|
if (comprParams->strategy) params.cParams.strategy = (ZSTD_strategy)(comprParams->strategy - 1);
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
{ size_t const errorCode = ZSTDMT_initCStream_advanced(ress.cctx, dictBuffer, dictBuffSize, params, srcSize);
|
||||||
|
if (ZSTD_isError(errorCode)) EXM_THROW(33, "Error initializing CStream : %s", ZSTD_getErrorName(errorCode));
|
||||||
|
ZSTDMT_setMTCtxParameter(ress.cctx, ZSTDMT_p_sectionSize, g_blockSize);
|
||||||
|
#else
|
||||||
{ size_t const errorCode = ZSTD_initCStream_advanced(ress.cctx, dictBuffer, dictBuffSize, params, srcSize);
|
{ size_t const errorCode = ZSTD_initCStream_advanced(ress.cctx, dictBuffer, dictBuffSize, params, srcSize);
|
||||||
if (ZSTD_isError(errorCode)) EXM_THROW(33, "Error initializing CStream : %s", ZSTD_getErrorName(errorCode));
|
if (ZSTD_isError(errorCode)) EXM_THROW(33, "Error initializing CStream : %s", ZSTD_getErrorName(errorCode));
|
||||||
|
#endif
|
||||||
} }
|
} }
|
||||||
free(dictBuffer);
|
free(dictBuffer);
|
||||||
}
|
}
|
||||||
@@ -281,7 +327,11 @@ static void FIO_freeCResources(cRess_t ress)
|
|||||||
{
|
{
|
||||||
free(ress.srcBuffer);
|
free(ress.srcBuffer);
|
||||||
free(ress.dstBuffer);
|
free(ress.dstBuffer);
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
ZSTDMT_freeCCtx(ress.cctx);
|
||||||
|
#else
|
||||||
ZSTD_freeCStream(ress.cctx); /* never fails */
|
ZSTD_freeCStream(ress.cctx); /* never fails */
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -300,7 +350,11 @@ static int FIO_compressFilename_internal(cRess_t ress,
|
|||||||
U64 const fileSize = UTIL_getFileSize(srcFileName);
|
U64 const fileSize = UTIL_getFileSize(srcFileName);
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
{ size_t const resetError = ZSTDMT_resetCStream(ress.cctx, fileSize);
|
||||||
|
#else
|
||||||
{ size_t const resetError = ZSTD_resetCStream(ress.cctx, fileSize);
|
{ size_t const resetError = ZSTD_resetCStream(ress.cctx, fileSize);
|
||||||
|
#endif
|
||||||
if (ZSTD_isError(resetError)) EXM_THROW(21, "Error initializing compression : %s", ZSTD_getErrorName(resetError));
|
if (ZSTD_isError(resetError)) EXM_THROW(21, "Error initializing compression : %s", ZSTD_getErrorName(resetError));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,33 +364,46 @@ static int FIO_compressFilename_internal(cRess_t ress,
|
|||||||
size_t const inSize = fread(ress.srcBuffer, (size_t)1, ress.srcBufferSize, srcFile);
|
size_t const inSize = fread(ress.srcBuffer, (size_t)1, ress.srcBufferSize, srcFile);
|
||||||
if (inSize==0) break;
|
if (inSize==0) break;
|
||||||
readsize += inSize;
|
readsize += inSize;
|
||||||
DISPLAYUPDATE(2, "\rRead : %u MB ", (U32)(readsize>>20));
|
|
||||||
|
|
||||||
/* Compress using buffered streaming */
|
|
||||||
{ ZSTD_inBuffer inBuff = { ress.srcBuffer, inSize, 0 };
|
{ ZSTD_inBuffer inBuff = { ress.srcBuffer, inSize, 0 };
|
||||||
ZSTD_outBuffer outBuff= { ress.dstBuffer, ress.dstBufferSize, 0 };
|
while (inBuff.pos != inBuff.size) { /* note : is there any possibility of endless loop ? for example, if outBuff is not large enough ? */
|
||||||
{ size_t const result = ZSTD_compressStream(ress.cctx, &outBuff, &inBuff);
|
ZSTD_outBuffer outBuff= { ress.dstBuffer, ress.dstBufferSize, 0 };
|
||||||
if (ZSTD_isError(result)) EXM_THROW(23, "Compression error : %s ", ZSTD_getErrorName(result)); }
|
#ifdef ZSTD_MULTITHREAD
|
||||||
if (inBuff.pos != inBuff.size)
|
size_t const result = ZSTDMT_compressStream(ress.cctx, &outBuff, &inBuff);
|
||||||
/* inBuff should be entirely consumed since buffer sizes are recommended ones */
|
#else
|
||||||
EXM_THROW(24, "Compression error : input block not fully consumed");
|
size_t const result = ZSTD_compressStream(ress.cctx, &outBuff, &inBuff);
|
||||||
|
#endif
|
||||||
|
if (ZSTD_isError(result)) EXM_THROW(23, "Compression error : %s ", ZSTD_getErrorName(result));
|
||||||
|
|
||||||
/* Write cBlock */
|
/* Write compressed stream */
|
||||||
{ size_t const sizeCheck = fwrite(ress.dstBuffer, 1, outBuff.pos, dstFile);
|
if (outBuff.pos) {
|
||||||
if (sizeCheck!=outBuff.pos) EXM_THROW(25, "Write error : cannot write compressed block into %s", dstFileName); }
|
size_t const sizeCheck = fwrite(ress.dstBuffer, 1, outBuff.pos, dstFile);
|
||||||
compressedfilesize += outBuff.pos;
|
if (sizeCheck!=outBuff.pos) EXM_THROW(25, "Write error : cannot write compressed block into %s", dstFileName);
|
||||||
}
|
compressedfilesize += outBuff.pos;
|
||||||
DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", (U32)(readsize>>20), (double)compressedfilesize/readsize*100);
|
} } }
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
if (!fileSize) DISPLAYUPDATE(2, "\rRead : %u MB", (U32)(readsize>>20))
|
||||||
|
else DISPLAYUPDATE(2, "\rRead : %u / %u MB", (U32)(readsize>>20), (U32)(fileSize>>20));
|
||||||
|
#else
|
||||||
|
if (!fileSize) DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%%", (U32)(readsize>>20), (double)compressedfilesize/readsize*100)
|
||||||
|
else DISPLAYUPDATE(2, "\rRead : %u / %u MB ==> %.2f%%", (U32)(readsize>>20), (U32)(fileSize>>20), (double)compressedfilesize/readsize*100);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End of Frame */
|
/* End of Frame */
|
||||||
{ ZSTD_outBuffer outBuff = { ress.dstBuffer, ress.dstBufferSize, 0 };
|
{ size_t result = 1;
|
||||||
size_t const result = ZSTD_endStream(ress.cctx, &outBuff);
|
while (result!=0) { /* note : is there any possibility of endless loop ? */
|
||||||
if (result!=0) EXM_THROW(26, "Compression error : cannot create frame end");
|
ZSTD_outBuffer outBuff = { ress.dstBuffer, ress.dstBufferSize, 0 };
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
{ size_t const sizeCheck = fwrite(ress.dstBuffer, 1, outBuff.pos, dstFile);
|
result = ZSTDMT_endStream(ress.cctx, &outBuff);
|
||||||
if (sizeCheck!=outBuff.pos) EXM_THROW(27, "Write error : cannot write frame end into %s", dstFileName); }
|
#else
|
||||||
compressedfilesize += outBuff.pos;
|
result = ZSTD_endStream(ress.cctx, &outBuff);
|
||||||
|
#endif
|
||||||
|
if (ZSTD_isError(result)) EXM_THROW(26, "Compression error during frame end : %s", ZSTD_getErrorName(result));
|
||||||
|
{ size_t const sizeCheck = fwrite(ress.dstBuffer, 1, outBuff.pos, dstFile);
|
||||||
|
if (sizeCheck!=outBuff.pos) EXM_THROW(27, "Write error : cannot write frame end into %s", dstFileName); }
|
||||||
|
compressedfilesize += outBuff.pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Status */
|
/* Status */
|
||||||
@@ -365,6 +432,7 @@ static int FIO_compressFilename_srcFile(cRess_t ress,
|
|||||||
DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
|
DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ress.srcFile = FIO_openSrcFile(srcFileName);
|
ress.srcFile = FIO_openSrcFile(srcFileName);
|
||||||
if (!ress.srcFile) return 1; /* srcFile could not be opened */
|
if (!ress.srcFile) return 1; /* srcFile could not be opened */
|
||||||
|
|
||||||
@@ -401,12 +469,12 @@ static int FIO_compressFilename_dstFile(cRess_t ress,
|
|||||||
|
|
||||||
|
|
||||||
int FIO_compressFilename(const char* dstFileName, const char* srcFileName,
|
int FIO_compressFilename(const char* dstFileName, const char* srcFileName,
|
||||||
const char* dictFileName, int compressionLevel)
|
const char* dictFileName, int compressionLevel, ZSTD_compressionParameters* comprParams)
|
||||||
{
|
{
|
||||||
clock_t const start = clock();
|
clock_t const start = clock();
|
||||||
U64 const srcSize = UTIL_getFileSize(srcFileName);
|
U64 const srcSize = UTIL_getFileSize(srcFileName);
|
||||||
|
|
||||||
cRess_t const ress = FIO_createCResources(dictFileName, compressionLevel, srcSize);
|
cRess_t const ress = FIO_createCResources(dictFileName, compressionLevel, srcSize, comprParams);
|
||||||
int const result = FIO_compressFilename_dstFile(ress, dstFileName, srcFileName);
|
int const result = FIO_compressFilename_dstFile(ress, dstFileName, srcFileName);
|
||||||
|
|
||||||
double const seconds = (double)(clock() - start) / CLOCKS_PER_SEC;
|
double const seconds = (double)(clock() - start) / CLOCKS_PER_SEC;
|
||||||
@@ -419,14 +487,15 @@ int FIO_compressFilename(const char* dstFileName, const char* srcFileName,
|
|||||||
|
|
||||||
int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFiles,
|
int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFiles,
|
||||||
const char* suffix,
|
const char* suffix,
|
||||||
const char* dictFileName, int compressionLevel)
|
const char* dictFileName, int compressionLevel,
|
||||||
|
ZSTD_compressionParameters* comprParams)
|
||||||
{
|
{
|
||||||
int missed_files = 0;
|
int missed_files = 0;
|
||||||
size_t dfnSize = FNSPACE;
|
size_t dfnSize = FNSPACE;
|
||||||
char* dstFileName = (char*)malloc(FNSPACE);
|
char* dstFileName = (char*)malloc(FNSPACE);
|
||||||
size_t const suffixSize = suffix ? strlen(suffix) : 0;
|
size_t const suffixSize = suffix ? strlen(suffix) : 0;
|
||||||
U64 const srcSize = (nbFiles != 1) ? 0 : UTIL_getFileSize(inFileNamesTable[0]) ;
|
U64 const srcSize = (nbFiles != 1) ? 0 : UTIL_getFileSize(inFileNamesTable[0]) ;
|
||||||
cRess_t ress = FIO_createCResources(dictFileName, compressionLevel, srcSize);
|
cRess_t ress = FIO_createCResources(dictFileName, compressionLevel, srcSize, comprParams);
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
if (dstFileName==NULL) EXM_THROW(27, "FIO_compressMultipleFilenames : allocation error for dstFileName");
|
if (dstFileName==NULL) EXM_THROW(27, "FIO_compressMultipleFilenames : allocation error for dstFileName");
|
||||||
@@ -484,7 +553,7 @@ static dRess_t FIO_createDResources(const char* dictFileName)
|
|||||||
/* Allocation */
|
/* Allocation */
|
||||||
ress.dctx = ZSTD_createDStream();
|
ress.dctx = ZSTD_createDStream();
|
||||||
if (ress.dctx==NULL) EXM_THROW(60, "Can't create ZSTD_DStream");
|
if (ress.dctx==NULL) EXM_THROW(60, "Can't create ZSTD_DStream");
|
||||||
ZSTD_setDStreamParameter(ress.dctx, ZSTDdsp_maxWindowSize, g_memLimit);
|
ZSTD_setDStreamParameter(ress.dctx, DStream_p_maxWindowSize, g_memLimit);
|
||||||
ress.srcBufferSize = ZSTD_DStreamInSize();
|
ress.srcBufferSize = ZSTD_DStreamInSize();
|
||||||
ress.srcBuffer = malloc(ress.srcBufferSize);
|
ress.srcBuffer = malloc(ress.srcBufferSize);
|
||||||
ress.dstBufferSize = ZSTD_DStreamOutSize();
|
ress.dstBufferSize = ZSTD_DStreamOutSize();
|
||||||
@@ -635,7 +704,7 @@ unsigned long long FIO_decompressFrame(dRess_t* ress,
|
|||||||
if (ZSTD_isError(readSizeHint)) EXM_THROW(36, "Decoding error : %s", ZSTD_getErrorName(readSizeHint));
|
if (ZSTD_isError(readSizeHint)) EXM_THROW(36, "Decoding error : %s", ZSTD_getErrorName(readSizeHint));
|
||||||
|
|
||||||
/* Write block */
|
/* Write block */
|
||||||
storedSkips = FIO_fwriteSparse(ress->dstFile, ress->dstBuffer, outBuff.pos, storedSkips);
|
storedSkips = FIO_fwriteSparse(ress->dstFile, ress->dstBuffer, outBuff.pos, storedSkips);
|
||||||
frameSize += outBuff.pos;
|
frameSize += outBuff.pos;
|
||||||
DISPLAYUPDATE(2, "\rDecoded : %u MB... ", (U32)((alreadyDecoded+frameSize)>>20) );
|
DISPLAYUPDATE(2, "\rDecoded : %u MB... ", (U32)((alreadyDecoded+frameSize)>>20) );
|
||||||
|
|
||||||
@@ -673,9 +742,9 @@ static unsigned long long FIO_decompressGzFrame(dRess_t* ress, FILE* srcFile, co
|
|||||||
strm.avail_in = Z_NULL;
|
strm.avail_in = Z_NULL;
|
||||||
if (inflateInit2(&strm, 15 /* maxWindowLogSize */ + 16 /* gzip only */) != Z_OK) return 0; /* see http://www.zlib.net/manual.html */
|
if (inflateInit2(&strm, 15 /* maxWindowLogSize */ + 16 /* gzip only */) != Z_OK) return 0; /* see http://www.zlib.net/manual.html */
|
||||||
|
|
||||||
strm.next_out = ress->dstBuffer;
|
strm.next_out = (Bytef*)ress->dstBuffer;
|
||||||
strm.avail_out = ress->dstBufferSize;
|
strm.avail_out = (uInt)ress->dstBufferSize;
|
||||||
strm.avail_in = ress->srcBufferLoaded;
|
strm.avail_in = (uInt)ress->srcBufferLoaded;
|
||||||
strm.next_in = (z_const unsigned char*)ress->srcBuffer;
|
strm.next_in = (z_const unsigned char*)ress->srcBuffer;
|
||||||
|
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
@@ -684,7 +753,7 @@ static unsigned long long FIO_decompressGzFrame(dRess_t* ress, FILE* srcFile, co
|
|||||||
ress->srcBufferLoaded = fread(ress->srcBuffer, 1, ress->srcBufferSize, srcFile);
|
ress->srcBufferLoaded = fread(ress->srcBuffer, 1, ress->srcBufferSize, srcFile);
|
||||||
if (ress->srcBufferLoaded == 0) break;
|
if (ress->srcBufferLoaded == 0) break;
|
||||||
strm.next_in = (z_const unsigned char*)ress->srcBuffer;
|
strm.next_in = (z_const unsigned char*)ress->srcBuffer;
|
||||||
strm.avail_in = ress->srcBufferLoaded;
|
strm.avail_in = (uInt)ress->srcBufferLoaded;
|
||||||
}
|
}
|
||||||
ret = inflate(&strm, Z_NO_FLUSH);
|
ret = inflate(&strm, Z_NO_FLUSH);
|
||||||
if (ret != Z_OK && ret != Z_STREAM_END) { DISPLAY("zstd: %s: inflate error %d \n", srcFileName, ret); return 0; }
|
if (ret != Z_OK && ret != Z_STREAM_END) { DISPLAY("zstd: %s: inflate error %d \n", srcFileName, ret); return 0; }
|
||||||
@@ -692,8 +761,8 @@ static unsigned long long FIO_decompressGzFrame(dRess_t* ress, FILE* srcFile, co
|
|||||||
if (decompBytes) {
|
if (decompBytes) {
|
||||||
if (fwrite(ress->dstBuffer, 1, decompBytes, ress->dstFile) != decompBytes) EXM_THROW(31, "Write error : cannot write to output file");
|
if (fwrite(ress->dstBuffer, 1, decompBytes, ress->dstFile) != decompBytes) EXM_THROW(31, "Write error : cannot write to output file");
|
||||||
outFileSize += decompBytes;
|
outFileSize += decompBytes;
|
||||||
strm.next_out = ress->dstBuffer;
|
strm.next_out = (Bytef*)ress->dstBuffer;
|
||||||
strm.avail_out = ress->dstBufferSize;
|
strm.avail_out = (uInt)ress->dstBufferSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret == Z_STREAM_END) break;
|
if (ret == Z_STREAM_END) break;
|
||||||
|
|||||||
+11
-2
@@ -11,10 +11,14 @@
|
|||||||
#ifndef FILEIO_H_23981798732
|
#ifndef FILEIO_H_23981798732
|
||||||
#define FILEIO_H_23981798732
|
#define FILEIO_H_23981798732
|
||||||
|
|
||||||
|
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */
|
||||||
|
#include "zstd.h" /* ZSTD_* */
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* *************************************
|
/* *************************************
|
||||||
* Special i/o constants
|
* Special i/o constants
|
||||||
**************************************/
|
**************************************/
|
||||||
@@ -37,6 +41,9 @@ void FIO_setDictIDFlag(unsigned dictIDFlag);
|
|||||||
void FIO_setChecksumFlag(unsigned checksumFlag);
|
void FIO_setChecksumFlag(unsigned checksumFlag);
|
||||||
void FIO_setRemoveSrcFile(unsigned flag);
|
void FIO_setRemoveSrcFile(unsigned flag);
|
||||||
void FIO_setMemLimit(unsigned memLimit);
|
void FIO_setMemLimit(unsigned memLimit);
|
||||||
|
void FIO_setNbThreads(unsigned nbThreads);
|
||||||
|
void FIO_setBlockSize(unsigned blockSize);
|
||||||
|
void FIO_setOverlapLog(unsigned overlapLog);
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************
|
/*-*************************************
|
||||||
@@ -44,7 +51,8 @@ void FIO_setMemLimit(unsigned memLimit);
|
|||||||
***************************************/
|
***************************************/
|
||||||
/** FIO_compressFilename() :
|
/** FIO_compressFilename() :
|
||||||
@return : 0 == ok; 1 == pb with src file. */
|
@return : 0 == ok; 1 == pb with src file. */
|
||||||
int FIO_compressFilename (const char* outfilename, const char* infilename, const char* dictFileName, int compressionLevel);
|
int FIO_compressFilename (const char* outfilename, const char* infilename, const char* dictFileName,
|
||||||
|
int compressionLevel, ZSTD_compressionParameters* comprParams);
|
||||||
|
|
||||||
/** FIO_decompressFilename() :
|
/** FIO_decompressFilename() :
|
||||||
@return : 0 == ok; 1 == pb with src file. */
|
@return : 0 == ok; 1 == pb with src file. */
|
||||||
@@ -58,7 +66,8 @@ int FIO_decompressFilename (const char* outfilename, const char* infilename, con
|
|||||||
@return : nb of missing files */
|
@return : nb of missing files */
|
||||||
int FIO_compressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles,
|
int FIO_compressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles,
|
||||||
const char* suffix,
|
const char* suffix,
|
||||||
const char* dictFileName, int compressionLevel);
|
const char* dictFileName, int compressionLevel,
|
||||||
|
ZSTD_compressionParameters* comprParams);
|
||||||
|
|
||||||
/** FIO_decompressMultipleFilenames() :
|
/** FIO_decompressMultipleFilenames() :
|
||||||
@return : nb of missing or skipped files */
|
@return : nb of missing or skipped files */
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
/**
|
||||||
|
* platform.h - compiler and OS detection
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PLATFORM_H_MODULE
|
||||||
|
#define PLATFORM_H_MODULE
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* **************************************
|
||||||
|
* Compiler Options
|
||||||
|
****************************************/
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define _CRT_SECURE_NO_WARNINGS /* Disable Visual Studio warning messages for fopen, strncpy, strerror */
|
||||||
|
# define _CRT_SECURE_NO_DEPRECATE /* VS2005 - must be declared before <io.h> and <windows.h> */
|
||||||
|
# if (_MSC_VER <= 1800) /* (1800 = Visual Studio 2013) */
|
||||||
|
# define snprintf sprintf_s /* snprintf unsupported by Visual <= 2013 */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* **************************************
|
||||||
|
* Detect 64-bit OS
|
||||||
|
* http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros
|
||||||
|
****************************************/
|
||||||
|
#if defined __ia64 || defined _M_IA64 /* Intel Itanium */ \
|
||||||
|
|| defined __powerpc64__ || defined __ppc64__ || defined __PPC64__ /* POWER 64-bit */ \
|
||||||
|
|| (defined __sparc && (defined __sparcv9 || defined __sparc_v9__ || defined __arch64__)) || defined __sparc64__ /* SPARC 64-bit */ \
|
||||||
|
|| defined __x86_64__s || defined _M_X64 /* x86 64-bit */ \
|
||||||
|
|| defined __arm64__ || defined __aarch64__ || defined __ARM64_ARCH_8__ /* ARM 64-bit */ \
|
||||||
|
|| (defined __mips && (__mips == 64 || __mips == 4 || __mips == 3)) /* MIPS 64-bit */ \
|
||||||
|
|| defined _LP64 || defined __LP64__ /* NetBSD, OpenBSD */ || defined __64BIT__ /* AIX */ || defined _ADDR64 /* Cray */ \
|
||||||
|
|| (defined __SIZEOF_POINTER__ && __SIZEOF_POINTER__ == 8) /* gcc */
|
||||||
|
# if !defined(__64BIT__)
|
||||||
|
# define __64BIT__ 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* *********************************************************
|
||||||
|
* Turn on Large Files support (>4GB) for 32-bit Linux/Unix
|
||||||
|
***********************************************************/
|
||||||
|
#if !defined(__64BIT__) /* No point defining Large file for 64 bit */
|
||||||
|
# if !defined(_FILE_OFFSET_BITS)
|
||||||
|
# define _FILE_OFFSET_BITS 64 /* turn off_t into a 64-bit type for ftello, fseeko */
|
||||||
|
# endif
|
||||||
|
# if !defined(_LARGEFILE_SOURCE) /* obsolete macro, replaced with _FILE_OFFSET_BITS */
|
||||||
|
# define _LARGEFILE_SOURCE 1 /* Large File Support extension (LFS) - fseeko, ftello */
|
||||||
|
# endif
|
||||||
|
# if defined(_AIX) || defined(__hpux)
|
||||||
|
# define _LARGE_FILES /* Large file support on 32-bits AIX and HP-UX */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ************************************************************
|
||||||
|
* Detect POSIX version
|
||||||
|
* PLATFORM_POSIX_VERSION = -1 for non-Unix e.g. Windows
|
||||||
|
* PLATFORM_POSIX_VERSION = 0 for Unix-like non-POSIX
|
||||||
|
* PLATFORM_POSIX_VERSION >= 1 is equal to found _POSIX_VERSION
|
||||||
|
***************************************************************/
|
||||||
|
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) /* UNIX-like OS */ \
|
||||||
|
|| defined(__midipix__) || defined(__VMS))
|
||||||
|
# if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1–2001 (SUSv3) conformant */ \
|
||||||
|
|| defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) /* BSD distros */
|
||||||
|
# define PLATFORM_POSIX_VERSION 200112L
|
||||||
|
# else
|
||||||
|
# if defined(__linux__) || defined(__linux)
|
||||||
|
# define _POSIX_C_SOURCE 200112L /* use feature test macro */
|
||||||
|
# endif
|
||||||
|
# include <unistd.h> /* declares _POSIX_VERSION */
|
||||||
|
# if defined(_POSIX_VERSION) /* POSIX compliant */
|
||||||
|
# define PLATFORM_POSIX_VERSION _POSIX_VERSION
|
||||||
|
# else
|
||||||
|
# define PLATFORM_POSIX_VERSION 0
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if !defined(PLATFORM_POSIX_VERSION)
|
||||||
|
# define PLATFORM_POSIX_VERSION -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*-*********************************************
|
||||||
|
* Detect if isatty() and fileno() are available
|
||||||
|
************************************************/
|
||||||
|
#if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 1)) || (PLATFORM_POSIX_VERSION >= 200112L) || defined(__DJGPP__)
|
||||||
|
# include <unistd.h> /* isatty */
|
||||||
|
# define IS_CONSOLE(stdStream) isatty(fileno(stdStream))
|
||||||
|
#elif defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
|
||||||
|
# include <io.h> /* _isatty */
|
||||||
|
# define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
|
||||||
|
#else
|
||||||
|
# define IS_CONSOLE(stdStream) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* OS-specific Includes
|
||||||
|
******************************/
|
||||||
|
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32)
|
||||||
|
# include <fcntl.h> /* _O_BINARY */
|
||||||
|
# include <io.h> /* _setmode, _fileno, _get_osfhandle */
|
||||||
|
# if !defined(__DJGPP__)
|
||||||
|
# include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
|
||||||
|
# include <winioctl.h> /* FSCTL_SET_SPARSE */
|
||||||
|
# define SET_BINARY_MODE(file) { int unused=_setmode(_fileno(file), _O_BINARY); (void)unused; }
|
||||||
|
# define SET_SPARSE_FILE_MODE(file) { DWORD dw; DeviceIoControl((HANDLE) _get_osfhandle(_fileno(file)), FSCTL_SET_SPARSE, 0, 0, 0, 0, &dw, 0); }
|
||||||
|
# else
|
||||||
|
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
|
||||||
|
# define SET_SPARSE_FILE_MODE(file)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define SET_BINARY_MODE(file)
|
||||||
|
# define SET_SPARSE_FILE_MODE(file)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PLATFORM_H_MODULE */
|
||||||
+63
-75
@@ -1,4 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
|
* util.h - utility functions
|
||||||
|
*
|
||||||
* Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
|
* Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -14,50 +16,57 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* **************************************
|
|
||||||
* Compiler Options
|
|
||||||
****************************************/
|
|
||||||
#if defined(__INTEL_COMPILER)
|
|
||||||
# pragma warning(disable : 177) /* disable: message #177: function was declared but never referenced */
|
|
||||||
#endif
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
# define _CRT_SECURE_NO_WARNINGS /* Disable some Visual warning messages for fopen, strncpy */
|
|
||||||
# define _CRT_SECURE_NO_DEPRECATE /* VS2005 */
|
|
||||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
|
||||||
#if _MSC_VER <= 1800 /* (1800 = Visual Studio 2013) */
|
|
||||||
# define snprintf sprintf_s /* snprintf unsupported by Visual <= 2013 */
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Unix Large Files support (>4GB) */
|
|
||||||
#if !defined(__LP64__) /* No point defining Large file for 64 bit */
|
|
||||||
# define _FILE_OFFSET_BITS 64 /* turn off_t into a 64-bit type for ftello, fseeko */
|
|
||||||
# if defined(__sun__) && !defined(_LARGEFILE_SOURCE) /* Sun Solaris 32-bits requires specific definitions */
|
|
||||||
# define _LARGEFILE_SOURCE /* fseeko, ftello */
|
|
||||||
# elif !defined(_LARGEFILE64_SOURCE)
|
|
||||||
# define _LARGEFILE64_SOURCE /* off64_t, fseeko64, ftello64 */
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*-****************************************
|
/*-****************************************
|
||||||
* Dependencies
|
* Dependencies
|
||||||
******************************************/
|
******************************************/
|
||||||
#include <stdlib.h> /* features.h with _POSIX_C_SOURCE, malloc */
|
#include "platform.h" /* PLATFORM_POSIX_VERSION */
|
||||||
#include <stdio.h> /* fprintf */
|
#include <stdlib.h> /* malloc */
|
||||||
#include <sys/types.h> /* stat, utime */
|
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||||
#include <sys/stat.h> /* stat */
|
#include <stdio.h> /* fprintf */
|
||||||
|
#include <sys/types.h> /* stat, utime */
|
||||||
|
#include <sys/stat.h> /* stat */
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# include <sys/utime.h> /* utime */
|
# include <sys/utime.h> /* utime */
|
||||||
# include <io.h> /* _chmod */
|
# include <io.h> /* _chmod */
|
||||||
#else
|
#else
|
||||||
# include <unistd.h> /* chown, stat */
|
# include <unistd.h> /* chown, stat */
|
||||||
# include <utime.h> /* utime */
|
# include <utime.h> /* utime */
|
||||||
#endif
|
#endif
|
||||||
#include <time.h> /* time */
|
#include <time.h> /* time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "mem.h" /* U32, U64 */
|
#include "mem.h" /* U32, U64 */
|
||||||
|
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* Sleep functions: Windows - Posix - others
|
||||||
|
******************************************/
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# include <windows.h>
|
||||||
|
# define SET_HIGH_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)
|
||||||
|
# define UTIL_sleep(s) Sleep(1000*s)
|
||||||
|
# define UTIL_sleepMilli(milli) Sleep(milli)
|
||||||
|
#elif PLATFORM_POSIX_VERSION >= 0 /* Unix-like operating system */
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <sys/resource.h> /* setpriority */
|
||||||
|
# include <time.h> /* clock_t, nanosleep, clock, CLOCKS_PER_SEC */
|
||||||
|
# if defined(PRIO_PROCESS)
|
||||||
|
# define SET_HIGH_PRIORITY setpriority(PRIO_PROCESS, 0, -20)
|
||||||
|
# else
|
||||||
|
# define SET_HIGH_PRIORITY /* disabled */
|
||||||
|
# endif
|
||||||
|
# define UTIL_sleep(s) sleep(s)
|
||||||
|
# if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 199309L)) || (PLATFORM_POSIX_VERSION >= 200112L) /* nanosleep requires POSIX.1-2001 */
|
||||||
|
# define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); }
|
||||||
|
# else
|
||||||
|
# define UTIL_sleepMilli(milli) /* disabled */
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define SET_HIGH_PRIORITY /* disabled */
|
||||||
|
# define UTIL_sleep(s) /* disabled */
|
||||||
|
# define UTIL_sleepMilli(milli) /* disabled */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* *************************************
|
/* *************************************
|
||||||
@@ -69,6 +78,9 @@ extern "C" {
|
|||||||
/*-****************************************
|
/*-****************************************
|
||||||
* Compiler specifics
|
* Compiler specifics
|
||||||
******************************************/
|
******************************************/
|
||||||
|
#if defined(__INTEL_COMPILER)
|
||||||
|
# pragma warning(disable : 177) /* disable: message #177: function was declared but never referenced, useful with UTIL_STATIC */
|
||||||
|
#endif
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
# define UTIL_STATIC static __attribute__((unused))
|
# define UTIL_STATIC static __attribute__((unused))
|
||||||
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||||
@@ -80,51 +92,29 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*-****************************************
|
|
||||||
* Sleep functions: Windows - Posix - others
|
|
||||||
******************************************/
|
|
||||||
#if defined(_WIN32)
|
|
||||||
# include <windows.h>
|
|
||||||
# define SET_HIGH_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)
|
|
||||||
# define UTIL_sleep(s) Sleep(1000*s)
|
|
||||||
# define UTIL_sleepMilli(milli) Sleep(milli)
|
|
||||||
#elif (defined(__unix__) || defined(__unix) || defined(__VMS) || defined(__midipix__) || (defined(__APPLE__) && defined(__MACH__)))
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <sys/resource.h> /* setpriority */
|
|
||||||
# include <time.h> /* clock_t, nanosleep, clock, CLOCKS_PER_SEC */
|
|
||||||
# if defined(PRIO_PROCESS)
|
|
||||||
# define SET_HIGH_PRIORITY setpriority(PRIO_PROCESS, 0, -20)
|
|
||||||
# else
|
|
||||||
# define SET_HIGH_PRIORITY /* disabled */
|
|
||||||
# endif
|
|
||||||
# define UTIL_sleep(s) sleep(s)
|
|
||||||
# if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L))
|
|
||||||
# define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); }
|
|
||||||
# else
|
|
||||||
# define UTIL_sleepMilli(milli) /* disabled */
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define SET_HIGH_PRIORITY /* disabled */
|
|
||||||
# define UTIL_sleep(s) /* disabled */
|
|
||||||
# define UTIL_sleepMilli(milli) /* disabled */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*-****************************************
|
/*-****************************************
|
||||||
* Time functions
|
* Time functions
|
||||||
******************************************/
|
******************************************/
|
||||||
#if !defined(_WIN32)
|
#if (PLATFORM_POSIX_VERSION >= 1)
|
||||||
typedef clock_t UTIL_time_t;
|
#include <unistd.h>
|
||||||
UTIL_STATIC void UTIL_initTimer(UTIL_time_t* ticksPerSecond) { *ticksPerSecond=0; }
|
#include <sys/times.h> /* times */
|
||||||
UTIL_STATIC void UTIL_getTime(UTIL_time_t* x) { *x = clock(); }
|
typedef U64 UTIL_time_t;
|
||||||
UTIL_STATIC U64 UTIL_getSpanTimeMicro(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { (void)ticksPerSecond; return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
|
UTIL_STATIC void UTIL_initTimer(UTIL_time_t* ticksPerSecond) { *ticksPerSecond=sysconf(_SC_CLK_TCK); }
|
||||||
UTIL_STATIC U64 UTIL_getSpanTimeNano(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { (void)ticksPerSecond; return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
|
UTIL_STATIC void UTIL_getTime(UTIL_time_t* x) { struct tms junk; clock_t newTicks = (clock_t) times(&junk); (void)junk; *x = (UTIL_time_t)newTicks; }
|
||||||
#else
|
UTIL_STATIC U64 UTIL_getSpanTimeMicro(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / ticksPerSecond; }
|
||||||
|
UTIL_STATIC U64 UTIL_getSpanTimeNano(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / ticksPerSecond; }
|
||||||
|
#elif defined(_WIN32) /* Windows */
|
||||||
typedef LARGE_INTEGER UTIL_time_t;
|
typedef LARGE_INTEGER UTIL_time_t;
|
||||||
UTIL_STATIC void UTIL_initTimer(UTIL_time_t* ticksPerSecond) { if (!QueryPerformanceFrequency(ticksPerSecond)) fprintf(stderr, "ERROR: QueryPerformance not present\n"); }
|
UTIL_STATIC void UTIL_initTimer(UTIL_time_t* ticksPerSecond) { if (!QueryPerformanceFrequency(ticksPerSecond)) fprintf(stderr, "ERROR: QueryPerformance not present\n"); }
|
||||||
UTIL_STATIC void UTIL_getTime(UTIL_time_t* x) { QueryPerformanceCounter(x); }
|
UTIL_STATIC void UTIL_getTime(UTIL_time_t* x) { QueryPerformanceCounter(x); }
|
||||||
UTIL_STATIC U64 UTIL_getSpanTimeMicro(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart; }
|
UTIL_STATIC U64 UTIL_getSpanTimeMicro(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart; }
|
||||||
UTIL_STATIC U64 UTIL_getSpanTimeNano(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart; }
|
UTIL_STATIC U64 UTIL_getSpanTimeNano(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart; }
|
||||||
|
#else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */
|
||||||
|
typedef clock_t UTIL_time_t;
|
||||||
|
UTIL_STATIC void UTIL_initTimer(UTIL_time_t* ticksPerSecond) { *ticksPerSecond=0; }
|
||||||
|
UTIL_STATIC void UTIL_getTime(UTIL_time_t* x) { *x = clock(); }
|
||||||
|
UTIL_STATIC U64 UTIL_getSpanTimeMicro(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { (void)ticksPerSecond; return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
|
||||||
|
UTIL_STATIC U64 UTIL_getSpanTimeNano(UTIL_time_t ticksPerSecond, UTIL_time_t clockStart, UTIL_time_t clockEnd) { (void)ticksPerSecond; return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -325,12 +315,10 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
|
|||||||
return nbFiles;
|
return nbFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) || \
|
#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */
|
||||||
(defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) || \
|
|
||||||
defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
|
||||||
(defined(__linux__) && defined(_POSIX_C_SOURCE)) /* opendir */
|
|
||||||
# define UTIL_HAS_CREATEFILELIST
|
# define UTIL_HAS_CREATEFILELIST
|
||||||
# include <dirent.h> /* opendir, readdir */
|
# include <dirent.h> /* opendir, readdir */
|
||||||
|
# include <string.h> /* strerror, memcpy */
|
||||||
|
|
||||||
UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd)
|
UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd)
|
||||||
{
|
{
|
||||||
@@ -392,7 +380,7 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
|
|||||||
UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd)
|
UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd)
|
||||||
{
|
{
|
||||||
(void)bufStart; (void)bufEnd; (void)pos;
|
(void)bufStart; (void)bufEnd; (void)pos;
|
||||||
fprintf(stderr, "Directory %s ignored (zstd compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName);
|
fprintf(stderr, "Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+137
-1
@@ -69,6 +69,8 @@ from standard input if it is a terminal.
|
|||||||
.PP
|
.PP
|
||||||
Unless
|
Unless
|
||||||
.B \-\-stdout
|
.B \-\-stdout
|
||||||
|
or
|
||||||
|
.B \-o
|
||||||
is specified,
|
is specified,
|
||||||
.I files
|
.I files
|
||||||
are written to a new file whose name is derived from the source
|
are written to a new file whose name is derived from the source
|
||||||
@@ -159,7 +161,8 @@ No files are created or removed.
|
|||||||
# compression level [1-19] (default:3)
|
# compression level [1-19] (default:3)
|
||||||
.TP
|
.TP
|
||||||
.BR \--ultra
|
.BR \--ultra
|
||||||
unlocks high compression levels 20+ (maximum 22), using a lot more memory
|
unlocks high compression levels 20+ (maximum 22), using a lot more memory.
|
||||||
|
Note that decompression will also require more memory when using these levels.
|
||||||
.TP
|
.TP
|
||||||
.B \-D file
|
.B \-D file
|
||||||
use `file` as Dictionary to compress or decompress FILE(s)
|
use `file` as Dictionary to compress or decompress FILE(s)
|
||||||
@@ -248,6 +251,30 @@ and weight typically 100x the target dictionary size (for example, 10 MB for a 1
|
|||||||
.B \-s#
|
.B \-s#
|
||||||
dictionary selectivity level (default: 9)
|
dictionary selectivity level (default: 9)
|
||||||
the smaller the value, the denser the dictionary, improving its efficiency but reducing its possible maximum size.
|
the smaller the value, the denser the dictionary, improving its efficiency but reducing its possible maximum size.
|
||||||
|
.TP
|
||||||
|
.B \--cover=k=#,d=#
|
||||||
|
Use alternate dictionary builder algorithm named cover with parameters \fIk\fR and \fId\fR with \fId\fR <= \fIk\fR.
|
||||||
|
Selects segments of size \fIk\fR with the highest score to put in the dictionary.
|
||||||
|
The score of a segment is computed by the sum of the frequencies of all the subsegments of of size \fId\fR.
|
||||||
|
Generally \fId\fR should be in the range [6, 24].
|
||||||
|
Good values for \fIk\fR vary widely based on the input data, but a safe range is [32, 2048].
|
||||||
|
Example: \fB--train --cover=k=64,d=8 FILEs\fR.
|
||||||
|
.TP
|
||||||
|
.B \--optimize-cover[=steps=#,k=#,d=#]
|
||||||
|
If \fIsteps\fR is not specified, the default value of 32 is used.
|
||||||
|
If \fIk\fR is not specified, \fIsteps\fR values in [16, 2048] are checked for each value of \fId\fR.
|
||||||
|
If \fId\fR is not specified, the values checked are [6, 8, ..., 16].
|
||||||
|
|
||||||
|
Runs the cover dictionary builder for each parameter set saves the optimal parameters and dictionary.
|
||||||
|
Prints the optimal parameters and writes the optimal dictionary to the output file.
|
||||||
|
Supports multithreading if \fBzstd\fR is compiled with threading support.
|
||||||
|
|
||||||
|
The parameter \fIk\fR is more sensitve than \fId\fR, and is faster to optimize over.
|
||||||
|
Suggested use is to run with a \fIsteps\fR <= 32 with neither \fIk\fR nor \fId\fR set.
|
||||||
|
Once it completes, use the value of \fId\fR it selects with a higher \fIsteps\fR (in the range [256, 1024]).
|
||||||
|
\fBzstd --train --optimize-cover FILEs
|
||||||
|
\fBzstd --train --optimize-cover=d=d,steps=512 FILEs
|
||||||
|
.TP
|
||||||
|
|
||||||
.SH BENCHMARK
|
.SH BENCHMARK
|
||||||
.TP
|
.TP
|
||||||
@@ -264,6 +291,115 @@ and weight typically 100x the target dictionary size (for example, 10 MB for a 1
|
|||||||
cut file into independent blocks of size # (default: no block)
|
cut file into independent blocks of size # (default: no block)
|
||||||
|
|
||||||
|
|
||||||
|
.SH ADVANCED COMPRESSION OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \--zstd[=\fIoptions\fR]
|
||||||
|
.PD
|
||||||
|
\fBzstd\fR provides 22 predefined compression levels. The selected or default predefined compression level can be changed with advanced compression options.
|
||||||
|
The \fIoptions\fR are provided as a comma-separated list. You may specify only the \fIoptions\fR you want to change and the rest will be taken from the selected or default compression level.
|
||||||
|
The list of available \fIoptions\fR:
|
||||||
|
.RS
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI strategy= strat
|
||||||
|
.PD 0
|
||||||
|
.TP
|
||||||
|
.BI strat= strat
|
||||||
|
.PD
|
||||||
|
Specify a strategy used by a match finder.
|
||||||
|
.IP ""
|
||||||
|
There are 8 strategies numbered from 0 to 7, from faster to stronger:
|
||||||
|
0=ZSTD_fast, 1=ZSTD_dfast, 2=ZSTD_greedy, 3=ZSTD_lazy, 4=ZSTD_lazy2, 5=ZSTD_btlazy2, 6=ZSTD_btopt, 7=ZSTD_btopt2.
|
||||||
|
.IP ""
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI windowLog= wlog
|
||||||
|
.PD 0
|
||||||
|
.TP
|
||||||
|
.BI wlog= wlog
|
||||||
|
.PD
|
||||||
|
Specify the maximum number of bits for a match distance.
|
||||||
|
.IP ""
|
||||||
|
The higher number of bits increases the chance to find a match what usually improves compression ratio.
|
||||||
|
It also increases memory requirements for compressor and decompressor.
|
||||||
|
.IP ""
|
||||||
|
The minimum \fIwlog\fR is 10 (1 KiB) and the maximum is 25 (32 MiB) for 32-bit compilation and 27 (128 MiB) for 64-bit compilation.
|
||||||
|
.IP ""
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI hashLog= hlog
|
||||||
|
.PD 0
|
||||||
|
.TP
|
||||||
|
.BI hlog= hlog
|
||||||
|
.PD
|
||||||
|
Specify the maximum number of bits for a hash table.
|
||||||
|
.IP ""
|
||||||
|
The bigger hash table causes less collisions what usually make compression faster but requires more memory during compression.
|
||||||
|
.IP ""
|
||||||
|
The minimum \fIhlog\fR is 6 (64 B) and the maximum is 25 (32 MiB) for 32-bit compilation and 27 (128 MiB) for 64-bit compilation.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI chainLog= clog
|
||||||
|
.PD 0
|
||||||
|
.TP
|
||||||
|
.BI clog= clog
|
||||||
|
.PD
|
||||||
|
Specify the maximum number of bits for a hash chain or a binary tree.
|
||||||
|
.IP ""
|
||||||
|
The higher number of bits increases the chance to find a match what usually improves compression ratio.
|
||||||
|
It also slows down compression speed and increases memory requirements for compression.
|
||||||
|
This option is ignored for the ZSTD_fast strategy.
|
||||||
|
.IP ""
|
||||||
|
The minimum \fIclog\fR is 6 (64 B) and the maximum is 26 (64 MiB) for 32-bit compilation and 28 (256 MiB) for 64-bit compilation.
|
||||||
|
.IP ""
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI searchLog= slog
|
||||||
|
.PD 0
|
||||||
|
.TP
|
||||||
|
.BI slog= slog
|
||||||
|
.PD
|
||||||
|
Specify the maximum number of searches in a hash chain or a binary tree using logarithmic scale.
|
||||||
|
.IP ""
|
||||||
|
The bigger number of searches increases the chance to find a match what usually improves compression ratio but decreases compression speed.
|
||||||
|
.IP ""
|
||||||
|
The minimum \fIslog\fR is 1 and the maximum is 24 for 32-bit compilation and 26 for 64-bit compilation.
|
||||||
|
.IP ""
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI searchLength= slen
|
||||||
|
.PD 0
|
||||||
|
.TP
|
||||||
|
.BI slen= slen
|
||||||
|
.PD
|
||||||
|
Specify the minimum searched length of a match in a hash table.
|
||||||
|
.IP ""
|
||||||
|
The bigger search length usually decreases compression ratio but improves decompression speed.
|
||||||
|
.IP ""
|
||||||
|
The minimum \fIslen\fR is 3 and the maximum is 7.
|
||||||
|
.IP ""
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI targetLength= tlen
|
||||||
|
.PD 0
|
||||||
|
.TP
|
||||||
|
.BI tlen= tlen
|
||||||
|
.PD
|
||||||
|
Specify the minimum match length that causes a match finder to interrupt searching of better matches.
|
||||||
|
.IP ""
|
||||||
|
The bigger minimum match length usually improves compression ratio but decreases compression speed.
|
||||||
|
This option is used only with ZSTD_btopt and ZSTD_btopt2 strategies.
|
||||||
|
.IP ""
|
||||||
|
The minimum \fItlen\fR is 4 and the maximum is 999.
|
||||||
|
.IP ""
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.B An example
|
||||||
|
.br
|
||||||
|
The following parameters sets advanced compression options to predefined level 19 for files bigger than 256 KB:
|
||||||
|
.IP ""
|
||||||
|
\fB--zstd=\fRwindowLog=23,chainLog=23,hashLog=22,searchLog=6,searchLength=3,targetLength=48,strategy=6
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Report bugs at:- https://github.com/facebook/zstd/issues
|
Report bugs at:- https://github.com/facebook/zstd/issues
|
||||||
|
|
||||||
|
|||||||
+143
-45
@@ -20,10 +20,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Dependencies
|
* Dependencies
|
||||||
**************************************/
|
**************************************/
|
||||||
#include "util.h" /* Compiler options, UTIL_HAS_CREATEFILELIST */
|
#include "platform.h" /* IS_CONSOLE, PLATFORM_POSIX_VERSION */
|
||||||
|
#include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
|
||||||
#include <string.h> /* strcmp, strlen */
|
#include <string.h> /* strcmp, strlen */
|
||||||
#include <errno.h> /* errno */
|
#include <errno.h> /* errno */
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
@@ -37,21 +39,6 @@
|
|||||||
#include "zstd.h" /* ZSTD_VERSION_STRING */
|
#include "zstd.h" /* ZSTD_VERSION_STRING */
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
|
||||||
* OS-specific Includes
|
|
||||||
**************************************/
|
|
||||||
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
|
|
||||||
# include <io.h> /* _isatty */
|
|
||||||
# define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
|
|
||||||
#elif defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) || (defined(__APPLE__) && defined(__MACH__)) || \
|
|
||||||
defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) /* https://sourceforge.net/p/predef/wiki/OperatingSystems/ */
|
|
||||||
# include <unistd.h> /* isatty */
|
|
||||||
# define IS_CONSOLE(stdStream) isatty(fileno(stdStream))
|
|
||||||
#else
|
|
||||||
# define IS_CONSOLE(stdStream) 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Constants
|
* Constants
|
||||||
**************************************/
|
**************************************/
|
||||||
@@ -76,6 +63,8 @@ static const char* g_defaultDictName = "dictionary";
|
|||||||
static const unsigned g_defaultMaxDictSize = 110 KB;
|
static const unsigned g_defaultMaxDictSize = 110 KB;
|
||||||
static const int g_defaultDictCLevel = 3;
|
static const int g_defaultDictCLevel = 3;
|
||||||
static const unsigned g_defaultSelectivityLevel = 9;
|
static const unsigned g_defaultSelectivityLevel = 9;
|
||||||
|
#define OVERLAP_LOG_DEFAULT 9999
|
||||||
|
static U32 g_overlapLog = OVERLAP_LOG_DEFAULT;
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
@@ -124,12 +113,16 @@ static int usage_advanced(const char* programName)
|
|||||||
DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n");
|
DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n");
|
||||||
DISPLAY( " -c : force write to standard output, even if it is the console\n");
|
DISPLAY( " -c : force write to standard output, even if it is the console\n");
|
||||||
#ifdef UTIL_HAS_CREATEFILELIST
|
#ifdef UTIL_HAS_CREATEFILELIST
|
||||||
DISPLAY( " -r : operate recursively on directories\n");
|
DISPLAY( " -r : operate recursively on directories \n");
|
||||||
#endif
|
#endif
|
||||||
#ifndef ZSTD_NOCOMPRESS
|
#ifndef ZSTD_NOCOMPRESS
|
||||||
DISPLAY( "--ultra : enable levels beyond %i, up to %i (requires more memory)\n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel());
|
DISPLAY( "--ultra : enable levels beyond %i, up to %i (requires more memory)\n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel());
|
||||||
DISPLAY( "--no-dictID : don't write dictID into header (dictionary compression)\n");
|
DISPLAY( "--no-dictID : don't write dictID into header (dictionary compression)\n");
|
||||||
DISPLAY( "--[no-]check : integrity check (default:enabled)\n");
|
DISPLAY( "--[no-]check : integrity check (default:enabled) \n");
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
DISPLAY( " -T# : use # threads for compression (default:1) \n");
|
||||||
|
DISPLAY( " -B# : select size of independent sections (default:0==automatic) \n");
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifndef ZSTD_NODECOMPRESS
|
#ifndef ZSTD_NODECOMPRESS
|
||||||
DISPLAY( "--test : test compressed file integrity \n");
|
DISPLAY( "--test : test compressed file integrity \n");
|
||||||
@@ -141,6 +134,8 @@ static int usage_advanced(const char* programName)
|
|||||||
DISPLAY( "\n");
|
DISPLAY( "\n");
|
||||||
DISPLAY( "Dictionary builder :\n");
|
DISPLAY( "Dictionary builder :\n");
|
||||||
DISPLAY( "--train ## : create a dictionary from a training set of files \n");
|
DISPLAY( "--train ## : create a dictionary from a training set of files \n");
|
||||||
|
DISPLAY( "--cover=k=#,d=# : use the cover algorithm with parameters k and d \n");
|
||||||
|
DISPLAY( "--optimize-cover[=steps=#,k=#,d=#] : optimize cover parameters with optional parameters\n");
|
||||||
DISPLAY( " -o file : `file` is dictionary name (default: %s) \n", g_defaultDictName);
|
DISPLAY( " -o file : `file` is dictionary name (default: %s) \n", g_defaultDictName);
|
||||||
DISPLAY( "--maxdict ## : limit dictionary to specified size (default : %u) \n", g_defaultMaxDictSize);
|
DISPLAY( "--maxdict ## : limit dictionary to specified size (default : %u) \n", g_defaultMaxDictSize);
|
||||||
DISPLAY( " -s# : dictionary selectivity level (default: %u)\n", g_defaultSelectivityLevel);
|
DISPLAY( " -s# : dictionary selectivity level (default: %u)\n", g_defaultSelectivityLevel);
|
||||||
@@ -193,7 +188,7 @@ static unsigned readU32FromChar(const char** stringPtr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** longCommandWArg() :
|
/** longCommandWArg() :
|
||||||
* check is *stringPtr is the same as longCommand.
|
* check if *stringPtr is the same as longCommand.
|
||||||
* If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
|
* If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
|
||||||
* @return 0 and doesn't modify *stringPtr otherwise.
|
* @return 0 and doesn't modify *stringPtr otherwise.
|
||||||
*/
|
*/
|
||||||
@@ -205,6 +200,56 @@ static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ZSTD_NODICT
|
||||||
|
/**
|
||||||
|
* parseCoverParameters() :
|
||||||
|
* reads cover parameters from *stringPtr (e.g. "--cover=smoothing=100,kmin=48,kstep=4,kmax=64,d=8") into *params
|
||||||
|
* @return 1 means that cover parameters were correct
|
||||||
|
* @return 0 in case of malformed parameters
|
||||||
|
*/
|
||||||
|
static unsigned parseCoverParameters(const char* stringPtr, COVER_params_t *params)
|
||||||
|
{
|
||||||
|
memset(params, 0, sizeof(*params));
|
||||||
|
for (; ;) {
|
||||||
|
if (longCommandWArg(&stringPtr, "k=")) { params->k = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
if (longCommandWArg(&stringPtr, "d=")) { params->d = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
if (longCommandWArg(&stringPtr, "steps=")) { params->steps = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (stringPtr[0] != 0) return 0;
|
||||||
|
DISPLAYLEVEL(4, "k=%u\nd=%u\nsteps=%u\n", params->k, params->d, params->steps);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/** parseCompressionParameters() :
|
||||||
|
* reads compression parameters from *stringPtr (e.g. "--zstd=wlog=23,clog=23,hlog=22,slog=6,slen=3,tlen=48,strat=6") into *params
|
||||||
|
* @return 1 means that compression parameters were correct
|
||||||
|
* @return 0 in case of malformed parameters
|
||||||
|
*/
|
||||||
|
static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressionParameters* params)
|
||||||
|
{
|
||||||
|
for ( ; ;) {
|
||||||
|
if (longCommandWArg(&stringPtr, "windowLog=") || longCommandWArg(&stringPtr, "wlog=")) { params->windowLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
if (longCommandWArg(&stringPtr, "chainLog=") || longCommandWArg(&stringPtr, "clog=")) { params->chainLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
if (longCommandWArg(&stringPtr, "hashLog=") || longCommandWArg(&stringPtr, "hlog=")) { params->hashLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
if (longCommandWArg(&stringPtr, "searchLog=") || longCommandWArg(&stringPtr, "slog=")) { params->searchLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
if (longCommandWArg(&stringPtr, "searchLength=") || longCommandWArg(&stringPtr, "slen=")) { params->searchLength = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
if (longCommandWArg(&stringPtr, "targetLength=") || longCommandWArg(&stringPtr, "tlen=")) { params->targetLength = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
if (longCommandWArg(&stringPtr, "strategy=") || longCommandWArg(&stringPtr, "strat=")) { params->strategy = (ZSTD_strategy)(1 + readU32FromChar(&stringPtr)); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
if (longCommandWArg(&stringPtr, "overlapLog=") || longCommandWArg(&stringPtr, "ovlog=")) { g_overlapLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stringPtr[0] != 0) return 0; /* check the end of string */
|
||||||
|
DISPLAYLEVEL(4, "windowLog=%d\nchainLog=%d\nhashLog=%d\nsearchLog=%d\n", params->windowLog, params->chainLog, params->hashLog, params->searchLog);
|
||||||
|
DISPLAYLEVEL(4, "searchLength=%d\ntargetLength=%d\nstrategy=%d\n", params->searchLength, params->targetLength, params->strategy);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train } zstd_operation_mode;
|
typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train } zstd_operation_mode;
|
||||||
|
|
||||||
#define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
|
#define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
|
||||||
@@ -221,8 +266,12 @@ int main(int argCount, const char* argv[])
|
|||||||
nextArgumentIsDictID=0,
|
nextArgumentIsDictID=0,
|
||||||
nextArgumentsAreFiles=0,
|
nextArgumentsAreFiles=0,
|
||||||
ultra=0,
|
ultra=0,
|
||||||
lastCommand = 0;
|
lastCommand = 0,
|
||||||
|
nbThreads = 1;
|
||||||
|
unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */
|
||||||
|
size_t blockSize = 0;
|
||||||
zstd_operation_mode operation = zom_compress;
|
zstd_operation_mode operation = zom_compress;
|
||||||
|
ZSTD_compressionParameters compressionParams;
|
||||||
int cLevel = ZSTDCLI_CLEVEL_DEFAULT;
|
int cLevel = ZSTDCLI_CLEVEL_DEFAULT;
|
||||||
int cLevelLast = 1;
|
int cLevelLast = 1;
|
||||||
unsigned recursive = 0;
|
unsigned recursive = 0;
|
||||||
@@ -241,6 +290,10 @@ int main(int argCount, const char* argv[])
|
|||||||
char* fileNamesBuf = NULL;
|
char* fileNamesBuf = NULL;
|
||||||
unsigned fileNamesNb;
|
unsigned fileNamesNb;
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef ZSTD_NODICT
|
||||||
|
COVER_params_t coverParams;
|
||||||
|
int cover = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
(void)recursive; (void)cLevelLast; /* not used when ZSTD_NOBENCH set */
|
(void)recursive; (void)cLevelLast; /* not used when ZSTD_NOBENCH set */
|
||||||
@@ -259,6 +312,7 @@ int main(int argCount, const char* argv[])
|
|||||||
/* preset behaviors */
|
/* preset behaviors */
|
||||||
if (!strcmp(programName, ZSTD_UNZSTD)) operation=zom_decompress;
|
if (!strcmp(programName, ZSTD_UNZSTD)) operation=zom_decompress;
|
||||||
if (!strcmp(programName, ZSTD_CAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; displayLevel=1; }
|
if (!strcmp(programName, ZSTD_CAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; displayLevel=1; }
|
||||||
|
memset(&compressionParams, 0, sizeof(compressionParams));
|
||||||
|
|
||||||
/* command switches */
|
/* command switches */
|
||||||
for (argNb=1; argNb<argCount; argNb++) {
|
for (argNb=1; argNb<argCount; argNb++) {
|
||||||
@@ -304,9 +358,25 @@ int main(int argCount, const char* argv[])
|
|||||||
if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(1); continue; }
|
if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(1); continue; }
|
||||||
|
|
||||||
/* long commands with arguments */
|
/* long commands with arguments */
|
||||||
|
#ifndef ZSTD_NODICT
|
||||||
|
if (longCommandWArg(&argument, "--cover=")) {
|
||||||
|
cover=1; if (!parseCoverParameters(argument, &coverParams)) CLEAN_RETURN(badusage(programName));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (longCommandWArg(&argument, "--optimize-cover")) {
|
||||||
|
cover=2;
|
||||||
|
/* Allow optional arguments following an = */
|
||||||
|
if (*argument == 0) { memset(&coverParams, 0, sizeof(coverParams)); }
|
||||||
|
else if (*argument++ != '=') { CLEAN_RETURN(badusage(programName)); }
|
||||||
|
else if (!parseCoverParameters(argument, &coverParams)) { CLEAN_RETURN(badusage(programName)); }
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (longCommandWArg(&argument, "--memlimit=")) { memLimit = readU32FromChar(&argument); continue; }
|
if (longCommandWArg(&argument, "--memlimit=")) { memLimit = readU32FromChar(&argument); continue; }
|
||||||
if (longCommandWArg(&argument, "--memory=")) { memLimit = readU32FromChar(&argument); continue; }
|
if (longCommandWArg(&argument, "--memory=")) { memLimit = readU32FromChar(&argument); continue; }
|
||||||
if (longCommandWArg(&argument, "--memlimit-decompress=")) { memLimit = readU32FromChar(&argument); continue; }
|
if (longCommandWArg(&argument, "--memlimit-decompress=")) { memLimit = readU32FromChar(&argument); continue; }
|
||||||
|
if (longCommandWArg(&argument, "--block-size=")) { blockSize = readU32FromChar(&argument); continue; }
|
||||||
|
if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) CLEAN_RETURN(badusage(programName)); continue; }
|
||||||
/* fall-through, will trigger bad_usage() later on */
|
/* fall-through, will trigger bad_usage() later on */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +407,7 @@ int main(int argCount, const char* argv[])
|
|||||||
/* Decoding */
|
/* Decoding */
|
||||||
case 'd':
|
case 'd':
|
||||||
#ifndef ZSTD_NOBENCH
|
#ifndef ZSTD_NOBENCH
|
||||||
if (operation==zom_bench) { BMK_setDecodeOnly(1); argument++; break; } /* benchmark decode (hidden option) */
|
if (operation==zom_bench) { BMK_setDecodeOnlyMode(1); argument++; break; } /* benchmark decode (hidden option) */
|
||||||
#endif
|
#endif
|
||||||
operation=zom_decompress; argument++; break;
|
operation=zom_decompress; argument++; break;
|
||||||
|
|
||||||
@@ -381,34 +451,38 @@ int main(int argCount, const char* argv[])
|
|||||||
|
|
||||||
#ifndef ZSTD_NOBENCH
|
#ifndef ZSTD_NOBENCH
|
||||||
/* Benchmark */
|
/* Benchmark */
|
||||||
case 'b': operation=zom_bench; argument++; break;
|
case 'b':
|
||||||
|
operation=zom_bench;
|
||||||
|
argument++;
|
||||||
|
break;
|
||||||
|
|
||||||
/* range bench (benchmark only) */
|
/* range bench (benchmark only) */
|
||||||
case 'e':
|
case 'e':
|
||||||
/* compression Level */
|
/* compression Level */
|
||||||
argument++;
|
argument++;
|
||||||
cLevelLast = readU32FromChar(&argument);
|
cLevelLast = readU32FromChar(&argument);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Modify Nb Iterations (benchmark only) */
|
/* Modify Nb Iterations (benchmark only) */
|
||||||
case 'i':
|
case 'i':
|
||||||
argument++;
|
argument++;
|
||||||
{ U32 const iters = readU32FromChar(&argument);
|
bench_nbSeconds = readU32FromChar(&argument);
|
||||||
BMK_setNotificationLevel(displayLevel);
|
|
||||||
BMK_SetNbSeconds(iters);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* cut input into blocks (benchmark only) */
|
/* cut input into blocks (benchmark only) */
|
||||||
case 'B':
|
case 'B':
|
||||||
argument++;
|
argument++;
|
||||||
{ size_t const bSize = readU32FromChar(&argument);
|
blockSize = readU32FromChar(&argument);
|
||||||
BMK_setNotificationLevel(displayLevel);
|
|
||||||
BMK_SetBlockSize(bSize);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#endif /* ZSTD_NOBENCH */
|
#endif /* ZSTD_NOBENCH */
|
||||||
|
|
||||||
|
/* nb of threads (hidden option) */
|
||||||
|
case 'T':
|
||||||
|
argument++;
|
||||||
|
nbThreads = readU32FromChar(&argument);
|
||||||
|
break;
|
||||||
|
|
||||||
/* Dictionary Selection level */
|
/* Dictionary Selection level */
|
||||||
case 's':
|
case 's':
|
||||||
argument++;
|
argument++;
|
||||||
@@ -470,6 +544,15 @@ int main(int argCount, const char* argv[])
|
|||||||
|
|
||||||
/* Welcome message (if verbose) */
|
/* Welcome message (if verbose) */
|
||||||
DISPLAYLEVEL(3, WELCOME_MESSAGE);
|
DISPLAYLEVEL(3, WELCOME_MESSAGE);
|
||||||
|
#ifdef _POSIX_C_SOURCE
|
||||||
|
DISPLAYLEVEL(4, "_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE);
|
||||||
|
#endif
|
||||||
|
#ifdef _POSIX_VERSION
|
||||||
|
DISPLAYLEVEL(4, "_POSIX_VERSION defined: %ldL\n", (long) _POSIX_VERSION);
|
||||||
|
#endif
|
||||||
|
#ifdef PLATFORM_POSIX_VERSION
|
||||||
|
DISPLAYLEVEL(4, "PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef UTIL_HAS_CREATEFILELIST
|
#ifdef UTIL_HAS_CREATEFILELIST
|
||||||
if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
|
if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
|
||||||
@@ -488,21 +571,33 @@ int main(int argCount, const char* argv[])
|
|||||||
if (operation==zom_bench) {
|
if (operation==zom_bench) {
|
||||||
#ifndef ZSTD_NOBENCH
|
#ifndef ZSTD_NOBENCH
|
||||||
BMK_setNotificationLevel(displayLevel);
|
BMK_setNotificationLevel(displayLevel);
|
||||||
BMK_benchFiles(filenameTable, filenameIdx, dictFileName, cLevel, cLevelLast);
|
BMK_setBlockSize(blockSize);
|
||||||
|
BMK_setNbThreads(nbThreads);
|
||||||
|
BMK_setNbSeconds(bench_nbSeconds);
|
||||||
|
BMK_benchFiles(filenameTable, filenameIdx, dictFileName, cLevel, cLevelLast, &compressionParams);
|
||||||
#endif
|
#endif
|
||||||
|
(void)bench_nbSeconds;
|
||||||
goto _end;
|
goto _end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if dictionary builder is selected */
|
/* Check if dictionary builder is selected */
|
||||||
if (operation==zom_train) {
|
if (operation==zom_train) {
|
||||||
#ifndef ZSTD_NODICT
|
#ifndef ZSTD_NODICT
|
||||||
ZDICT_params_t dictParams;
|
if (cover) {
|
||||||
memset(&dictParams, 0, sizeof(dictParams));
|
coverParams.nbThreads = nbThreads;
|
||||||
dictParams.compressionLevel = dictCLevel;
|
coverParams.compressionLevel = dictCLevel;
|
||||||
dictParams.selectivityLevel = dictSelect;
|
coverParams.notificationLevel = displayLevel;
|
||||||
dictParams.notificationLevel = displayLevel;
|
coverParams.dictID = dictID;
|
||||||
dictParams.dictID = dictID;
|
DiB_trainFromFiles(outFileName, maxDictSize, filenameTable, filenameIdx, NULL, &coverParams, cover - 1);
|
||||||
DiB_trainFromFiles(outFileName, maxDictSize, filenameTable, filenameIdx, dictParams);
|
} else {
|
||||||
|
ZDICT_params_t dictParams;
|
||||||
|
memset(&dictParams, 0, sizeof(dictParams));
|
||||||
|
dictParams.compressionLevel = dictCLevel;
|
||||||
|
dictParams.selectivityLevel = dictSelect;
|
||||||
|
dictParams.notificationLevel = displayLevel;
|
||||||
|
dictParams.dictID = dictID;
|
||||||
|
DiB_trainFromFiles(outFileName, maxDictSize, filenameTable, filenameIdx, &dictParams, NULL, 0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
goto _end;
|
goto _end;
|
||||||
}
|
}
|
||||||
@@ -531,7 +626,7 @@ int main(int argCount, const char* argv[])
|
|||||||
} }
|
} }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* No warning message in pipe mode (stdin + stdout) or multi-files mode */
|
/* No status message in pipe mode (stdin - stdout) or multi-files mode */
|
||||||
if (!strcmp(filenameTable[0], stdinmark) && outFileName && !strcmp(outFileName,stdoutmark) && (displayLevel==2)) displayLevel=1;
|
if (!strcmp(filenameTable[0], stdinmark) && outFileName && !strcmp(outFileName,stdoutmark) && (displayLevel==2)) displayLevel=1;
|
||||||
if ((filenameIdx>1) & (displayLevel==2)) displayLevel=1;
|
if ((filenameIdx>1) & (displayLevel==2)) displayLevel=1;
|
||||||
|
|
||||||
@@ -539,10 +634,13 @@ int main(int argCount, const char* argv[])
|
|||||||
FIO_setNotificationLevel(displayLevel);
|
FIO_setNotificationLevel(displayLevel);
|
||||||
if (operation==zom_compress) {
|
if (operation==zom_compress) {
|
||||||
#ifndef ZSTD_NOCOMPRESS
|
#ifndef ZSTD_NOCOMPRESS
|
||||||
|
FIO_setNbThreads(nbThreads);
|
||||||
|
FIO_setBlockSize((U32)blockSize);
|
||||||
|
if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(g_overlapLog);
|
||||||
if ((filenameIdx==1) && outFileName)
|
if ((filenameIdx==1) && outFileName)
|
||||||
operationResult = FIO_compressFilename(outFileName, filenameTable[0], dictFileName, cLevel);
|
operationResult = FIO_compressFilename(outFileName, filenameTable[0], dictFileName, cLevel, &compressionParams);
|
||||||
else
|
else
|
||||||
operationResult = FIO_compressMultipleFilenames(filenameTable, filenameIdx, outFileName ? outFileName : ZSTD_EXTENSION, dictFileName, cLevel);
|
operationResult = FIO_compressMultipleFilenames(filenameTable, filenameIdx, outFileName ? outFileName : ZSTD_EXTENSION, dictFileName, cLevel, &compressionParams);
|
||||||
#else
|
#else
|
||||||
DISPLAY("Compression not supported\n");
|
DISPLAY("Compression not supported\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+2
-1
@@ -1 +1,2 @@
|
|||||||
zstdcat $@ | less
|
#!/bin/sh
|
||||||
|
zstdcat "$@" | less
|
||||||
|
|||||||
@@ -3,15 +3,21 @@ fullbench
|
|||||||
fullbench32
|
fullbench32
|
||||||
fuzzer
|
fuzzer
|
||||||
fuzzer32
|
fuzzer32
|
||||||
|
fuzzer-dll
|
||||||
zbufftest
|
zbufftest
|
||||||
zbufftest32
|
zbufftest32
|
||||||
|
zbufftest-dll
|
||||||
zstreamtest
|
zstreamtest
|
||||||
zstreamtest32
|
zstreamtest32
|
||||||
|
zstreamtest-dll
|
||||||
datagen
|
datagen
|
||||||
paramgrill
|
paramgrill
|
||||||
paramgrill32
|
paramgrill32
|
||||||
roundTripCrash
|
roundTripCrash
|
||||||
longmatch
|
longmatch
|
||||||
|
symbols
|
||||||
|
pool
|
||||||
|
invalidDictionaries
|
||||||
|
|
||||||
# Tmp test directory
|
# Tmp test directory
|
||||||
zstdtest
|
zstdtest
|
||||||
|
|||||||
+79
-28
@@ -2,6 +2,8 @@
|
|||||||
# Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
# Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
# This Makefile is validated for Linux, macOS, *BSD, Hurd, Solaris, MSYS2 targets
|
||||||
|
#
|
||||||
# This source code is licensed under the BSD-style license found in the
|
# This source code is licensed under the BSD-style license found in the
|
||||||
# LICENSE file in the root directory of this source tree. An additional grant
|
# LICENSE file in the root directory of this source tree. An additional grant
|
||||||
# of patent rights can be found in the PATENTS file in the same directory.
|
# of patent rights can be found in the PATENTS file in the same directory.
|
||||||
@@ -18,22 +20,18 @@
|
|||||||
# zstreamtest32: Same as zstreamtest, but forced to compile in 32-bits mode
|
# zstreamtest32: Same as zstreamtest, but forced to compile in 32-bits mode
|
||||||
# ##########################################################################
|
# ##########################################################################
|
||||||
|
|
||||||
DESTDIR?=
|
|
||||||
PREFIX ?= /usr/local
|
|
||||||
BINDIR = $(PREFIX)/bin
|
|
||||||
MANDIR = $(PREFIX)/share/man/man1
|
|
||||||
ZSTDDIR = ../lib
|
ZSTDDIR = ../lib
|
||||||
PRGDIR = ../programs
|
PRGDIR = ../programs
|
||||||
PYTHON ?= python3
|
PYTHON ?= python3
|
||||||
TESTARTEFACT := versionsTest namespaceTest
|
TESTARTEFACT := versionsTest namespaceTest
|
||||||
|
|
||||||
|
|
||||||
CPPFLAGS= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/dictBuilder -I$(PRGDIR)
|
CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress -I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR)
|
||||||
CFLAGS ?= -O3
|
CFLAGS ?= -O3
|
||||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 \
|
CFLAGS += -g -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 \
|
||||||
-Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wundef
|
-Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wundef
|
||||||
CFLAGS += $(MOREFLAGS)
|
CFLAGS += $(MOREFLAGS)
|
||||||
FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||||
|
|
||||||
|
|
||||||
ZSTDCOMMON_FILES := $(ZSTDDIR)/common/*.c
|
ZSTDCOMMON_FILES := $(ZSTDDIR)/common/*.c
|
||||||
@@ -48,16 +46,18 @@ ZDICT_FILES := $(ZSTDDIR)/dictBuilder/*.c
|
|||||||
# Define *.exe as extension for Windows systems
|
# Define *.exe as extension for Windows systems
|
||||||
ifneq (,$(filter Windows%,$(OS)))
|
ifneq (,$(filter Windows%,$(OS)))
|
||||||
EXT =.exe
|
EXT =.exe
|
||||||
|
MULTITHREAD = -DZSTD_MULTITHREAD
|
||||||
else
|
else
|
||||||
EXT =
|
EXT =
|
||||||
|
MULTITHREAD = -pthread -DZSTD_MULTITHREAD
|
||||||
endif
|
endif
|
||||||
|
|
||||||
VOID = /dev/null
|
VOID = /dev/null
|
||||||
ZSTREAM_TESTTIME = -T2mn
|
ZSTREAM_TESTTIME = -T2mn
|
||||||
FUZZERTEST= -T5mn
|
FUZZERTEST ?= -T5mn
|
||||||
ZSTDRTTEST= --test-large-data
|
ZSTDRTTEST = --test-large-data
|
||||||
|
|
||||||
.PHONY: default all all32 clean test test32 test-all namespaceTest versionsTest
|
.PHONY: default all all32 dll clean test test32 test-all namespaceTest versionsTest
|
||||||
|
|
||||||
default: fullbench
|
default: fullbench
|
||||||
|
|
||||||
@@ -65,6 +65,8 @@ all: fullbench fuzzer zstreamtest paramgrill datagen zbufftest
|
|||||||
|
|
||||||
all32: fullbench32 fuzzer32 zstreamtest32 zbufftest32
|
all32: fullbench32 fuzzer32 zstreamtest32 zbufftest32
|
||||||
|
|
||||||
|
dll: fuzzer-dll zstreamtest-dll zbufftest-dll
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
zstd:
|
zstd:
|
||||||
@@ -93,11 +95,16 @@ fullbench-dll: $(PRGDIR)/datagen.c fullbench.c
|
|||||||
$(MAKE) -C $(ZSTDDIR) libzstd
|
$(MAKE) -C $(ZSTDDIR) libzstd
|
||||||
$(CC) $(FLAGS) $^ -o $@$(EXT) -DZSTD_DLL_IMPORT=1 $(ZSTDDIR)/dll/libzstd.dll
|
$(CC) $(FLAGS) $^ -o $@$(EXT) -DZSTD_DLL_IMPORT=1 $(ZSTDDIR)/dll/libzstd.dll
|
||||||
|
|
||||||
fuzzer : $(ZSTD_FILES) $(ZDICT_FILES) $(PRGDIR)/datagen.c fuzzer.c
|
fuzzer : $(ZSTD_FILES) $(ZDICT_FILES) $(PRGDIR)/datagen.c fuzzer.c
|
||||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||||
|
|
||||||
fuzzer32 : $(ZSTD_FILES) $(ZDICT_FILES) $(PRGDIR)/datagen.c fuzzer.c
|
fuzzer32 : $(ZSTD_FILES) $(ZDICT_FILES) $(PRGDIR)/datagen.c fuzzer.c
|
||||||
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
|
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
|
||||||
|
|
||||||
|
fuzzer-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd
|
||||||
|
fuzzer-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/datagen.c fuzzer.c
|
||||||
|
$(MAKE) -C $(ZSTDDIR) libzstd
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@$(EXT)
|
||||||
|
|
||||||
zbufftest : CPPFLAGS += -I$(ZSTDDIR)/deprecated
|
zbufftest : CPPFLAGS += -I$(ZSTDDIR)/deprecated
|
||||||
zbufftest : CFLAGS += -Wno-deprecated-declarations # required to silence deprecation warnings
|
zbufftest : CFLAGS += -Wno-deprecated-declarations # required to silence deprecation warnings
|
||||||
@@ -109,11 +116,23 @@ zbufftest32 : CFLAGS += -Wno-deprecated-declarations -m32
|
|||||||
zbufftest32 : $(ZSTD_FILES) $(ZBUFF_FILES) $(PRGDIR)/datagen.c zbufftest.c
|
zbufftest32 : $(ZSTD_FILES) $(ZBUFF_FILES) $(PRGDIR)/datagen.c zbufftest.c
|
||||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||||
|
|
||||||
zstreamtest : $(ZSTD_FILES) $(PRGDIR)/datagen.c zstreamtest.c
|
zbufftest-dll : CPPFLAGS += -I$(ZSTDDIR)/deprecated
|
||||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
zbufftest-dll : CFLAGS += -Wno-deprecated-declarations # required to silence deprecation warnings
|
||||||
|
zbufftest-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd
|
||||||
|
zbufftest-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/datagen.c zbufftest.c
|
||||||
|
$(MAKE) -C $(ZSTDDIR) libzstd
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@$(EXT)
|
||||||
|
|
||||||
zstreamtest32 : $(ZSTD_FILES) $(PRGDIR)/datagen.c zstreamtest.c
|
zstreamtest : $(ZSTD_FILES) $(ZDICT_FILES) $(PRGDIR)/datagen.c zstreamtest.c
|
||||||
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
|
$(CC) $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT)
|
||||||
|
|
||||||
|
zstreamtest32 : $(ZSTD_FILES) $(ZDICT_FILES) $(PRGDIR)/datagen.c zstreamtest.c
|
||||||
|
$(CC) -m32 $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT)
|
||||||
|
|
||||||
|
zstreamtest-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd
|
||||||
|
zstreamtest-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/datagen.c zstreamtest.c
|
||||||
|
$(MAKE) -C $(ZSTDDIR) libzstd
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@$(EXT)
|
||||||
|
|
||||||
paramgrill : $(ZSTD_FILES) $(PRGDIR)/datagen.c paramgrill.c
|
paramgrill : $(ZSTD_FILES) $(PRGDIR)/datagen.c paramgrill.c
|
||||||
$(CC) $(FLAGS) $^ -lm -o $@$(EXT)
|
$(CC) $(FLAGS) $^ -lm -o $@$(EXT)
|
||||||
@@ -127,6 +146,21 @@ roundTripCrash : $(ZSTD_FILES) roundTripCrash.c
|
|||||||
longmatch : $(ZSTD_FILES) longmatch.c
|
longmatch : $(ZSTD_FILES) longmatch.c
|
||||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||||
|
|
||||||
|
invalidDictionaries : $(ZSTD_FILES) invalidDictionaries.c
|
||||||
|
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||||
|
|
||||||
|
symbols : symbols.c
|
||||||
|
$(MAKE) -C $(ZSTDDIR) libzstd
|
||||||
|
ifneq (,$(filter Windows%,$(OS)))
|
||||||
|
cp $(ZSTDDIR)/dll/libzstd.dll .
|
||||||
|
$(CC) $(FLAGS) $^ -o $@$(EXT) -DZSTD_DLL_IMPORT=1 libzstd.dll
|
||||||
|
else
|
||||||
|
$(CC) $(FLAGS) $^ -o $@$(EXT) -Wl,-rpath=$(ZSTDDIR) $(ZSTDDIR)/libzstd.so
|
||||||
|
endif
|
||||||
|
|
||||||
|
pool : pool.c $(ZSTDDIR)/common/pool.c $(ZSTDDIR)/common/threading.c
|
||||||
|
$(CC) $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT)
|
||||||
|
|
||||||
namespaceTest:
|
namespaceTest:
|
||||||
if $(CC) namespaceTest.c ../lib/common/xxhash.c -o $@ ; then echo compilation should fail; exit 1 ; fi
|
if $(CC) namespaceTest.c ../lib/common/xxhash.c -o $@ ; then echo compilation should fail; exit 1 ; fi
|
||||||
$(RM) $@
|
$(RM) $@
|
||||||
@@ -142,15 +176,17 @@ clean:
|
|||||||
fullbench$(EXT) fullbench32$(EXT) \
|
fullbench$(EXT) fullbench32$(EXT) \
|
||||||
fullbench-lib$(EXT) fullbench-dll$(EXT) \
|
fullbench-lib$(EXT) fullbench-dll$(EXT) \
|
||||||
fuzzer$(EXT) fuzzer32$(EXT) zbufftest$(EXT) zbufftest32$(EXT) \
|
fuzzer$(EXT) fuzzer32$(EXT) zbufftest$(EXT) zbufftest32$(EXT) \
|
||||||
zstreamtest$(EXT) zstreamtest32$(EXT) \
|
fuzzer-dll$(EXT) zstreamtest-dll$(EXT) zbufftest-dll$(EXT)\
|
||||||
datagen$(EXT) paramgrill$(EXT) roundTripCrash$(EXT) longmatch$(EXT)
|
zstreamtest$(EXT) zstreamtest32$(EXT) \
|
||||||
|
datagen$(EXT) paramgrill$(EXT) roundTripCrash$(EXT) longmatch$(EXT) \
|
||||||
|
symbols$(EXT) invalidDictionaries$(EXT) pool$(EXT)
|
||||||
@echo Cleaning completed
|
@echo Cleaning completed
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------
|
||||||
#make valgrindTest is validated only for Linux, OSX, kFreeBSD, Hurd and some BSD targets
|
#make valgrindTest is validated only for Linux, OSX, BSD, Hurd and Solaris targets
|
||||||
#----------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------
|
||||||
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD DragonFly))
|
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS))
|
||||||
HOST_OS = POSIX
|
HOST_OS = POSIX
|
||||||
|
|
||||||
valgrindTest: VALGRIND = valgrind --leak-check=full --error-exitcode=1
|
valgrindTest: VALGRIND = valgrind --leak-check=full --error-exitcode=1
|
||||||
@@ -175,15 +211,21 @@ HOST_OS = MSYS
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
#make tests validated only for MSYS, Linux, OSX, kFreeBSD and Hurd targets
|
#make tests validated only for MSYS, Linux, OSX, BSD, Hurd and Solaris targets
|
||||||
#------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
ifneq (,$(filter $(HOST_OS),MSYS POSIX))
|
ifneq (,$(filter $(HOST_OS),MSYS POSIX))
|
||||||
|
|
||||||
|
DIFF:=diff
|
||||||
|
ifneq (,$(filter $(shell uname),SunOS))
|
||||||
|
DIFF:=gdiff
|
||||||
|
endif
|
||||||
|
|
||||||
zstd-playTests: datagen
|
zstd-playTests: datagen
|
||||||
file $(ZSTD)
|
file $(ZSTD)
|
||||||
ZSTD="$(QEMU_SYS) $(ZSTD)" ./playTests.sh $(ZSTDRTTEST)
|
ZSTD="$(QEMU_SYS) $(ZSTD)" ./playTests.sh $(ZSTDRTTEST)
|
||||||
|
|
||||||
test: test-zstd test-fullbench test-fuzzer test-zstream test-longmatch
|
test: test-zstd test-fullbench test-fuzzer test-zstream test-longmatch test-invalidDictionaries test-pool
|
||||||
|
|
||||||
test32: test-zstd32 test-fullbench32 test-fuzzer32 test-zstream32
|
test32: test-zstd32 test-fullbench32 test-fuzzer32 test-zstream32
|
||||||
|
|
||||||
@@ -206,7 +248,7 @@ test-gzstd: gzstd
|
|||||||
$(PRGDIR)/zstd -d README.md.gz -o README2.md
|
$(PRGDIR)/zstd -d README.md.gz -o README2.md
|
||||||
$(PRGDIR)/zstd -d README.md.gz test-zstd-speed.py.gz
|
$(PRGDIR)/zstd -d README.md.gz test-zstd-speed.py.gz
|
||||||
$(PRGDIR)/zstd -d zstd_gz.zst gz_zstd.gz
|
$(PRGDIR)/zstd -d zstd_gz.zst gz_zstd.gz
|
||||||
diff -q zstd_gz gz_zstd
|
$(DIFF) -q zstd_gz gz_zstd
|
||||||
echo Hello World ZSTD | $(PRGDIR)/zstd -c - >hello.zst
|
echo Hello World ZSTD | $(PRGDIR)/zstd -c - >hello.zst
|
||||||
echo Hello World GZIP | gzip -c - >hello.gz
|
echo Hello World GZIP | gzip -c - >hello.gz
|
||||||
echo Hello World TEXT >hello.txt
|
echo Hello World TEXT >hello.txt
|
||||||
@@ -243,4 +285,13 @@ test-zstream32: zstreamtest32
|
|||||||
test-longmatch: longmatch
|
test-longmatch: longmatch
|
||||||
$(QEMU_SYS) ./longmatch
|
$(QEMU_SYS) ./longmatch
|
||||||
|
|
||||||
|
test-invalidDictionaries: invalidDictionaries
|
||||||
|
$(QEMU_SYS) ./invalidDictionaries
|
||||||
|
|
||||||
|
test-symbols: symbols
|
||||||
|
$(QEMU_SYS) ./symbols
|
||||||
|
|
||||||
|
test-pool: pool
|
||||||
|
$(QEMU_SYS) ./pool
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -179,6 +179,23 @@ size_t local_ZSTD_compressContinue(void* dst, size_t dstCapacity, void* buff2, c
|
|||||||
return ZSTD_compressEnd(g_zcc, dst, dstCapacity, src, srcSize);
|
return ZSTD_compressEnd(g_zcc, dst, dstCapacity, src, srcSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FIRST_BLOCK_SIZE 8
|
||||||
|
size_t local_ZSTD_compressContinue_extDict(void* dst, size_t dstCapacity, void* buff2, const void* src, size_t srcSize)
|
||||||
|
{
|
||||||
|
BYTE firstBlockBuf[FIRST_BLOCK_SIZE];
|
||||||
|
|
||||||
|
(void)buff2;
|
||||||
|
memcpy(firstBlockBuf, src, FIRST_BLOCK_SIZE);
|
||||||
|
ZSTD_compressBegin(g_zcc, 1);
|
||||||
|
|
||||||
|
{ size_t const compressResult = ZSTD_compressContinue(g_zcc, dst, dstCapacity, firstBlockBuf, FIRST_BLOCK_SIZE);
|
||||||
|
if (ZSTD_isError(compressResult)) { DISPLAY("local_ZSTD_compressContinue_extDict error : %s\n", ZSTD_getErrorName(compressResult)); return compressResult; }
|
||||||
|
dst = (BYTE*)dst + compressResult;
|
||||||
|
dstCapacity -= compressResult;
|
||||||
|
}
|
||||||
|
return ZSTD_compressEnd(g_zcc, dst, dstCapacity, (const BYTE*)src + FIRST_BLOCK_SIZE, srcSize - FIRST_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
size_t local_ZSTD_decompressContinue(void* dst, size_t dstCapacity, void* buff2, const void* src, size_t srcSize)
|
size_t local_ZSTD_decompressContinue(void* dst, size_t dstCapacity, void* buff2, const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
size_t regeneratedSize = 0;
|
size_t regeneratedSize = 0;
|
||||||
@@ -229,6 +246,9 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb)
|
|||||||
benchFunction = local_ZSTD_compressContinue; benchName = "ZSTD_compressContinue";
|
benchFunction = local_ZSTD_compressContinue; benchName = "ZSTD_compressContinue";
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
|
benchFunction = local_ZSTD_compressContinue_extDict; benchName = "ZSTD_compressContinue_extDict";
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
benchFunction = local_ZSTD_decompressContinue; benchName = "ZSTD_decompressContinue";
|
benchFunction = local_ZSTD_decompressContinue; benchName = "ZSTD_decompressContinue";
|
||||||
break;
|
break;
|
||||||
case 31:
|
case 31:
|
||||||
@@ -268,6 +288,9 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb)
|
|||||||
if (g_zcc==NULL) g_zcc = ZSTD_createCCtx();
|
if (g_zcc==NULL) g_zcc = ZSTD_createCCtx();
|
||||||
break;
|
break;
|
||||||
case 12 :
|
case 12 :
|
||||||
|
if (g_zcc==NULL) g_zcc = ZSTD_createCCtx();
|
||||||
|
break;
|
||||||
|
case 13 :
|
||||||
if (g_zdc==NULL) g_zdc = ZSTD_createDCtx();
|
if (g_zdc==NULL) g_zdc = ZSTD_createDCtx();
|
||||||
g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, 1);
|
g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, 1);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressContinue, ZSTD_compressBlock */
|
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressContinue, ZSTD_compressBlock */
|
||||||
#include "zstd.h" /* ZSTD_VERSION_STRING */
|
#include "zstd.h" /* ZSTD_VERSION_STRING */
|
||||||
#include "zstd_errors.h" /* ZSTD_getErrorCode */
|
#include "zstd_errors.h" /* ZSTD_getErrorCode */
|
||||||
|
#define ZDICT_STATIC_LINKING_ONLY
|
||||||
#include "zdict.h" /* ZDICT_trainFromBuffer */
|
#include "zdict.h" /* ZDICT_trainFromBuffer */
|
||||||
#include "datagen.h" /* RDG_genBuffer */
|
#include "datagen.h" /* RDG_genBuffer */
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
@@ -311,6 +312,70 @@ static int basicUnitTests(U32 seed, double compressibility)
|
|||||||
if (r != CNBuffSize) goto _output_error);
|
if (r != CNBuffSize) goto _output_error);
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(4, "OK \n");
|
||||||
|
|
||||||
|
DISPLAYLEVEL(4, "test%3i : dictionary containing only header should return error : ", testNb++);
|
||||||
|
{
|
||||||
|
const size_t ret = ZSTD_decompress_usingDict(
|
||||||
|
dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize,
|
||||||
|
"\x37\xa4\x30\xec\x11\x22\x33\x44", 8);
|
||||||
|
if (ZSTD_getErrorCode(ret) != ZSTD_error_dictionary_corrupted) goto _output_error;
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(4, "OK \n");
|
||||||
|
|
||||||
|
ZSTD_freeCCtx(cctx);
|
||||||
|
ZSTD_freeDCtx(dctx);
|
||||||
|
free(dictBuffer);
|
||||||
|
free(samplesSizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* COVER dictionary builder tests */
|
||||||
|
{ ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||||
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||||
|
size_t dictSize = 16 KB;
|
||||||
|
size_t optDictSize = dictSize;
|
||||||
|
void* dictBuffer = malloc(dictSize);
|
||||||
|
size_t const totalSampleSize = 1 MB;
|
||||||
|
size_t const sampleUnitSize = 8 KB;
|
||||||
|
U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize);
|
||||||
|
size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t));
|
||||||
|
COVER_params_t params;
|
||||||
|
U32 dictID;
|
||||||
|
|
||||||
|
if (dictBuffer==NULL || samplesSizes==NULL) {
|
||||||
|
free(dictBuffer);
|
||||||
|
free(samplesSizes);
|
||||||
|
goto _output_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
DISPLAYLEVEL(4, "test%3i : COVER_trainFromBuffer : ", testNb++);
|
||||||
|
{ U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
params.d = 1 + (FUZ_rand(&seed) % 16);
|
||||||
|
params.k = params.d + (FUZ_rand(&seed) % 256);
|
||||||
|
dictSize = COVER_trainFromBuffer(dictBuffer, dictSize,
|
||||||
|
CNBuffer, samplesSizes, nbSamples,
|
||||||
|
params);
|
||||||
|
if (ZDICT_isError(dictSize)) goto _output_error;
|
||||||
|
DISPLAYLEVEL(4, "OK, created dictionary of size %u \n", (U32)dictSize);
|
||||||
|
|
||||||
|
DISPLAYLEVEL(4, "test%3i : check dictID : ", testNb++);
|
||||||
|
dictID = ZDICT_getDictID(dictBuffer, dictSize);
|
||||||
|
if (dictID==0) goto _output_error;
|
||||||
|
DISPLAYLEVEL(4, "OK : %u \n", dictID);
|
||||||
|
|
||||||
|
DISPLAYLEVEL(4, "test%3i : COVER_optimizeTrainFromBuffer : ", testNb++);
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
params.steps = 4;
|
||||||
|
optDictSize = COVER_optimizeTrainFromBuffer(dictBuffer, optDictSize,
|
||||||
|
CNBuffer, samplesSizes, nbSamples,
|
||||||
|
¶ms);
|
||||||
|
if (ZDICT_isError(optDictSize)) goto _output_error;
|
||||||
|
DISPLAYLEVEL(4, "OK, created dictionary of size %u \n", (U32)optDictSize);
|
||||||
|
|
||||||
|
DISPLAYLEVEL(4, "test%3i : check dictID : ", testNb++);
|
||||||
|
dictID = ZDICT_getDictID(dictBuffer, optDictSize);
|
||||||
|
if (dictID==0) goto _output_error;
|
||||||
|
DISPLAYLEVEL(4, "OK : %u \n", dictID);
|
||||||
|
|
||||||
ZSTD_freeCCtx(cctx);
|
ZSTD_freeCCtx(cctx);
|
||||||
ZSTD_freeDCtx(dctx);
|
ZSTD_freeDCtx(dctx);
|
||||||
free(dictBuffer);
|
free(dictBuffer);
|
||||||
@@ -690,6 +755,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD
|
|||||||
CHECK (ZSTD_isError(errorCode), "ZSTD_copyCCtx error : %s", ZSTD_getErrorName(errorCode));
|
CHECK (ZSTD_isError(errorCode), "ZSTD_copyCCtx error : %s", ZSTD_getErrorName(errorCode));
|
||||||
} }
|
} }
|
||||||
XXH64_reset(&xxhState, 0);
|
XXH64_reset(&xxhState, 0);
|
||||||
|
ZSTD_setCCtxParameter(ctx, ZSTD_p_forceWindow, FUZ_rand(&lseed) & 1);
|
||||||
{ U32 const nbChunks = (FUZ_rand(&lseed) & 127) + 2;
|
{ U32 const nbChunks = (FUZ_rand(&lseed) & 127) + 2;
|
||||||
U32 n;
|
U32 n;
|
||||||
for (totalTestSize=0, cSize=0, n=0 ; n<nbChunks ; n++) {
|
for (totalTestSize=0, cSize=0, n=0 ; n<nbChunks ; n++) {
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include "zstd.h"
|
||||||
|
|
||||||
|
static const char invalidRepCode[] = {
|
||||||
|
0x37, 0xa4, 0x30, 0xec, 0x2a, 0x00, 0x00, 0x00, 0x39, 0x10, 0xc0, 0xc2,
|
||||||
|
0xa6, 0x00, 0x0c, 0x30, 0xc0, 0x00, 0x03, 0x0c, 0x30, 0x20, 0x72, 0xf8,
|
||||||
|
0xb4, 0x6d, 0x4b, 0x9f, 0xfc, 0x97, 0x29, 0x49, 0xb2, 0xdf, 0x4b, 0x29,
|
||||||
|
0x7d, 0x4a, 0xfc, 0x83, 0x18, 0x22, 0x75, 0x23, 0x24, 0x44, 0x4d, 0x02,
|
||||||
|
0xb7, 0x97, 0x96, 0xf6, 0xcb, 0xd1, 0xcf, 0xe8, 0x22, 0xea, 0x27, 0x36,
|
||||||
|
0xb7, 0x2c, 0x40, 0x46, 0x01, 0x08, 0x23, 0x01, 0x00, 0x00, 0x06, 0x1e,
|
||||||
|
0x3c, 0x83, 0x81, 0xd6, 0x18, 0xd4, 0x12, 0x3a, 0x04, 0x00, 0x80, 0x03,
|
||||||
|
0x08, 0x0e, 0x12, 0x1c, 0x12, 0x11, 0x0d, 0x0e, 0x0a, 0x0b, 0x0a, 0x09,
|
||||||
|
0x10, 0x0c, 0x09, 0x05, 0x04, 0x03, 0x06, 0x06, 0x06, 0x02, 0x00, 0x03,
|
||||||
|
0x00, 0x00, 0x02, 0x02, 0x00, 0x04, 0x06, 0x03, 0x06, 0x08, 0x24, 0x6b,
|
||||||
|
0x0d, 0x01, 0x10, 0x04, 0x81, 0x07, 0x00, 0x00, 0x04, 0xb9, 0x58, 0x18,
|
||||||
|
0x06, 0x59, 0x92, 0x43, 0xce, 0x28, 0xa5, 0x08, 0x88, 0xc0, 0x80, 0x88,
|
||||||
|
0x8c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x08, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct dictionary_s {
|
||||||
|
const char *data;
|
||||||
|
size_t size;
|
||||||
|
} dictionary;
|
||||||
|
|
||||||
|
static const dictionary dictionaries[] = {
|
||||||
|
{invalidRepCode, sizeof(invalidRepCode)},
|
||||||
|
{NULL, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, const char** argv) {
|
||||||
|
const dictionary *dict;
|
||||||
|
for (dict = dictionaries; dict->data != NULL; ++dict) {
|
||||||
|
ZSTD_CDict *cdict;
|
||||||
|
ZSTD_DDict *ddict;
|
||||||
|
cdict = ZSTD_createCDict(dict->data, dict->size, 1);
|
||||||
|
if (cdict) {
|
||||||
|
ZSTD_freeCDict(cdict);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ddict = ZSTD_createDDict(dict->data, dict->size);
|
||||||
|
if (ddict) {
|
||||||
|
ZSTD_freeDDict(ddict);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+57
-19
@@ -7,17 +7,17 @@ die() {
|
|||||||
|
|
||||||
roundTripTest() {
|
roundTripTest() {
|
||||||
if [ -n "$3" ]; then
|
if [ -n "$3" ]; then
|
||||||
local c="$3"
|
local_c="$3"
|
||||||
local p="$2"
|
local_p="$2"
|
||||||
else
|
else
|
||||||
local c="$2"
|
local_c="$2"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f tmp1 tmp2
|
rm -f tmp1 tmp2
|
||||||
$ECHO "roundTripTest: ./datagen $1 $p | $ZSTD -v$c | $ZSTD -d"
|
$ECHO "roundTripTest: ./datagen $1 $local_p | $ZSTD -v$local_c | $ZSTD -d"
|
||||||
./datagen $1 $p | $MD5SUM > tmp1
|
./datagen $1 $local_p | $MD5SUM > tmp1
|
||||||
./datagen $1 $p | $ZSTD --ultra -v$c | $ZSTD -d | $MD5SUM > tmp2
|
./datagen $1 $local_p | $ZSTD --ultra -v$local_c | $ZSTD -d | $MD5SUM > tmp2
|
||||||
diff -q tmp1 tmp2
|
$DIFF -q tmp1 tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
isWindows=false
|
isWindows=false
|
||||||
@@ -27,7 +27,6 @@ case "$OS" in
|
|||||||
Windows*)
|
Windows*)
|
||||||
isWindows=true
|
isWindows=true
|
||||||
ECHO="echo -e"
|
ECHO="echo -e"
|
||||||
INTOVOID="nul"
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@@ -38,6 +37,12 @@ case "$UNAME" in
|
|||||||
*) MD5SUM="md5sum" ;;
|
*) MD5SUM="md5sum" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
DIFF="diff"
|
||||||
|
case "$UNAME" in
|
||||||
|
SunOS) DIFF="gdiff" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
$ECHO "\nStarting playTests.sh isWindows=$isWindows ZSTD='$ZSTD'"
|
$ECHO "\nStarting playTests.sh isWindows=$isWindows ZSTD='$ZSTD'"
|
||||||
|
|
||||||
[ -n "$ZSTD" ] || die "ZSTD variable must be defined!"
|
[ -n "$ZSTD" ] || die "ZSTD variable must be defined!"
|
||||||
@@ -101,6 +106,18 @@ $ZSTD -f tmp && die "tmp not present : should have failed"
|
|||||||
ls tmp.zst && die "tmp.zst should not be created"
|
ls tmp.zst && die "tmp.zst should not be created"
|
||||||
|
|
||||||
|
|
||||||
|
$ECHO "\n**** Advanced compression parameters **** "
|
||||||
|
$ECHO "Hello world!" | $ZSTD --zstd=windowLog=21, - -o tmp.zst && die "wrong parameters not detected!"
|
||||||
|
$ECHO "Hello world!" | $ZSTD --zstd=windowLo=21 - -o tmp.zst && die "wrong parameters not detected!"
|
||||||
|
$ECHO "Hello world!" | $ZSTD --zstd=windowLog=21,slog - -o tmp.zst && die "wrong parameters not detected!"
|
||||||
|
ls tmp.zst && die "tmp.zst should not be created"
|
||||||
|
roundTripTest -g512K
|
||||||
|
roundTripTest -g512K " --zstd=slen=3,tlen=48,strat=6"
|
||||||
|
roundTripTest -g512K " --zstd=strat=6,wlog=23,clog=23,hlog=22,slog=6"
|
||||||
|
roundTripTest -g512K " --zstd=windowLog=23,chainLog=23,hashLog=22,searchLog=6,searchLength=3,targetLength=48,strategy=6"
|
||||||
|
roundTripTest -g512K 19
|
||||||
|
|
||||||
|
|
||||||
$ECHO "\n**** Pass-Through mode **** "
|
$ECHO "\n**** Pass-Through mode **** "
|
||||||
$ECHO "Hello world 1!" | $ZSTD -df
|
$ECHO "Hello world 1!" | $ZSTD -df
|
||||||
$ECHO "Hello world 2!" | $ZSTD -dcf
|
$ECHO "Hello world 2!" | $ZSTD -dcf
|
||||||
@@ -118,19 +135,19 @@ $ZSTD -c world.tmp > world.zstd
|
|||||||
cat hello.zstd world.zstd > helloworld.zstd
|
cat hello.zstd world.zstd > helloworld.zstd
|
||||||
$ZSTD -dc helloworld.zstd > result.tmp
|
$ZSTD -dc helloworld.zstd > result.tmp
|
||||||
cat result.tmp
|
cat result.tmp
|
||||||
sdiff helloworld.tmp result.tmp
|
$DIFF helloworld.tmp result.tmp
|
||||||
$ECHO "frame concatenation without checksum"
|
$ECHO "frame concatenation without checksum"
|
||||||
$ZSTD -c hello.tmp > hello.zstd --no-check
|
$ZSTD -c hello.tmp > hello.zstd --no-check
|
||||||
$ZSTD -c world.tmp > world.zstd --no-check
|
$ZSTD -c world.tmp > world.zstd --no-check
|
||||||
cat hello.zstd world.zstd > helloworld.zstd
|
cat hello.zstd world.zstd > helloworld.zstd
|
||||||
$ZSTD -dc helloworld.zstd > result.tmp
|
$ZSTD -dc helloworld.zstd > result.tmp
|
||||||
cat result.tmp
|
cat result.tmp
|
||||||
sdiff helloworld.tmp result.tmp
|
$DIFF helloworld.tmp result.tmp
|
||||||
rm ./*.tmp ./*.zstd
|
rm ./*.tmp ./*.zstd
|
||||||
$ECHO "frame concatenation tests completed"
|
$ECHO "frame concatenation tests completed"
|
||||||
|
|
||||||
|
|
||||||
if [ "$isWindows" = false ] ; then
|
if [ "$isWindows" = false ] && [ "$UNAME" != 'SunOS' ] ; then
|
||||||
$ECHO "\n**** flush write error test **** "
|
$ECHO "\n**** flush write error test **** "
|
||||||
|
|
||||||
$ECHO "$ECHO foo | $ZSTD > /dev/full"
|
$ECHO "$ECHO foo | $ZSTD > /dev/full"
|
||||||
@@ -144,14 +161,14 @@ $ECHO "\n**** test sparse file support **** "
|
|||||||
|
|
||||||
./datagen -g5M -P100 > tmpSparse
|
./datagen -g5M -P100 > tmpSparse
|
||||||
$ZSTD tmpSparse -c | $ZSTD -dv -o tmpSparseRegen
|
$ZSTD tmpSparse -c | $ZSTD -dv -o tmpSparseRegen
|
||||||
diff -s tmpSparse tmpSparseRegen
|
$DIFF -s tmpSparse tmpSparseRegen
|
||||||
$ZSTD tmpSparse -c | $ZSTD -dv --sparse -c > tmpOutSparse
|
$ZSTD tmpSparse -c | $ZSTD -dv --sparse -c > tmpOutSparse
|
||||||
diff -s tmpSparse tmpOutSparse
|
$DIFF -s tmpSparse tmpOutSparse
|
||||||
$ZSTD tmpSparse -c | $ZSTD -dv --no-sparse -c > tmpOutNoSparse
|
$ZSTD tmpSparse -c | $ZSTD -dv --no-sparse -c > tmpOutNoSparse
|
||||||
diff -s tmpSparse tmpOutNoSparse
|
$DIFF -s tmpSparse tmpOutNoSparse
|
||||||
ls -ls tmpSparse*
|
ls -ls tmpSparse*
|
||||||
./datagen -s1 -g1200007 -P100 | $ZSTD | $ZSTD -dv --sparse -c > tmpSparseOdd # Odd size file (to not finish on an exact nb of blocks)
|
./datagen -s1 -g1200007 -P100 | $ZSTD | $ZSTD -dv --sparse -c > tmpSparseOdd # Odd size file (to not finish on an exact nb of blocks)
|
||||||
./datagen -s1 -g1200007 -P100 | diff -s - tmpSparseOdd
|
./datagen -s1 -g1200007 -P100 | $DIFF -s - tmpSparseOdd
|
||||||
ls -ls tmpSparseOdd
|
ls -ls tmpSparseOdd
|
||||||
$ECHO "\n Sparse Compatibility with Console :"
|
$ECHO "\n Sparse Compatibility with Console :"
|
||||||
$ECHO "Hello World 1 !" | $ZSTD | $ZSTD -d -c
|
$ECHO "Hello World 1 !" | $ZSTD | $ZSTD -d -c
|
||||||
@@ -163,7 +180,7 @@ $ZSTD -v -f tmpSparse1M -o tmpSparseCompressed
|
|||||||
$ZSTD -d -v -f tmpSparseCompressed -o tmpSparseRegenerated
|
$ZSTD -d -v -f tmpSparseCompressed -o tmpSparseRegenerated
|
||||||
$ZSTD -d -v -f tmpSparseCompressed -c >> tmpSparseRegenerated
|
$ZSTD -d -v -f tmpSparseCompressed -c >> tmpSparseRegenerated
|
||||||
ls -ls tmpSparse*
|
ls -ls tmpSparse*
|
||||||
diff tmpSparse2M tmpSparseRegenerated
|
$DIFF tmpSparse2M tmpSparseRegenerated
|
||||||
rm tmpSparse*
|
rm tmpSparse*
|
||||||
|
|
||||||
|
|
||||||
@@ -196,13 +213,13 @@ TESTFILE=../programs/zstdcli.c
|
|||||||
./datagen > tmpDict
|
./datagen > tmpDict
|
||||||
./datagen -g1M | $MD5SUM > tmp1
|
./datagen -g1M | $MD5SUM > tmp1
|
||||||
./datagen -g1M | $ZSTD -D tmpDict | $ZSTD -D tmpDict -dvq | $MD5SUM > tmp2
|
./datagen -g1M | $ZSTD -D tmpDict | $ZSTD -D tmpDict -dvq | $MD5SUM > tmp2
|
||||||
diff -q tmp1 tmp2
|
$DIFF -q tmp1 tmp2
|
||||||
$ECHO "- Create first dictionary"
|
$ECHO "- Create first dictionary"
|
||||||
$ZSTD --train *.c ../programs/*.c -o tmpDict
|
$ZSTD --train *.c ../programs/*.c -o tmpDict
|
||||||
cp $TESTFILE tmp
|
cp $TESTFILE tmp
|
||||||
$ZSTD -f tmp -D tmpDict
|
$ZSTD -f tmp -D tmpDict
|
||||||
$ZSTD -d tmp.zst -D tmpDict -fo result
|
$ZSTD -d tmp.zst -D tmpDict -fo result
|
||||||
diff $TESTFILE result
|
$DIFF $TESTFILE result
|
||||||
$ECHO "- Create second (different) dictionary"
|
$ECHO "- Create second (different) dictionary"
|
||||||
$ZSTD --train *.c ../programs/*.c ../programs/*.h -o tmpDictC
|
$ZSTD --train *.c ../programs/*.c ../programs/*.h -o tmpDictC
|
||||||
$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
|
$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
|
||||||
@@ -218,7 +235,7 @@ $ZSTD --train *.c ../programs/*.c -o tmpDict2 --maxdict -v 4K && die "wrong orde
|
|||||||
$ECHO "- Compress without dictID"
|
$ECHO "- Compress without dictID"
|
||||||
$ZSTD -f tmp -D tmpDict1 --no-dictID
|
$ZSTD -f tmp -D tmpDict1 --no-dictID
|
||||||
$ZSTD -d tmp.zst -D tmpDict -fo result
|
$ZSTD -d tmp.zst -D tmpDict -fo result
|
||||||
diff $TESTFILE result
|
$DIFF $TESTFILE result
|
||||||
$ECHO "- Compress with wrong argument order (must fail)"
|
$ECHO "- Compress with wrong argument order (must fail)"
|
||||||
$ZSTD tmp -Df tmpDict1 -c > /dev/null && die "-D must be followed by dictionary name "
|
$ZSTD tmp -Df tmpDict1 -c > /dev/null && die "-D must be followed by dictionary name "
|
||||||
$ECHO "- Compress multiple files with dictionary"
|
$ECHO "- Compress multiple files with dictionary"
|
||||||
@@ -238,6 +255,27 @@ rm -rf dirTestDict
|
|||||||
rm tmp*
|
rm tmp*
|
||||||
|
|
||||||
|
|
||||||
|
$ECHO "\n**** cover dictionary tests **** "
|
||||||
|
|
||||||
|
TESTFILE=../programs/zstdcli.c
|
||||||
|
./datagen > tmpDict
|
||||||
|
$ECHO "- Create first dictionary"
|
||||||
|
$ZSTD --train --cover=k=46,d=8 *.c ../programs/*.c -o tmpDict
|
||||||
|
cp $TESTFILE tmp
|
||||||
|
$ZSTD -f tmp -D tmpDict
|
||||||
|
$ZSTD -d tmp.zst -D tmpDict -fo result
|
||||||
|
$DIFF $TESTFILE result
|
||||||
|
$ECHO "- Create second (different) dictionary"
|
||||||
|
$ZSTD --train --cover=k=56,d=8 *.c ../programs/*.c ../programs/*.h -o tmpDictC
|
||||||
|
$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
|
||||||
|
$ECHO "- Create dictionary with short dictID"
|
||||||
|
$ZSTD --train --cover=k=46,d=8 *.c ../programs/*.c --dictID 1 -o tmpDict1
|
||||||
|
cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
|
||||||
|
$ECHO "- Create dictionary with size limit"
|
||||||
|
$ZSTD --train --optimize-cover=steps=8 *.c ../programs/*.c -o tmpDict2 --maxdict 4K
|
||||||
|
rm tmp*
|
||||||
|
|
||||||
|
|
||||||
$ECHO "\n**** integrity tests **** "
|
$ECHO "\n**** integrity tests **** "
|
||||||
|
|
||||||
$ECHO "test one file (tmp1.zst) "
|
$ECHO "test one file (tmp1.zst) "
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#include "pool.h"
|
||||||
|
#include "threading.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define ASSERT_TRUE(p) \
|
||||||
|
do { \
|
||||||
|
if (!(p)) { \
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define ASSERT_FALSE(p) ASSERT_TRUE(!(p))
|
||||||
|
#define ASSERT_EQ(lhs, rhs) ASSERT_TRUE((lhs) == (rhs))
|
||||||
|
|
||||||
|
struct data {
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
unsigned data[16];
|
||||||
|
size_t i;
|
||||||
|
};
|
||||||
|
|
||||||
|
void fn(void *opaque) {
|
||||||
|
struct data *data = (struct data *)opaque;
|
||||||
|
pthread_mutex_lock(&data->mutex);
|
||||||
|
data->data[data->i] = data->i;
|
||||||
|
++data->i;
|
||||||
|
pthread_mutex_unlock(&data->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int testOrder(size_t numThreads, size_t queueSize) {
|
||||||
|
struct data data;
|
||||||
|
POOL_ctx *ctx = POOL_create(numThreads, queueSize);
|
||||||
|
ASSERT_TRUE(ctx);
|
||||||
|
data.i = 0;
|
||||||
|
pthread_mutex_init(&data.mutex, NULL);
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < 16; ++i) {
|
||||||
|
POOL_add(ctx, &fn, &data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
POOL_free(ctx);
|
||||||
|
ASSERT_EQ(16, data.i);
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < data.i; ++i) {
|
||||||
|
ASSERT_EQ(i, data.data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_destroy(&data.mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv) {
|
||||||
|
size_t numThreads;
|
||||||
|
for (numThreads = 1; numThreads <= 4; ++numThreads) {
|
||||||
|
size_t queueSize;
|
||||||
|
for (queueSize = 1; queueSize <= 2; ++queueSize) {
|
||||||
|
if (testOrder(numThreads, queueSize)) {
|
||||||
|
printf("FAIL: testOrder\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("PASS: testOrder\n");
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
return (POOL_create(0, 1) || POOL_create(1, 0)) ? printf("FAIL: testInvalid\n"), 1
|
||||||
|
: printf("PASS: testInvalid\n"), 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+145
@@ -0,0 +1,145 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "zstd_errors.h"
|
||||||
|
#define ZSTD_STATIC_LINKING_ONLY
|
||||||
|
#include "zstd.h"
|
||||||
|
#define ZBUFF_DISABLE_DEPRECATE_WARNINGS
|
||||||
|
#define ZBUFF_STATIC_LINKING_ONLY
|
||||||
|
#include "zbuff.h"
|
||||||
|
#define ZDICT_DISABLE_DEPRECATE_WARNINGS
|
||||||
|
#define ZDICT_STATIC_LINKING_ONLY
|
||||||
|
#include "zdict.h"
|
||||||
|
|
||||||
|
static const void *symbols[] = {
|
||||||
|
/* zstd.h */
|
||||||
|
&ZSTD_versionNumber,
|
||||||
|
&ZSTD_compress,
|
||||||
|
&ZSTD_decompress,
|
||||||
|
&ZSTD_getDecompressedSize,
|
||||||
|
&ZSTD_maxCLevel,
|
||||||
|
&ZSTD_compressBound,
|
||||||
|
&ZSTD_isError,
|
||||||
|
&ZSTD_getErrorName,
|
||||||
|
&ZSTD_createCCtx,
|
||||||
|
&ZSTD_freeCCtx,
|
||||||
|
&ZSTD_compressCCtx,
|
||||||
|
&ZSTD_createDCtx,
|
||||||
|
&ZSTD_freeDCtx,
|
||||||
|
&ZSTD_decompressDCtx,
|
||||||
|
&ZSTD_compress_usingDict,
|
||||||
|
&ZSTD_decompress_usingDict,
|
||||||
|
&ZSTD_createCDict,
|
||||||
|
&ZSTD_freeCDict,
|
||||||
|
&ZSTD_compress_usingCDict,
|
||||||
|
&ZSTD_createDDict,
|
||||||
|
&ZSTD_freeDDict,
|
||||||
|
&ZSTD_decompress_usingDDict,
|
||||||
|
&ZSTD_createCStream,
|
||||||
|
&ZSTD_freeCStream,
|
||||||
|
&ZSTD_initCStream,
|
||||||
|
&ZSTD_compressStream,
|
||||||
|
&ZSTD_flushStream,
|
||||||
|
&ZSTD_endStream,
|
||||||
|
&ZSTD_CStreamInSize,
|
||||||
|
&ZSTD_CStreamOutSize,
|
||||||
|
&ZSTD_createDStream,
|
||||||
|
&ZSTD_freeDStream,
|
||||||
|
&ZSTD_initDStream,
|
||||||
|
&ZSTD_decompressStream,
|
||||||
|
&ZSTD_DStreamInSize,
|
||||||
|
&ZSTD_DStreamOutSize,
|
||||||
|
/* zstd.h: advanced functions */
|
||||||
|
&ZSTD_estimateCCtxSize,
|
||||||
|
&ZSTD_createCCtx_advanced,
|
||||||
|
&ZSTD_sizeof_CCtx,
|
||||||
|
&ZSTD_createCDict_advanced,
|
||||||
|
&ZSTD_sizeof_CDict,
|
||||||
|
&ZSTD_getCParams,
|
||||||
|
&ZSTD_getParams,
|
||||||
|
&ZSTD_checkCParams,
|
||||||
|
&ZSTD_adjustCParams,
|
||||||
|
&ZSTD_compress_advanced,
|
||||||
|
&ZSTD_isFrame,
|
||||||
|
&ZSTD_estimateDCtxSize,
|
||||||
|
&ZSTD_createDCtx_advanced,
|
||||||
|
&ZSTD_sizeof_DCtx,
|
||||||
|
&ZSTD_sizeof_DDict,
|
||||||
|
&ZSTD_getDictID_fromDict,
|
||||||
|
&ZSTD_getDictID_fromDDict,
|
||||||
|
&ZSTD_getDictID_fromFrame,
|
||||||
|
&ZSTD_createCStream_advanced,
|
||||||
|
&ZSTD_initCStream_srcSize,
|
||||||
|
&ZSTD_initCStream_usingDict,
|
||||||
|
&ZSTD_initCStream_advanced,
|
||||||
|
&ZSTD_initCStream_usingCDict,
|
||||||
|
&ZSTD_resetCStream,
|
||||||
|
&ZSTD_sizeof_CStream,
|
||||||
|
&ZSTD_createDStream_advanced,
|
||||||
|
&ZSTD_initDStream_usingDict,
|
||||||
|
&ZSTD_setDStreamParameter,
|
||||||
|
&ZSTD_initDStream_usingDDict,
|
||||||
|
&ZSTD_resetDStream,
|
||||||
|
&ZSTD_sizeof_DStream,
|
||||||
|
&ZSTD_compressBegin,
|
||||||
|
&ZSTD_compressBegin_usingDict,
|
||||||
|
&ZSTD_compressBegin_advanced,
|
||||||
|
&ZSTD_copyCCtx,
|
||||||
|
&ZSTD_compressContinue,
|
||||||
|
&ZSTD_compressEnd,
|
||||||
|
&ZSTD_getFrameParams,
|
||||||
|
&ZSTD_decompressBegin,
|
||||||
|
&ZSTD_decompressBegin_usingDict,
|
||||||
|
&ZSTD_copyDCtx,
|
||||||
|
&ZSTD_nextSrcSizeToDecompress,
|
||||||
|
&ZSTD_decompressContinue,
|
||||||
|
&ZSTD_nextInputType,
|
||||||
|
&ZSTD_getBlockSizeMax,
|
||||||
|
&ZSTD_compressBlock,
|
||||||
|
&ZSTD_decompressBlock,
|
||||||
|
&ZSTD_insertBlock,
|
||||||
|
/* zstd_errors.h */
|
||||||
|
&ZSTD_getErrorCode,
|
||||||
|
&ZSTD_getErrorString,
|
||||||
|
/* zbuff.h */
|
||||||
|
&ZBUFF_createCCtx,
|
||||||
|
&ZBUFF_freeCCtx,
|
||||||
|
&ZBUFF_compressInit,
|
||||||
|
&ZBUFF_compressInitDictionary,
|
||||||
|
&ZBUFF_compressContinue,
|
||||||
|
&ZBUFF_compressFlush,
|
||||||
|
&ZBUFF_compressEnd,
|
||||||
|
&ZBUFF_createDCtx,
|
||||||
|
&ZBUFF_freeDCtx,
|
||||||
|
&ZBUFF_decompressInit,
|
||||||
|
&ZBUFF_decompressInitDictionary,
|
||||||
|
&ZBUFF_decompressContinue,
|
||||||
|
&ZBUFF_isError,
|
||||||
|
&ZBUFF_getErrorName,
|
||||||
|
&ZBUFF_recommendedCInSize,
|
||||||
|
&ZBUFF_recommendedCOutSize,
|
||||||
|
&ZBUFF_recommendedDInSize,
|
||||||
|
&ZBUFF_recommendedDOutSize,
|
||||||
|
/* zbuff.h: advanced functions */
|
||||||
|
&ZBUFF_createCCtx_advanced,
|
||||||
|
&ZBUFF_createDCtx_advanced,
|
||||||
|
&ZBUFF_compressInit_advanced,
|
||||||
|
/* zdict.h */
|
||||||
|
&ZDICT_trainFromBuffer,
|
||||||
|
&ZDICT_getDictID,
|
||||||
|
&ZDICT_isError,
|
||||||
|
&ZDICT_getErrorName,
|
||||||
|
/* zdict.h: advanced functions */
|
||||||
|
&ZDICT_trainFromBuffer_advanced,
|
||||||
|
&ZDICT_addEntropyTablesFromBuffer,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, const char** argv) {
|
||||||
|
const void **symbol;
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
for (symbol = symbols; *symbol != NULL; ++symbol) {
|
||||||
|
printf("%p\n", *symbol);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+378
-60
@@ -26,9 +26,11 @@
|
|||||||
#include <time.h> /* clock_t, clock() */
|
#include <time.h> /* clock_t, clock() */
|
||||||
#include <string.h> /* strcmp */
|
#include <string.h> /* strcmp */
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel, ZSTD_customMem */
|
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel, ZSTD_customMem, ZSTD_getDictID_fromFrame */
|
||||||
#include "zstd.h" /* ZSTD_compressBound */
|
#include "zstd.h" /* ZSTD_compressBound */
|
||||||
#include "zstd_errors.h" /* ZSTD_error_srcSize_wrong */
|
#include "zstd_errors.h" /* ZSTD_error_srcSize_wrong */
|
||||||
|
#include "zstdmt_compress.h"
|
||||||
|
#include "zdict.h" /* ZDICT_trainFromBuffer */
|
||||||
#include "datagen.h" /* RDG_genBuffer */
|
#include "datagen.h" /* RDG_genBuffer */
|
||||||
#define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
#define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
||||||
#include "xxhash.h" /* XXH64_* */
|
#include "xxhash.h" /* XXH64_* */
|
||||||
@@ -44,8 +46,7 @@
|
|||||||
static const U32 nbTestsDefault = 10000;
|
static const U32 nbTestsDefault = 10000;
|
||||||
#define COMPRESSIBLE_NOISE_LENGTH (10 MB)
|
#define COMPRESSIBLE_NOISE_LENGTH (10 MB)
|
||||||
#define FUZ_COMPRESSIBILITY_DEFAULT 50
|
#define FUZ_COMPRESSIBILITY_DEFAULT 50
|
||||||
static const U32 prime1 = 2654435761U;
|
static const U32 prime32 = 2654435761U;
|
||||||
static const U32 prime2 = 2246822519U;
|
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
@@ -81,8 +82,9 @@ static clock_t FUZ_GetClockSpan(clock_t clockStart)
|
|||||||
#define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
#define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||||
unsigned int FUZ_rand(unsigned int* seedPtr)
|
unsigned int FUZ_rand(unsigned int* seedPtr)
|
||||||
{
|
{
|
||||||
|
static const U32 prime2 = 2246822519U;
|
||||||
U32 rand32 = *seedPtr;
|
U32 rand32 = *seedPtr;
|
||||||
rand32 *= prime1;
|
rand32 *= prime32;
|
||||||
rand32 += prime2;
|
rand32 += prime2;
|
||||||
rand32 = FUZ_rotl32(rand32, 13);
|
rand32 = FUZ_rotl32(rand32, 13);
|
||||||
*seedPtr = rand32;
|
*seedPtr = rand32;
|
||||||
@@ -107,6 +109,41 @@ static void freeFunction(void* opaque, void* address)
|
|||||||
* Basic Unit tests
|
* Basic Unit tests
|
||||||
======================================================*/
|
======================================================*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* start;
|
||||||
|
size_t size;
|
||||||
|
size_t filled;
|
||||||
|
} buffer_t;
|
||||||
|
|
||||||
|
static const buffer_t g_nullBuffer = { NULL, 0 , 0 };
|
||||||
|
|
||||||
|
static buffer_t FUZ_createDictionary(const void* src, size_t srcSize, size_t blockSize, size_t requestedDictSize)
|
||||||
|
{
|
||||||
|
buffer_t dict = { NULL, 0, 0 };
|
||||||
|
size_t const nbBlocks = (srcSize + (blockSize-1)) / blockSize;
|
||||||
|
size_t* const blockSizes = (size_t*) malloc(nbBlocks * sizeof(size_t));
|
||||||
|
if (!blockSizes) return dict;
|
||||||
|
dict.start = malloc(requestedDictSize);
|
||||||
|
if (!dict.start) { free(blockSizes); return dict; }
|
||||||
|
{ size_t nb;
|
||||||
|
for (nb=0; nb<nbBlocks-1; nb++) blockSizes[nb] = blockSize;
|
||||||
|
blockSizes[nbBlocks-1] = srcSize - (blockSize * (nbBlocks-1));
|
||||||
|
}
|
||||||
|
{ size_t const dictSize = ZDICT_trainFromBuffer(dict.start, requestedDictSize, src, blockSizes, (unsigned)nbBlocks);
|
||||||
|
free(blockSizes);
|
||||||
|
if (ZDICT_isError(dictSize)) { free(dict.start); return (buffer_t){ NULL, 0, 0 }; }
|
||||||
|
dict.size = requestedDictSize;
|
||||||
|
dict.filled = dictSize;
|
||||||
|
return dict; /* how to return dictSize ? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FUZ_freeDictionary(buffer_t dict)
|
||||||
|
{
|
||||||
|
free(dict.start);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem customMem)
|
static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem customMem)
|
||||||
{
|
{
|
||||||
size_t const CNBufferSize = COMPRESSIBLE_NOISE_LENGTH;
|
size_t const CNBufferSize = COMPRESSIBLE_NOISE_LENGTH;
|
||||||
@@ -123,21 +160,32 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
ZSTD_DStream* zd = ZSTD_createDStream_advanced(customMem);
|
ZSTD_DStream* zd = ZSTD_createDStream_advanced(customMem);
|
||||||
ZSTD_inBuffer inBuff, inBuff2;
|
ZSTD_inBuffer inBuff, inBuff2;
|
||||||
ZSTD_outBuffer outBuff;
|
ZSTD_outBuffer outBuff;
|
||||||
|
buffer_t dictionary = g_nullBuffer;
|
||||||
|
unsigned dictID = 0;
|
||||||
|
|
||||||
/* Create compressible test buffer */
|
/* Create compressible test buffer */
|
||||||
if (!CNBuffer || !compressedBuffer || !decodedBuffer || !zc || !zd) {
|
if (!CNBuffer || !compressedBuffer || !decodedBuffer || !zc || !zd) {
|
||||||
DISPLAY("Not enough memory, aborting\n");
|
DISPLAY("Not enough memory, aborting \n");
|
||||||
goto _output_error;
|
goto _output_error;
|
||||||
}
|
}
|
||||||
RDG_genBuffer(CNBuffer, CNBufferSize, compressibility, 0., seed);
|
RDG_genBuffer(CNBuffer, CNBufferSize, compressibility, 0., seed);
|
||||||
|
|
||||||
|
/* Create dictionary */
|
||||||
|
MEM_STATIC_ASSERT(COMPRESSIBLE_NOISE_LENGTH >= 4 MB);
|
||||||
|
dictionary = FUZ_createDictionary(CNBuffer, 4 MB, 4 KB, 40 KB);
|
||||||
|
if (!dictionary.start) {
|
||||||
|
DISPLAY("Error creating dictionary, aborting \n");
|
||||||
|
goto _output_error;
|
||||||
|
}
|
||||||
|
dictID = ZDICT_getDictID(dictionary.start, dictionary.filled);
|
||||||
|
|
||||||
/* generate skippable frame */
|
/* generate skippable frame */
|
||||||
MEM_writeLE32(compressedBuffer, ZSTD_MAGIC_SKIPPABLE_START);
|
MEM_writeLE32(compressedBuffer, ZSTD_MAGIC_SKIPPABLE_START);
|
||||||
MEM_writeLE32(((char*)compressedBuffer)+4, (U32)skippableFrameSize);
|
MEM_writeLE32(((char*)compressedBuffer)+4, (U32)skippableFrameSize);
|
||||||
cSize = skippableFrameSize + 8;
|
cSize = skippableFrameSize + 8;
|
||||||
|
|
||||||
/* Basic compression test */
|
/* Basic compression test */
|
||||||
DISPLAYLEVEL(4, "test%3i : compress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
|
DISPLAYLEVEL(3, "test%3i : compress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
|
||||||
ZSTD_initCStream_usingDict(zc, CNBuffer, 128 KB, 1);
|
ZSTD_initCStream_usingDict(zc, CNBuffer, 128 KB, 1);
|
||||||
outBuff.dst = (char*)(compressedBuffer)+cSize;
|
outBuff.dst = (char*)(compressedBuffer)+cSize;
|
||||||
outBuff.size = compressedBufferSize;
|
outBuff.size = compressedBufferSize;
|
||||||
@@ -151,16 +199,16 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
||||||
if (r != 0) goto _output_error; } /* error, or some data not flushed */
|
if (r != 0) goto _output_error; } /* error, or some data not flushed */
|
||||||
cSize += outBuff.pos;
|
cSize += outBuff.pos;
|
||||||
DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
|
DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
|
||||||
|
|
||||||
DISPLAYLEVEL(4, "test%3i : check CStream size : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : check CStream size : ", testNb++);
|
||||||
{ size_t const s = ZSTD_sizeof_CStream(zc);
|
{ size_t const s = ZSTD_sizeof_CStream(zc);
|
||||||
if (ZSTD_isError(s)) goto _output_error;
|
if (ZSTD_isError(s)) goto _output_error;
|
||||||
DISPLAYLEVEL(4, "OK (%u bytes) \n", (U32)s);
|
DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skippable frame test */
|
/* skippable frame test */
|
||||||
DISPLAYLEVEL(4, "test%3i : decompress skippable frame : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : decompress skippable frame : ", testNb++);
|
||||||
ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
|
ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
|
||||||
inBuff.src = compressedBuffer;
|
inBuff.src = compressedBuffer;
|
||||||
inBuff.size = cSize;
|
inBuff.size = cSize;
|
||||||
@@ -171,45 +219,45 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
{ size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
{ size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
||||||
if (r != 0) goto _output_error; }
|
if (r != 0) goto _output_error; }
|
||||||
if (outBuff.pos != 0) goto _output_error; /* skippable frame len is 0 */
|
if (outBuff.pos != 0) goto _output_error; /* skippable frame len is 0 */
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
/* Basic decompression test */
|
/* Basic decompression test */
|
||||||
inBuff2 = inBuff;
|
inBuff2 = inBuff;
|
||||||
DISPLAYLEVEL(4, "test%3i : decompress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
|
DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
|
||||||
ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
|
ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
|
||||||
{ size_t const r = ZSTD_setDStreamParameter(zd, ZSTDdsp_maxWindowSize, 1000000000); /* large limit */
|
{ size_t const r = ZSTD_setDStreamParameter(zd, DStream_p_maxWindowSize, 1000000000); /* large limit */
|
||||||
if (ZSTD_isError(r)) goto _output_error; }
|
if (ZSTD_isError(r)) goto _output_error; }
|
||||||
{ size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
{ size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
||||||
if (remaining != 0) goto _output_error; } /* should reach end of frame == 0; otherwise, some data left, or an error */
|
if (remaining != 0) goto _output_error; } /* should reach end of frame == 0; otherwise, some data left, or an error */
|
||||||
if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */
|
if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */
|
||||||
if (inBuff.pos != inBuff.size) goto _output_error; /* should have read the entire frame */
|
if (inBuff.pos != inBuff.size) goto _output_error; /* should have read the entire frame */
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
/* Re-use without init */
|
/* Re-use without init */
|
||||||
DISPLAYLEVEL(4, "test%3i : decompress again without init (re-use previous settings): ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : decompress again without init (re-use previous settings): ", testNb++);
|
||||||
outBuff.pos = 0;
|
outBuff.pos = 0;
|
||||||
{ size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff2);
|
{ size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff2);
|
||||||
if (remaining != 0) goto _output_error; } /* should reach end of frame == 0; otherwise, some data left, or an error */
|
if (remaining != 0) goto _output_error; } /* should reach end of frame == 0; otherwise, some data left, or an error */
|
||||||
if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */
|
if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */
|
||||||
if (inBuff.pos != inBuff.size) goto _output_error; /* should have read the entire frame */
|
if (inBuff.pos != inBuff.size) goto _output_error; /* should have read the entire frame */
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
/* check regenerated data is byte exact */
|
/* check regenerated data is byte exact */
|
||||||
DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
|
||||||
{ size_t i;
|
{ size_t i;
|
||||||
for (i=0; i<CNBufferSize; i++) {
|
for (i=0; i<CNBufferSize; i++) {
|
||||||
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;
|
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;
|
||||||
} }
|
} }
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
DISPLAYLEVEL(4, "test%3i : check DStream size : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : check DStream size : ", testNb++);
|
||||||
{ size_t const s = ZSTD_sizeof_DStream(zd);
|
{ size_t const s = ZSTD_sizeof_DStream(zd);
|
||||||
if (ZSTD_isError(s)) goto _output_error;
|
if (ZSTD_isError(s)) goto _output_error;
|
||||||
DISPLAYLEVEL(4, "OK (%u bytes) \n", (U32)s);
|
DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Byte-by-byte decompression test */
|
/* Byte-by-byte decompression test */
|
||||||
DISPLAYLEVEL(4, "test%3i : decompress byte-by-byte : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : decompress byte-by-byte : ", testNb++);
|
||||||
{ /* skippable frame */
|
{ /* skippable frame */
|
||||||
size_t r = 1;
|
size_t r = 1;
|
||||||
ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
|
ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
|
||||||
@@ -235,20 +283,20 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
}
|
}
|
||||||
if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */
|
if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */
|
||||||
if (inBuff.pos != cSize) goto _output_error; /* should have read the entire frame */
|
if (inBuff.pos != cSize) goto _output_error; /* should have read the entire frame */
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
/* check regenerated data is byte exact */
|
/* check regenerated data is byte exact */
|
||||||
DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
|
||||||
{ size_t i;
|
{ size_t i;
|
||||||
for (i=0; i<CNBufferSize; i++) {
|
for (i=0; i<CNBufferSize; i++) {
|
||||||
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;;
|
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;;
|
||||||
} }
|
} }
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
/* _srcSize compression test */
|
/* _srcSize compression test */
|
||||||
DISPLAYLEVEL(4, "test%3i : compress_srcSize %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
|
DISPLAYLEVEL(3, "test%3i : compress_srcSize %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
|
||||||
ZSTD_initCStream_srcSize(zc, 1, CNBufferSize);
|
ZSTD_initCStream_srcSize(zc, 1, CNBufferSize);
|
||||||
outBuff.dst = (char*)(compressedBuffer)+cSize;
|
outBuff.dst = (char*)(compressedBuffer);
|
||||||
outBuff.size = compressedBufferSize;
|
outBuff.size = compressedBufferSize;
|
||||||
outBuff.pos = 0;
|
outBuff.pos = 0;
|
||||||
inBuff.src = CNBuffer;
|
inBuff.src = CNBuffer;
|
||||||
@@ -259,12 +307,14 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
|
if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
|
||||||
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
||||||
if (r != 0) goto _output_error; } /* error, or some data not flushed */
|
if (r != 0) goto _output_error; } /* error, or some data not flushed */
|
||||||
DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
|
{ unsigned long long origSize = ZSTD_getDecompressedSize(outBuff.dst, outBuff.pos);
|
||||||
|
if ((size_t)origSize != CNBufferSize) goto _output_error; } /* exact original size must be present */
|
||||||
|
DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
|
||||||
|
|
||||||
/* wrong _srcSize compression test */
|
/* wrong _srcSize compression test */
|
||||||
DISPLAYLEVEL(4, "test%3i : wrong srcSize : %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH-1);
|
DISPLAYLEVEL(3, "test%3i : wrong srcSize : %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH-1);
|
||||||
ZSTD_initCStream_srcSize(zc, 1, CNBufferSize-1);
|
ZSTD_initCStream_srcSize(zc, 1, CNBufferSize-1);
|
||||||
outBuff.dst = (char*)(compressedBuffer)+cSize;
|
outBuff.dst = (char*)(compressedBuffer);
|
||||||
outBuff.size = compressedBufferSize;
|
outBuff.size = compressedBufferSize;
|
||||||
outBuff.pos = 0;
|
outBuff.pos = 0;
|
||||||
inBuff.src = CNBuffer;
|
inBuff.src = CNBuffer;
|
||||||
@@ -275,10 +325,10 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
|
if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */
|
||||||
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
||||||
if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; /* must fail : wrong srcSize */
|
if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; /* must fail : wrong srcSize */
|
||||||
DISPLAYLEVEL(4, "OK (error detected : %s) \n", ZSTD_getErrorName(r)); }
|
DISPLAYLEVEL(3, "OK (error detected : %s) \n", ZSTD_getErrorName(r)); }
|
||||||
|
|
||||||
/* Complex context re-use scenario */
|
/* Complex context re-use scenario */
|
||||||
DISPLAYLEVEL(4, "test%3i : context re-use : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : context re-use : ", testNb++);
|
||||||
ZSTD_freeCStream(zc);
|
ZSTD_freeCStream(zc);
|
||||||
zc = ZSTD_createCStream_advanced(customMem);
|
zc = ZSTD_createCStream_advanced(customMem);
|
||||||
if (zc==NULL) goto _output_error; /* memory allocation issue */
|
if (zc==NULL) goto _output_error; /* memory allocation issue */
|
||||||
@@ -312,11 +362,11 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
{ size_t const r = ZSTD_endStream(zc, &outBuff);
|
||||||
if (r != 0) goto _output_error; } /* error, or some data not flushed */
|
if (r != 0) goto _output_error; } /* error, or some data not flushed */
|
||||||
}
|
}
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
/* CDict scenario */
|
/* CDict scenario */
|
||||||
DISPLAYLEVEL(4, "test%3i : digested dictionary : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : digested dictionary : ", testNb++);
|
||||||
{ ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, 128 KB, 1);
|
{ ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, 1);
|
||||||
size_t const initError = ZSTD_initCStream_usingCDict(zc, cdict);
|
size_t const initError = ZSTD_initCStream_usingCDict(zc, cdict);
|
||||||
if (ZSTD_isError(initError)) goto _output_error;
|
if (ZSTD_isError(initError)) goto _output_error;
|
||||||
cSize = 0;
|
cSize = 0;
|
||||||
@@ -333,18 +383,24 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
if (r != 0) goto _output_error; } /* error, or some data not flushed */
|
if (r != 0) goto _output_error; } /* error, or some data not flushed */
|
||||||
cSize = outBuff.pos;
|
cSize = outBuff.pos;
|
||||||
ZSTD_freeCDict(cdict);
|
ZSTD_freeCDict(cdict);
|
||||||
DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBufferSize*100);
|
DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBufferSize*100);
|
||||||
}
|
}
|
||||||
|
|
||||||
DISPLAYLEVEL(4, "test%3i : check CStream size : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : check CStream size : ", testNb++);
|
||||||
{ size_t const s = ZSTD_sizeof_CStream(zc);
|
{ size_t const s = ZSTD_sizeof_CStream(zc);
|
||||||
if (ZSTD_isError(s)) goto _output_error;
|
if (ZSTD_isError(s)) goto _output_error;
|
||||||
DISPLAYLEVEL(4, "OK (%u bytes) \n", (U32)s);
|
DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
|
||||||
|
}
|
||||||
|
|
||||||
|
DISPLAYLEVEL(4, "test%3i : check Dictionary ID : ", testNb++);
|
||||||
|
{ unsigned const dID = ZSTD_getDictID_fromFrame(compressedBuffer, cSize);
|
||||||
|
if (dID != dictID) goto _output_error;
|
||||||
|
DISPLAYLEVEL(4, "OK (%u) \n", dID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DDict scenario */
|
/* DDict scenario */
|
||||||
DISPLAYLEVEL(4, "test%3i : decompress %u bytes with digested dictionary : ", testNb++, (U32)CNBufferSize);
|
DISPLAYLEVEL(3, "test%3i : decompress %u bytes with digested dictionary : ", testNb++, (U32)CNBufferSize);
|
||||||
{ ZSTD_DDict* const ddict = ZSTD_createDDict(CNBuffer, 128 KB);
|
{ ZSTD_DDict* const ddict = ZSTD_createDDict(dictionary.start, dictionary.filled);
|
||||||
size_t const initError = ZSTD_initDStream_usingDDict(zd, ddict);
|
size_t const initError = ZSTD_initDStream_usingDDict(zd, ddict);
|
||||||
if (ZSTD_isError(initError)) goto _output_error;
|
if (ZSTD_isError(initError)) goto _output_error;
|
||||||
inBuff.src = compressedBuffer;
|
inBuff.src = compressedBuffer;
|
||||||
@@ -358,19 +414,19 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */
|
if (outBuff.pos != CNBufferSize) goto _output_error; /* should regenerate the same amount */
|
||||||
if (inBuff.pos != inBuff.size) goto _output_error; /* should have read the entire frame */
|
if (inBuff.pos != inBuff.size) goto _output_error; /* should have read the entire frame */
|
||||||
ZSTD_freeDDict(ddict);
|
ZSTD_freeDDict(ddict);
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* test ZSTD_setDStreamParameter() resilience */
|
/* test ZSTD_setDStreamParameter() resilience */
|
||||||
DISPLAYLEVEL(4, "test%3i : wrong parameter for ZSTD_setDStreamParameter(): ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : wrong parameter for ZSTD_setDStreamParameter(): ", testNb++);
|
||||||
{ size_t const r = ZSTD_setDStreamParameter(zd, (ZSTD_DStreamParameter_e)999, 1); /* large limit */
|
{ size_t const r = ZSTD_setDStreamParameter(zd, (ZSTD_DStreamParameter_e)999, 1); /* large limit */
|
||||||
if (!ZSTD_isError(r)) goto _output_error; }
|
if (!ZSTD_isError(r)) goto _output_error; }
|
||||||
DISPLAYLEVEL(4, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
/* Memory restriction */
|
/* Memory restriction */
|
||||||
DISPLAYLEVEL(4, "test%3i : maxWindowSize < frame requirement : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : maxWindowSize < frame requirement : ", testNb++);
|
||||||
ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
|
ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
|
||||||
{ size_t const r = ZSTD_setDStreamParameter(zd, ZSTDdsp_maxWindowSize, 1000); /* too small limit */
|
{ size_t const r = ZSTD_setDStreamParameter(zd, DStream_p_maxWindowSize, 1000); /* too small limit */
|
||||||
if (ZSTD_isError(r)) goto _output_error; }
|
if (ZSTD_isError(r)) goto _output_error; }
|
||||||
inBuff.src = compressedBuffer;
|
inBuff.src = compressedBuffer;
|
||||||
inBuff.size = cSize;
|
inBuff.size = cSize;
|
||||||
@@ -380,10 +436,11 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
|
|||||||
outBuff.pos = 0;
|
outBuff.pos = 0;
|
||||||
{ size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
{ size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
||||||
if (!ZSTD_isError(r)) goto _output_error; /* must fail : frame requires > 100 bytes */
|
if (!ZSTD_isError(r)) goto _output_error; /* must fail : frame requires > 100 bytes */
|
||||||
DISPLAYLEVEL(4, "OK (%s)\n", ZSTD_getErrorName(r)); }
|
DISPLAYLEVEL(3, "OK (%s)\n", ZSTD_getErrorName(r)); }
|
||||||
|
|
||||||
|
|
||||||
_end:
|
_end:
|
||||||
|
FUZ_freeDictionary(dictionary);
|
||||||
ZSTD_freeCStream(zc);
|
ZSTD_freeCStream(zc);
|
||||||
ZSTD_freeDStream(zd);
|
ZSTD_freeDStream(zd);
|
||||||
free(CNBuffer);
|
free(CNBuffer);
|
||||||
@@ -408,6 +465,11 @@ static size_t findDiff(const void* buf1, const void* buf2, size_t max)
|
|||||||
for (u=0; u<max; u++) {
|
for (u=0; u<max; u++) {
|
||||||
if (b1[u] != b2[u]) break;
|
if (b1[u] != b2[u]) break;
|
||||||
}
|
}
|
||||||
|
DISPLAY("Error at position %u / %u \n", (U32)u, (U32)max);
|
||||||
|
DISPLAY(" %02X %02X %02X :%02X: %02X %02X %02X %02X %02X \n",
|
||||||
|
b1[u-3], b1[u-2], b1[u-1], b1[u-0], b1[u+1], b1[u+2], b1[u+3], b1[u+4], b1[u+5]);
|
||||||
|
DISPLAY(" %02X %02X %02X :%02X: %02X %02X %02X %02X %02X \n",
|
||||||
|
b2[u-3], b2[u-2], b2[u-1], b2[u-0], b2[u+1], b2[u+2], b2[u+3], b2[u+4], b2[u+5]);
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,7 +550,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
|
|||||||
if (nbTests >= testNb) { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); }
|
if (nbTests >= testNb) { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); }
|
||||||
else { DISPLAYUPDATE(2, "\r%6u ", testNb); }
|
else { DISPLAYUPDATE(2, "\r%6u ", testNb); }
|
||||||
FUZ_rand(&coreSeed);
|
FUZ_rand(&coreSeed);
|
||||||
lseed = coreSeed ^ prime1;
|
lseed = coreSeed ^ prime32;
|
||||||
|
|
||||||
/* states full reset (deliberately not synchronized) */
|
/* states full reset (deliberately not synchronized) */
|
||||||
/* some issues can only happen when reusing states */
|
/* some issues can only happen when reusing states */
|
||||||
@@ -629,10 +691,13 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
|
|||||||
size_t const randomCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
|
size_t const randomCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
size_t const adjustedDstSize = MIN(dstBufferSize - outBuff.pos, randomDstSize);
|
size_t const adjustedDstSize = MIN(dstBufferSize - outBuff.pos, randomDstSize);
|
||||||
|
size_t const adjustedCSrcSize = MIN(cSize - inBuff.pos, randomCSrcSize);
|
||||||
outBuff.size = outBuff.pos + adjustedDstSize;
|
outBuff.size = outBuff.pos + adjustedDstSize;
|
||||||
inBuff.size = inBuff.pos + randomCSrcSize;
|
inBuff.size = inBuff.pos + adjustedCSrcSize;
|
||||||
{ size_t const decompressError = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
{ size_t const decompressError = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
||||||
if (ZSTD_isError(decompressError)) break; /* error correctly detected */
|
if (ZSTD_isError(decompressError)) break; /* error correctly detected */
|
||||||
|
/* No forward progress possible */
|
||||||
|
if (outBuff.pos < outBuff.size && inBuff.pos == cSize) break;
|
||||||
} } } }
|
} } } }
|
||||||
DISPLAY("\r%u fuzzer tests completed \n", testNb);
|
DISPLAY("\r%u fuzzer tests completed \n", testNb);
|
||||||
|
|
||||||
@@ -656,6 +721,253 @@ _output_error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Multi-threading version of fuzzer Tests */
|
||||||
|
static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double compressibility)
|
||||||
|
{
|
||||||
|
static const U32 maxSrcLog = 24;
|
||||||
|
static const U32 maxSampleLog = 19;
|
||||||
|
size_t const srcBufferSize = (size_t)1<<maxSrcLog;
|
||||||
|
BYTE* cNoiseBuffer[5];
|
||||||
|
size_t const copyBufferSize= srcBufferSize + (1<<maxSampleLog);
|
||||||
|
BYTE* const copyBuffer = (BYTE*)malloc (copyBufferSize);
|
||||||
|
size_t const cBufferSize = ZSTD_compressBound(srcBufferSize);
|
||||||
|
BYTE* const cBuffer = (BYTE*)malloc (cBufferSize);
|
||||||
|
size_t const dstBufferSize = srcBufferSize;
|
||||||
|
BYTE* const dstBuffer = (BYTE*)malloc (dstBufferSize);
|
||||||
|
U32 result = 0;
|
||||||
|
U32 testNb = 0;
|
||||||
|
U32 coreSeed = seed;
|
||||||
|
ZSTDMT_CCtx* zc = ZSTDMT_createCCtx(2); /* will be reset sometimes */
|
||||||
|
ZSTD_DStream* zd = ZSTD_createDStream(); /* will be reset sometimes */
|
||||||
|
ZSTD_DStream* const zd_noise = ZSTD_createDStream();
|
||||||
|
clock_t const startClock = clock();
|
||||||
|
const BYTE* dict=NULL; /* can keep same dict on 2 consecutive tests */
|
||||||
|
size_t dictSize = 0;
|
||||||
|
U32 oldTestLog = 0;
|
||||||
|
|
||||||
|
/* allocations */
|
||||||
|
cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
|
||||||
|
cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize);
|
||||||
|
cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize);
|
||||||
|
cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize);
|
||||||
|
cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize);
|
||||||
|
CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4] ||
|
||||||
|
!copyBuffer || !dstBuffer || !cBuffer || !zc || !zd || !zd_noise ,
|
||||||
|
"Not enough memory, fuzzer tests cancelled");
|
||||||
|
|
||||||
|
/* Create initial samples */
|
||||||
|
RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed); /* pure noise */
|
||||||
|
RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed); /* barely compressible */
|
||||||
|
RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed);
|
||||||
|
RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed); /* highly compressible */
|
||||||
|
RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed); /* sparse content */
|
||||||
|
memset(copyBuffer, 0x65, copyBufferSize); /* make copyBuffer considered initialized */
|
||||||
|
ZSTD_initDStream_usingDict(zd, NULL, 0); /* ensure at least one init */
|
||||||
|
|
||||||
|
/* catch up testNb */
|
||||||
|
for (testNb=1; testNb < startTest; testNb++)
|
||||||
|
FUZ_rand(&coreSeed);
|
||||||
|
|
||||||
|
/* test loop */
|
||||||
|
for ( ; (testNb <= nbTests) || (FUZ_GetClockSpan(startClock) < g_clockTime) ; testNb++ ) {
|
||||||
|
U32 lseed;
|
||||||
|
const BYTE* srcBuffer;
|
||||||
|
size_t totalTestSize, totalGenSize, cSize;
|
||||||
|
XXH64_state_t xxhState;
|
||||||
|
U64 crcOrig;
|
||||||
|
U32 resetAllowed = 1;
|
||||||
|
size_t maxTestSize;
|
||||||
|
|
||||||
|
/* init */
|
||||||
|
if (nbTests >= testNb) { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); }
|
||||||
|
else { DISPLAYUPDATE(2, "\r%6u ", testNb); }
|
||||||
|
FUZ_rand(&coreSeed);
|
||||||
|
lseed = coreSeed ^ prime32;
|
||||||
|
|
||||||
|
/* states full reset (deliberately not synchronized) */
|
||||||
|
/* some issues can only happen when reusing states */
|
||||||
|
if ((FUZ_rand(&lseed) & 0xFF) == 131) {
|
||||||
|
U32 const nbThreads = (FUZ_rand(&lseed) % 6) + 1;
|
||||||
|
ZSTDMT_freeCCtx(zc);
|
||||||
|
zc = ZSTDMT_createCCtx(nbThreads);
|
||||||
|
resetAllowed=0;
|
||||||
|
}
|
||||||
|
if ((FUZ_rand(&lseed) & 0xFF) == 132) {
|
||||||
|
ZSTD_freeDStream(zd);
|
||||||
|
zd = ZSTD_createDStream();
|
||||||
|
ZSTD_initDStream_usingDict(zd, NULL, 0); /* ensure at least one init */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* srcBuffer selection [0-4] */
|
||||||
|
{ U32 buffNb = FUZ_rand(&lseed) & 0x7F;
|
||||||
|
if (buffNb & 7) buffNb=2; /* most common : compressible (P) */
|
||||||
|
else {
|
||||||
|
buffNb >>= 3;
|
||||||
|
if (buffNb & 7) {
|
||||||
|
const U32 tnb[2] = { 1, 3 }; /* barely/highly compressible */
|
||||||
|
buffNb = tnb[buffNb >> 3];
|
||||||
|
} else {
|
||||||
|
const U32 tnb[2] = { 0, 4 }; /* not compressible / sparse */
|
||||||
|
buffNb = tnb[buffNb >> 3];
|
||||||
|
} }
|
||||||
|
srcBuffer = cNoiseBuffer[buffNb];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compression init */
|
||||||
|
if ((FUZ_rand(&lseed)&1) /* at beginning, to keep same nb of rand */
|
||||||
|
&& oldTestLog /* at least one test happened */ && resetAllowed) {
|
||||||
|
maxTestSize = FUZ_randomLength(&lseed, oldTestLog+2);
|
||||||
|
if (maxTestSize >= srcBufferSize) maxTestSize = srcBufferSize-1;
|
||||||
|
{ int const compressionLevel = (FUZ_rand(&lseed) % 5) + 1;
|
||||||
|
size_t const resetError = ZSTDMT_initCStream(zc, compressionLevel);
|
||||||
|
CHECK(ZSTD_isError(resetError), "ZSTDMT_initCStream error : %s", ZSTD_getErrorName(resetError));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;
|
||||||
|
U32 const cLevel = (FUZ_rand(&lseed) % (ZSTD_maxCLevel() - (testLog/3))) + 1;
|
||||||
|
maxTestSize = FUZ_rLogLength(&lseed, testLog);
|
||||||
|
oldTestLog = testLog;
|
||||||
|
/* random dictionary selection */
|
||||||
|
dictSize = ((FUZ_rand(&lseed)&63)==1) ? FUZ_randomLength(&lseed, maxSampleLog) : 0;
|
||||||
|
{ size_t const dictStart = FUZ_rand(&lseed) % (srcBufferSize - dictSize);
|
||||||
|
dict = srcBuffer + dictStart;
|
||||||
|
}
|
||||||
|
{ U64 const pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? 0 : maxTestSize;
|
||||||
|
ZSTD_parameters params = ZSTD_getParams(cLevel, pledgedSrcSize, dictSize);
|
||||||
|
DISPLAYLEVEL(5, "Init with windowLog = %u \n", params.cParams.windowLog);
|
||||||
|
params.fParams.checksumFlag = FUZ_rand(&lseed) & 1;
|
||||||
|
params.fParams.noDictIDFlag = FUZ_rand(&lseed) & 1;
|
||||||
|
{ size_t const initError = ZSTDMT_initCStream_advanced(zc, dict, dictSize, params, pledgedSrcSize);
|
||||||
|
CHECK (ZSTD_isError(initError),"ZSTDMT_initCStream_advanced error : %s", ZSTD_getErrorName(initError)); }
|
||||||
|
ZSTDMT_setMTCtxParameter(zc, ZSTDMT_p_overlapSectionLog, FUZ_rand(&lseed) % 12);
|
||||||
|
ZSTDMT_setMTCtxParameter(zc, ZSTDMT_p_sectionSize, FUZ_rand(&lseed) % (2*maxTestSize+1));
|
||||||
|
} }
|
||||||
|
|
||||||
|
/* multi-segments compression test */
|
||||||
|
XXH64_reset(&xxhState, 0);
|
||||||
|
{ ZSTD_outBuffer outBuff = { cBuffer, cBufferSize, 0 } ;
|
||||||
|
U32 n;
|
||||||
|
for (n=0, cSize=0, totalTestSize=0 ; totalTestSize < maxTestSize ; n++) {
|
||||||
|
/* compress random chunks into randomly sized dst buffers */
|
||||||
|
{ size_t const randomSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
|
size_t const srcSize = MIN (maxTestSize-totalTestSize, randomSrcSize);
|
||||||
|
size_t const srcStart = FUZ_rand(&lseed) % (srcBufferSize - srcSize);
|
||||||
|
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
|
size_t const dstBuffSize = MIN(cBufferSize - cSize, randomDstSize);
|
||||||
|
ZSTD_inBuffer inBuff = { srcBuffer+srcStart, srcSize, 0 };
|
||||||
|
outBuff.size = outBuff.pos + dstBuffSize;
|
||||||
|
|
||||||
|
DISPLAYLEVEL(5, "Sending %u bytes to compress \n", (U32)srcSize);
|
||||||
|
{ size_t const compressionError = ZSTDMT_compressStream(zc, &outBuff, &inBuff);
|
||||||
|
CHECK (ZSTD_isError(compressionError), "compression error : %s", ZSTD_getErrorName(compressionError)); }
|
||||||
|
DISPLAYLEVEL(5, "%u bytes read by ZSTDMT_compressStream \n", (U32)inBuff.pos);
|
||||||
|
|
||||||
|
XXH64_update(&xxhState, srcBuffer+srcStart, inBuff.pos);
|
||||||
|
memcpy(copyBuffer+totalTestSize, srcBuffer+srcStart, inBuff.pos);
|
||||||
|
totalTestSize += inBuff.pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* random flush operation, to mess around */
|
||||||
|
if ((FUZ_rand(&lseed) & 15) == 0) {
|
||||||
|
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
|
size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize);
|
||||||
|
outBuff.size = outBuff.pos + adjustedDstSize;
|
||||||
|
DISPLAYLEVEL(5, "Flushing into dst buffer of size %u \n", (U32)adjustedDstSize);
|
||||||
|
{ size_t const flushError = ZSTDMT_flushStream(zc, &outBuff);
|
||||||
|
CHECK (ZSTD_isError(flushError), "flush error : %s", ZSTD_getErrorName(flushError));
|
||||||
|
} } }
|
||||||
|
|
||||||
|
/* final frame epilogue */
|
||||||
|
{ size_t remainingToFlush = (size_t)(-1);
|
||||||
|
while (remainingToFlush) {
|
||||||
|
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
|
size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize);
|
||||||
|
outBuff.size = outBuff.pos + adjustedDstSize;
|
||||||
|
DISPLAYLEVEL(5, "Ending into dst buffer of size %u \n", (U32)adjustedDstSize);
|
||||||
|
remainingToFlush = ZSTDMT_endStream(zc, &outBuff);
|
||||||
|
CHECK (ZSTD_isError(remainingToFlush), "flush error : %s", ZSTD_getErrorName(remainingToFlush));
|
||||||
|
DISPLAYLEVEL(5, "endStream : remainingToFlush : %u \n", (U32)remainingToFlush);
|
||||||
|
} }
|
||||||
|
DISPLAYLEVEL(5, "Frame completed \n");
|
||||||
|
crcOrig = XXH64_digest(&xxhState);
|
||||||
|
cSize = outBuff.pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* multi - fragments decompression test */
|
||||||
|
if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) {
|
||||||
|
CHECK (ZSTD_isError(ZSTD_resetDStream(zd)), "ZSTD_resetDStream failed");
|
||||||
|
} else {
|
||||||
|
ZSTD_initDStream_usingDict(zd, dict, dictSize);
|
||||||
|
}
|
||||||
|
{ size_t decompressionResult = 1;
|
||||||
|
ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
|
||||||
|
ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
|
||||||
|
for (totalGenSize = 0 ; decompressionResult ; ) {
|
||||||
|
size_t const readCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
|
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
|
size_t const dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize);
|
||||||
|
inBuff.size = inBuff.pos + readCSrcSize;
|
||||||
|
outBuff.size = inBuff.pos + dstBuffSize;
|
||||||
|
decompressionResult = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
||||||
|
CHECK (ZSTD_isError(decompressionResult), "decompression error : %s", ZSTD_getErrorName(decompressionResult));
|
||||||
|
}
|
||||||
|
CHECK (outBuff.pos != totalTestSize, "decompressed data : wrong size (%u != %u)", (U32)outBuff.pos, (U32)totalTestSize);
|
||||||
|
CHECK (inBuff.pos != cSize, "compressed data should be fully read (%u != %u)", (U32)inBuff.pos, (U32)cSize);
|
||||||
|
{ U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0);
|
||||||
|
if (crcDest!=crcOrig) findDiff(copyBuffer, dstBuffer, totalTestSize);
|
||||||
|
CHECK (crcDest!=crcOrig, "decompressed data corrupted");
|
||||||
|
} }
|
||||||
|
|
||||||
|
/*===== noisy/erroneous src decompression test =====*/
|
||||||
|
|
||||||
|
/* add some noise */
|
||||||
|
{ U32 const nbNoiseChunks = (FUZ_rand(&lseed) & 7) + 2;
|
||||||
|
U32 nn; for (nn=0; nn<nbNoiseChunks; nn++) {
|
||||||
|
size_t const randomNoiseSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
|
size_t const noiseSize = MIN((cSize/3) , randomNoiseSize);
|
||||||
|
size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseSize);
|
||||||
|
size_t const cStart = FUZ_rand(&lseed) % (cSize - noiseSize);
|
||||||
|
memcpy(cBuffer+cStart, srcBuffer+noiseStart, noiseSize);
|
||||||
|
} }
|
||||||
|
|
||||||
|
/* try decompression on noisy data */
|
||||||
|
ZSTD_initDStream(zd_noise); /* note : no dictionary */
|
||||||
|
{ ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
|
||||||
|
ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
|
||||||
|
while (outBuff.pos < dstBufferSize) {
|
||||||
|
size_t const randomCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
|
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||||
|
size_t const adjustedDstSize = MIN(dstBufferSize - outBuff.pos, randomDstSize);
|
||||||
|
size_t const adjustedCSrcSize = MIN(cSize - inBuff.pos, randomCSrcSize);
|
||||||
|
outBuff.size = outBuff.pos + adjustedDstSize;
|
||||||
|
inBuff.size = inBuff.pos + adjustedCSrcSize;
|
||||||
|
{ size_t const decompressError = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
||||||
|
if (ZSTD_isError(decompressError)) break; /* error correctly detected */
|
||||||
|
/* No forward progress possible */
|
||||||
|
if (outBuff.pos < outBuff.size && inBuff.pos == cSize) break;
|
||||||
|
} } } }
|
||||||
|
DISPLAY("\r%u fuzzer tests completed \n", testNb);
|
||||||
|
|
||||||
|
_cleanup:
|
||||||
|
ZSTDMT_freeCCtx(zc);
|
||||||
|
ZSTD_freeDStream(zd);
|
||||||
|
ZSTD_freeDStream(zd_noise);
|
||||||
|
free(cNoiseBuffer[0]);
|
||||||
|
free(cNoiseBuffer[1]);
|
||||||
|
free(cNoiseBuffer[2]);
|
||||||
|
free(cNoiseBuffer[3]);
|
||||||
|
free(cNoiseBuffer[4]);
|
||||||
|
free(copyBuffer);
|
||||||
|
free(cBuffer);
|
||||||
|
free(dstBuffer);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
_output_error:
|
||||||
|
result = 1;
|
||||||
|
goto _cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-*******************************************************
|
/*-*******************************************************
|
||||||
* Command line
|
* Command line
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
@@ -685,10 +997,11 @@ int main(int argc, const char** argv)
|
|||||||
int testNb = 0;
|
int testNb = 0;
|
||||||
int proba = FUZ_COMPRESSIBILITY_DEFAULT;
|
int proba = FUZ_COMPRESSIBILITY_DEFAULT;
|
||||||
int result=0;
|
int result=0;
|
||||||
U32 mainPause = 0;
|
int mainPause = 0;
|
||||||
const char* programName = argv[0];
|
int mtOnly = 0;
|
||||||
ZSTD_customMem customMem = { allocFunction, freeFunction, NULL };
|
const char* const programName = argv[0];
|
||||||
ZSTD_customMem customNULL = { NULL, NULL, NULL };
|
ZSTD_customMem const customMem = { allocFunction, freeFunction, NULL };
|
||||||
|
ZSTD_customMem const customNULL = { NULL, NULL, NULL };
|
||||||
|
|
||||||
/* Check command line */
|
/* Check command line */
|
||||||
for(argNb=1; argNb<argc; argNb++) {
|
for(argNb=1; argNb<argc; argNb++) {
|
||||||
@@ -697,27 +1010,32 @@ int main(int argc, const char** argv)
|
|||||||
|
|
||||||
/* Parsing commands. Aggregated commands are allowed */
|
/* Parsing commands. Aggregated commands are allowed */
|
||||||
if (argument[0]=='-') {
|
if (argument[0]=='-') {
|
||||||
argument++;
|
|
||||||
|
|
||||||
|
if (!strcmp(argument, "--mt")) { mtOnly=1; continue; }
|
||||||
|
|
||||||
|
argument++;
|
||||||
while (*argument!=0) {
|
while (*argument!=0) {
|
||||||
switch(*argument)
|
switch(*argument)
|
||||||
{
|
{
|
||||||
case 'h':
|
case 'h':
|
||||||
return FUZ_usage(programName);
|
return FUZ_usage(programName);
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
argument++;
|
argument++;
|
||||||
g_displayLevel=4;
|
g_displayLevel++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q':
|
case 'q':
|
||||||
argument++;
|
argument++;
|
||||||
g_displayLevel--;
|
g_displayLevel--;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p': /* pause at the end */
|
case 'p': /* pause at the end */
|
||||||
argument++;
|
argument++;
|
||||||
mainPause = 1;
|
mainPause = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i': /* limit tests by nb of iterations (default) */
|
||||||
argument++;
|
argument++;
|
||||||
nbTests=0; g_clockTime=0;
|
nbTests=0; g_clockTime=0;
|
||||||
while ((*argument>='0') && (*argument<='9')) {
|
while ((*argument>='0') && (*argument<='9')) {
|
||||||
@@ -727,7 +1045,7 @@ int main(int argc, const char** argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T':
|
case 'T': /* limit tests by time */
|
||||||
argument++;
|
argument++;
|
||||||
nbTests=0; g_clockTime=0;
|
nbTests=0; g_clockTime=0;
|
||||||
while ((*argument>='0') && (*argument<='9')) {
|
while ((*argument>='0') && (*argument<='9')) {
|
||||||
@@ -740,7 +1058,7 @@ int main(int argc, const char** argv)
|
|||||||
g_clockTime *= CLOCKS_PER_SEC;
|
g_clockTime *= CLOCKS_PER_SEC;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's': /* manually select seed */
|
||||||
argument++;
|
argument++;
|
||||||
seed=0;
|
seed=0;
|
||||||
seedset=1;
|
seedset=1;
|
||||||
@@ -751,7 +1069,7 @@ int main(int argc, const char** argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't': /* select starting test number */
|
||||||
argument++;
|
argument++;
|
||||||
testNb=0;
|
testNb=0;
|
||||||
while ((*argument>='0') && (*argument<='9')) {
|
while ((*argument>='0') && (*argument<='9')) {
|
||||||
@@ -795,12 +1113,12 @@ int main(int argc, const char** argv)
|
|||||||
if (testNb==0) {
|
if (testNb==0) {
|
||||||
result = basicUnitTests(0, ((double)proba) / 100, customNULL); /* constant seed for predictability */
|
result = basicUnitTests(0, ((double)proba) / 100, customNULL); /* constant seed for predictability */
|
||||||
if (!result) {
|
if (!result) {
|
||||||
DISPLAYLEVEL(4, "Unit tests using customMem :\n")
|
DISPLAYLEVEL(3, "Unit tests using customMem :\n")
|
||||||
result = basicUnitTests(0, ((double)proba) / 100, customMem); /* use custom memory allocation functions */
|
result = basicUnitTests(0, ((double)proba) / 100, customMem); /* use custom memory allocation functions */
|
||||||
} }
|
} }
|
||||||
|
|
||||||
if (!result)
|
if (!result && !mtOnly) result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
|
||||||
result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
|
if (!result) result = fuzzerTests_MT(seed, nbTests, testNb, ((double)proba) / 100);
|
||||||
|
|
||||||
if (mainPause) {
|
if (mainPause) {
|
||||||
int unused;
|
int unused;
|
||||||
|
|||||||
@@ -20,3 +20,6 @@ zwrapbench
|
|||||||
*.bat
|
*.bat
|
||||||
*.zip
|
*.zip
|
||||||
*.txt
|
*.txt
|
||||||
|
|
||||||
|
# Directories
|
||||||
|
minizip/
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
cxx_library(
|
||||||
|
name='zlib_wrapper',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_linker_flags=['-lz'],
|
||||||
|
header_namespace='',
|
||||||
|
exported_headers=['zstd_zlibwrapper.h'],
|
||||||
|
headers=[
|
||||||
|
'gzcompatibility.h',
|
||||||
|
'gzguts.h',
|
||||||
|
],
|
||||||
|
srcs=glob(['*.c']),
|
||||||
|
deps=[
|
||||||
|
'//lib:zstd',
|
||||||
|
'//lib:zstd_common',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_binary(
|
||||||
|
name='minigzip',
|
||||||
|
srcs=['examples/minigzip.c'],
|
||||||
|
deps=[':zlib_wrapper'],
|
||||||
|
)
|
||||||
@@ -82,7 +82,7 @@ local int partcompress(FILE *in, z_streamp def)
|
|||||||
|
|
||||||
flush = Z_SYNC_FLUSH;
|
flush = Z_SYNC_FLUSH;
|
||||||
do {
|
do {
|
||||||
def->avail_in = fread(raw, 1, RAWLEN, in);
|
def->avail_in = (uInt)fread(raw, 1, RAWLEN, in);
|
||||||
if (ferror(in))
|
if (ferror(in))
|
||||||
return Z_ERRNO;
|
return Z_ERRNO;
|
||||||
def->next_in = raw;
|
def->next_in = raw;
|
||||||
@@ -148,7 +148,7 @@ int main(int argc, char **argv)
|
|||||||
/* get requested output size */
|
/* get requested output size */
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
quit("need one argument: size of output block");
|
quit("need one argument: size of output block");
|
||||||
ret = strtol(argv[1], argv + 1, 10);
|
ret = (int)strtol(argv[1], argv + 1, 10);
|
||||||
if (argv[1][0] != 0)
|
if (argv[1][0] != 0)
|
||||||
quit("argument must be a number");
|
quit("argument must be a number");
|
||||||
if (ret < 8) /* 8 is minimum zlib stream size */
|
if (ret < 8) /* 8 is minimum zlib stream size */
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
|
|||||||
if (compressor == BMK_ZSTD) {
|
if (compressor == BMK_ZSTD) {
|
||||||
ZSTD_parameters const zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize);
|
ZSTD_parameters const zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize);
|
||||||
ZSTD_customMem const cmem = { NULL, NULL, NULL };
|
ZSTD_customMem const cmem = { NULL, NULL, NULL };
|
||||||
ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, zparams, cmem);
|
ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, 1, zparams, cmem);
|
||||||
if (cdict==NULL) EXM_THROW(1, "ZSTD_createCDict_advanced() allocation failure");
|
if (cdict==NULL) EXM_THROW(1, "ZSTD_createCDict_advanced() allocation failure");
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -315,10 +315,10 @@ static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
|
|||||||
if (ZWRAP_isUsingZSTDcompression()) useSetDict = 0; /* zstd doesn't require deflateSetDictionary after ZWRAP_deflateReset_keepDict */
|
if (ZWRAP_isUsingZSTDcompression()) useSetDict = 0; /* zstd doesn't require deflateSetDictionary after ZWRAP_deflateReset_keepDict */
|
||||||
}
|
}
|
||||||
def.next_in = (z_const void*) blockTable[blockNb].srcPtr;
|
def.next_in = (z_const void*) blockTable[blockNb].srcPtr;
|
||||||
def.avail_in = blockTable[blockNb].srcSize;
|
def.avail_in = (uInt)blockTable[blockNb].srcSize;
|
||||||
def.total_in = 0;
|
def.total_in = 0;
|
||||||
def.next_out = (void*) blockTable[blockNb].cPtr;
|
def.next_out = (void*) blockTable[blockNb].cPtr;
|
||||||
def.avail_out = blockTable[blockNb].cRoom;
|
def.avail_out = (uInt)blockTable[blockNb].cRoom;
|
||||||
def.total_out = 0;
|
def.total_out = 0;
|
||||||
ret = deflate(&def, Z_FINISH);
|
ret = deflate(&def, Z_FINISH);
|
||||||
if (ret != Z_STREAM_END) EXM_THROW(1, "deflate failure ret=%d srcSize=%d" , ret, (int)blockTable[blockNb].srcSize);
|
if (ret != Z_STREAM_END) EXM_THROW(1, "deflate failure ret=%d srcSize=%d" , ret, (int)blockTable[blockNb].srcSize);
|
||||||
@@ -346,10 +346,10 @@ static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
|
|||||||
if (ret != Z_OK) EXM_THROW(1, "deflateSetDictionary failure");
|
if (ret != Z_OK) EXM_THROW(1, "deflateSetDictionary failure");
|
||||||
}
|
}
|
||||||
def.next_in = (z_const void*) blockTable[blockNb].srcPtr;
|
def.next_in = (z_const void*) blockTable[blockNb].srcPtr;
|
||||||
def.avail_in = blockTable[blockNb].srcSize;
|
def.avail_in = (uInt)blockTable[blockNb].srcSize;
|
||||||
def.total_in = 0;
|
def.total_in = 0;
|
||||||
def.next_out = (void*) blockTable[blockNb].cPtr;
|
def.next_out = (void*) blockTable[blockNb].cPtr;
|
||||||
def.avail_out = blockTable[blockNb].cRoom;
|
def.avail_out = (uInt)blockTable[blockNb].cRoom;
|
||||||
def.total_out = 0;
|
def.total_out = 0;
|
||||||
ret = deflate(&def, Z_FINISH);
|
ret = deflate(&def, Z_FINISH);
|
||||||
if (ret != Z_STREAM_END) EXM_THROW(1, "deflate failure");
|
if (ret != Z_STREAM_END) EXM_THROW(1, "deflate failure");
|
||||||
@@ -451,10 +451,10 @@ static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
|
|||||||
ret = inflateReset(&inf);
|
ret = inflateReset(&inf);
|
||||||
if (ret != Z_OK) EXM_THROW(1, "inflateReset failure");
|
if (ret != Z_OK) EXM_THROW(1, "inflateReset failure");
|
||||||
inf.next_in = (z_const void*) blockTable[blockNb].cPtr;
|
inf.next_in = (z_const void*) blockTable[blockNb].cPtr;
|
||||||
inf.avail_in = blockTable[blockNb].cSize;
|
inf.avail_in = (uInt)blockTable[blockNb].cSize;
|
||||||
inf.total_in = 0;
|
inf.total_in = 0;
|
||||||
inf.next_out = (void*) blockTable[blockNb].resPtr;
|
inf.next_out = (void*) blockTable[blockNb].resPtr;
|
||||||
inf.avail_out = blockTable[blockNb].srcSize;
|
inf.avail_out = (uInt)blockTable[blockNb].srcSize;
|
||||||
inf.total_out = 0;
|
inf.total_out = 0;
|
||||||
ret = inflate(&inf, Z_FINISH);
|
ret = inflate(&inf, Z_FINISH);
|
||||||
if (ret == Z_NEED_DICT) {
|
if (ret == Z_NEED_DICT) {
|
||||||
@@ -483,10 +483,10 @@ static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
|
|||||||
ret = inflateInit(&inf);
|
ret = inflateInit(&inf);
|
||||||
if (ret != Z_OK) EXM_THROW(1, "inflateInit failure");
|
if (ret != Z_OK) EXM_THROW(1, "inflateInit failure");
|
||||||
inf.next_in = (z_const void*) blockTable[blockNb].cPtr;
|
inf.next_in = (z_const void*) blockTable[blockNb].cPtr;
|
||||||
inf.avail_in = blockTable[blockNb].cSize;
|
inf.avail_in = (uInt)blockTable[blockNb].cSize;
|
||||||
inf.total_in = 0;
|
inf.total_in = 0;
|
||||||
inf.next_out = (void*) blockTable[blockNb].resPtr;
|
inf.next_out = (void*) blockTable[blockNb].resPtr;
|
||||||
inf.avail_out = blockTable[blockNb].srcSize;
|
inf.avail_out = (uInt)blockTable[blockNb].srcSize;
|
||||||
inf.total_out = 0;
|
inf.total_out = 0;
|
||||||
ret = inflate(&inf, Z_FINISH);
|
ret = inflate(&inf, Z_FINISH);
|
||||||
if (ret == Z_NEED_DICT) {
|
if (ret == Z_NEED_DICT) {
|
||||||
|
|||||||
@@ -43,3 +43,25 @@ ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
|
|||||||
const char *mode));
|
const char *mode));
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if ZLIB_VERNUM < 0x12B0
|
||||||
|
#ifdef Z_SOLO
|
||||||
|
typedef unsigned long z_size_t;
|
||||||
|
#else
|
||||||
|
# define z_longlong long long
|
||||||
|
# if defined(NO_SIZE_T)
|
||||||
|
typedef unsigned NO_SIZE_T z_size_t;
|
||||||
|
# elif defined(STDC)
|
||||||
|
# include <stddef.h>
|
||||||
|
typedef size_t z_size_t;
|
||||||
|
# else
|
||||||
|
typedef unsigned long z_size_t;
|
||||||
|
# endif
|
||||||
|
# undef z_longlong
|
||||||
|
#endif
|
||||||
|
ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
|
||||||
|
gzFile file));
|
||||||
|
ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
|
||||||
|
z_size_t nitems, gzFile file));
|
||||||
|
#endif
|
||||||
|
|||||||
+16
-7
@@ -3,7 +3,7 @@
|
|||||||
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
||||||
|
|
||||||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
|
||||||
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
|
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -30,6 +30,10 @@
|
|||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <limits.h>
|
# include <limits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef _POSIX_SOURCE
|
||||||
|
# define _POSIX_SOURCE
|
||||||
|
#endif
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -40,6 +44,10 @@
|
|||||||
# include <io.h>
|
# include <io.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
|
# define WIDECHAR
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WINAPI_FAMILY
|
#ifdef WINAPI_FAMILY
|
||||||
# define open _open
|
# define open _open
|
||||||
# define read _read
|
# define read _read
|
||||||
@@ -100,18 +108,19 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* unlike snprintf (which is required in C99, yet still not supported by
|
/* unlike snprintf (which is required in C99), _snprintf does not guarantee
|
||||||
Microsoft more than a decade later!), _snprintf does not guarantee null
|
null termination of the result -- however this is only used in gzlib.c where
|
||||||
termination of the result -- however this is only used in gzlib.c where
|
|
||||||
the result is assured to fit in the space provided */
|
the result is assured to fit in the space provided */
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
# define snprintf _snprintf
|
# define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef local
|
#ifndef local
|
||||||
# define local static
|
# define local static
|
||||||
#endif
|
#endif
|
||||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
/* since "static" is used to mean two completely different things in C, we
|
||||||
|
define "local" for the non-static meaning of "static", for readability
|
||||||
|
(compile with -Dlocal if your debugger can't find static symbols) */
|
||||||
|
|
||||||
/* gz* functions always use library allocation functions */
|
/* gz* functions always use library allocation functions */
|
||||||
#ifndef STDC
|
#ifndef STDC
|
||||||
@@ -175,7 +184,7 @@ typedef struct {
|
|||||||
char *path; /* path or fd for error messages */
|
char *path; /* path or fd for error messages */
|
||||||
unsigned size; /* buffer size, zero if not allocated yet */
|
unsigned size; /* buffer size, zero if not allocated yet */
|
||||||
unsigned want; /* requested buffer size, default is GZBUFSIZE */
|
unsigned want; /* requested buffer size, default is GZBUFSIZE */
|
||||||
unsigned char *in; /* input buffer */
|
unsigned char *in; /* input buffer (double-sized when writing) */
|
||||||
unsigned char *out; /* output buffer (double-sized when reading) */
|
unsigned char *out; /* output buffer (double-sized when reading) */
|
||||||
int direct; /* 0 if processing gzip, 1 if transparent */
|
int direct; /* 0 if processing gzip, 1 if transparent */
|
||||||
/* just for reading */
|
/* just for reading */
|
||||||
|
|||||||
+21
-18
@@ -1,14 +1,14 @@
|
|||||||
/* gzlib.c contains minimal changes required to be compiled with zlibWrapper:
|
/* gzlib.c contains minimal changes required to be compiled with zlibWrapper:
|
||||||
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
||||||
|
|
||||||
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
||||||
* Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
|
* Copyright (C) 2004-2017 Mark Adler
|
||||||
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
|
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gzguts.h"
|
#include "gzguts.h"
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__BORLANDC__)
|
#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
|
||||||
# define LSEEK _lseeki64
|
# define LSEEK _lseeki64
|
||||||
#else
|
#else
|
||||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||||
@@ -97,7 +97,7 @@ local gzFile gz_open(path, fd, mode)
|
|||||||
const char *mode;
|
const char *mode;
|
||||||
{
|
{
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
size_t len;
|
z_size_t len;
|
||||||
int oflag;
|
int oflag;
|
||||||
#ifdef O_CLOEXEC
|
#ifdef O_CLOEXEC
|
||||||
int cloexec = 0;
|
int cloexec = 0;
|
||||||
@@ -191,10 +191,10 @@ local gzFile gz_open(path, fd, mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* save the path name for error messages */
|
/* save the path name for error messages */
|
||||||
#ifdef _WIN32
|
#ifdef WIDECHAR
|
||||||
if (fd == -2) {
|
if (fd == -2) {
|
||||||
len = wcstombs(NULL, path, 0);
|
len = wcstombs(NULL, path, 0);
|
||||||
if (len == (size_t)-1)
|
if (len == (z_size_t)-1)
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -205,7 +205,7 @@ local gzFile gz_open(path, fd, mode)
|
|||||||
free(state.state);
|
free(state.state);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef WIDECHAR
|
||||||
if (fd == -2)
|
if (fd == -2)
|
||||||
if (len)
|
if (len)
|
||||||
wcstombs(state.state->path, path, len + 1);
|
wcstombs(state.state->path, path, len + 1);
|
||||||
@@ -214,7 +214,7 @@ local gzFile gz_open(path, fd, mode)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||||
snprintf(state.state->path, len + 1, "%s", (const char *)path);
|
(void)snprintf(state.state->path, len + 1, "%s", (const char *)path);
|
||||||
#else
|
#else
|
||||||
strcpy(state.state->path, path);
|
strcpy(state.state->path, path);
|
||||||
#endif
|
#endif
|
||||||
@@ -242,7 +242,7 @@ local gzFile gz_open(path, fd, mode)
|
|||||||
|
|
||||||
/* open the file with the appropriate flags (or just use fd) */
|
/* open the file with the appropriate flags (or just use fd) */
|
||||||
state.state->fd = fd > -1 ? fd : (
|
state.state->fd = fd > -1 ? fd : (
|
||||||
#ifdef _WIN32
|
#ifdef WIDECHAR
|
||||||
fd == -2 ? _wopen(path, oflag, 0666) :
|
fd == -2 ? _wopen(path, oflag, 0666) :
|
||||||
#endif
|
#endif
|
||||||
open((const char *)path, oflag, 0666));
|
open((const char *)path, oflag, 0666));
|
||||||
@@ -251,8 +251,10 @@ local gzFile gz_open(path, fd, mode)
|
|||||||
free(state.state);
|
free(state.state);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (state.state->mode == GZ_APPEND)
|
if (state.state->mode == GZ_APPEND) {
|
||||||
|
LSEEK(state.state->fd, 0, SEEK_END); /* so gzoffset() is correct */
|
||||||
state.state->mode = GZ_WRITE; /* simplify later checks */
|
state.state->mode = GZ_WRITE; /* simplify later checks */
|
||||||
|
}
|
||||||
|
|
||||||
/* save the current position for rewinding (only if reading) */
|
/* save the current position for rewinding (only if reading) */
|
||||||
if (state.state->mode == GZ_READ) {
|
if (state.state->mode == GZ_READ) {
|
||||||
@@ -294,7 +296,7 @@ gzFile ZEXPORT gzdopen(fd, mode)
|
|||||||
if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
|
if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||||
snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
|
(void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
|
||||||
#else
|
#else
|
||||||
sprintf(path, "<fd:%d>", fd); /* for debugging */
|
sprintf(path, "<fd:%d>", fd); /* for debugging */
|
||||||
#endif
|
#endif
|
||||||
@@ -304,7 +306,7 @@ gzFile ZEXPORT gzdopen(fd, mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
/* -- see zlib.h -- */
|
||||||
#ifdef _WIN32
|
#ifdef WIDECHAR
|
||||||
gzFile ZEXPORT gzopen_w(path, mode)
|
gzFile ZEXPORT gzopen_w(path, mode)
|
||||||
const wchar_t *path;
|
const wchar_t *path;
|
||||||
const char *mode;
|
const char *mode;
|
||||||
@@ -332,6 +334,8 @@ int ZEXPORT gzbuffer(file, size)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* check and set requested size */
|
/* check and set requested size */
|
||||||
|
if ((size << 1) < size)
|
||||||
|
return -1; /* need to be able to double it */
|
||||||
if (size < 2)
|
if (size < 2)
|
||||||
size = 2; /* need two bytes to check magic header */
|
size = 2; /* need two bytes to check magic header */
|
||||||
state.state->want = size;
|
state.state->want = size;
|
||||||
@@ -569,8 +573,8 @@ void ZEXPORT gzclearerr(file)
|
|||||||
gz_error(state, Z_OK, NULL);
|
gz_error(state, Z_OK, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create an error message in allocated memory and set state->err and
|
/* Create an error message in allocated memory and set state.state->err and
|
||||||
state->msg accordingly. Free any previous error message already there. Do
|
state.state->msg accordingly. Free any previous error message already there. Do
|
||||||
not try to free or allocate space if the error is Z_MEM_ERROR (out of
|
not try to free or allocate space if the error is Z_MEM_ERROR (out of
|
||||||
memory). Simply save the error message as a static string. If there is an
|
memory). Simply save the error message as a static string. If there is an
|
||||||
allocation failure constructing the error message, then convert the error to
|
allocation failure constructing the error message, then convert the error to
|
||||||
@@ -587,7 +591,7 @@ void ZLIB_INTERNAL gz_error(state, err, msg)
|
|||||||
state.state->msg = NULL;
|
state.state->msg = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
|
/* if fatal, set state.state->x.have to 0 so that the gzgetc() macro fails */
|
||||||
if (err != Z_OK && err != Z_BUF_ERROR)
|
if (err != Z_OK && err != Z_BUF_ERROR)
|
||||||
state.state->x.have = 0;
|
state.state->x.have = 0;
|
||||||
|
|
||||||
@@ -607,14 +611,13 @@ void ZLIB_INTERNAL gz_error(state, err, msg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||||
snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
|
(void)snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
|
||||||
"%s%s%s", state.state->path, ": ", msg);
|
"%s%s%s", state.state->path, ": ", msg);
|
||||||
#else
|
#else
|
||||||
strcpy(state.state->msg, state.state->path);
|
strcpy(state.state->msg, state.state->path);
|
||||||
strcat(state.state->msg, ": ");
|
strcat(state.state->msg, ": ");
|
||||||
strcat(state.state->msg, msg);
|
strcat(state.state->msg, msg);
|
||||||
#endif
|
#endif
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef INT_MAX
|
#ifndef INT_MAX
|
||||||
|
|||||||
+123
-65
@@ -1,8 +1,8 @@
|
|||||||
/* gzread.c contains minimal changes required to be compiled with zlibWrapper:
|
/* gzread.c contains minimal changes required to be compiled with zlibWrapper:
|
||||||
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
||||||
|
|
||||||
/* gzread.c -- zlib functions for reading gzip files
|
/* gzread.c -- zlib functions for reading gzip files
|
||||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
|
||||||
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
|
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -15,9 +15,10 @@ local int gz_look OF((gz_statep));
|
|||||||
local int gz_decomp OF((gz_statep));
|
local int gz_decomp OF((gz_statep));
|
||||||
local int gz_fetch OF((gz_statep));
|
local int gz_fetch OF((gz_statep));
|
||||||
local int gz_skip OF((gz_statep, z_off64_t));
|
local int gz_skip OF((gz_statep, z_off64_t));
|
||||||
|
local z_size_t gz_read OF((gz_statep, voidp, z_size_t));
|
||||||
|
|
||||||
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
|
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
|
||||||
state->fd, and update state->eof, state->err, and state->msg as appropriate.
|
state.state->fd, and update state.state->eof, state.state->err, and state.state->msg as appropriate.
|
||||||
This function needs to loop on read(), since read() is not guaranteed to
|
This function needs to loop on read(), since read() is not guaranteed to
|
||||||
read the number of bytes requested, depending on the type of descriptor. */
|
read the number of bytes requested, depending on the type of descriptor. */
|
||||||
local int gz_load(state, buf, len, have)
|
local int gz_load(state, buf, len, have)
|
||||||
@@ -26,14 +27,18 @@ local int gz_load(state, buf, len, have)
|
|||||||
unsigned len;
|
unsigned len;
|
||||||
unsigned *have;
|
unsigned *have;
|
||||||
{
|
{
|
||||||
int ret;
|
ssize_t ret;
|
||||||
|
unsigned get, max = ((unsigned)-1 >> 2) + 1;
|
||||||
|
|
||||||
*have = 0;
|
*have = 0;
|
||||||
do {
|
do {
|
||||||
ret = read(state.state->fd, buf + *have, len - *have);
|
get = len - *have;
|
||||||
|
if (get > max)
|
||||||
|
get = max;
|
||||||
|
ret = read(state.state->fd, buf + *have, get);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
*have += ret;
|
*have += (unsigned)ret;
|
||||||
} while (*have < len);
|
} while (*have < len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
gz_error(state, Z_ERRNO, zstrerror());
|
gz_error(state, Z_ERRNO, zstrerror());
|
||||||
@@ -77,8 +82,8 @@ local int gz_avail(state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
|
/* Look for gzip header, set up for inflate or copy. state.state->x.have must be 0.
|
||||||
If this is the first time in, allocate required memory. state->how will be
|
If this is the first time in, allocate required memory. state.state->how will be
|
||||||
left unchanged if there is no more input data available, will be set to COPY
|
left unchanged if there is no more input data available, will be set to COPY
|
||||||
if there is no gzip header and direct copying will be performed, or it will
|
if there is no gzip header and direct copying will be performed, or it will
|
||||||
be set to GZIP for decompression. If direct copying, then leftover input
|
be set to GZIP for decompression. If direct copying, then leftover input
|
||||||
@@ -97,10 +102,8 @@ local int gz_look(state)
|
|||||||
state.state->in = (unsigned char *)malloc(state.state->want);
|
state.state->in = (unsigned char *)malloc(state.state->want);
|
||||||
state.state->out = (unsigned char *)malloc(state.state->want << 1);
|
state.state->out = (unsigned char *)malloc(state.state->want << 1);
|
||||||
if (state.state->in == NULL || state.state->out == NULL) {
|
if (state.state->in == NULL || state.state->out == NULL) {
|
||||||
if (state.state->out != NULL)
|
free(state.state->out);
|
||||||
free(state.state->out);
|
free(state.state->in);
|
||||||
if (state.state->in != NULL)
|
|
||||||
free(state.state->in);
|
|
||||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -136,7 +139,6 @@ local int gz_look(state)
|
|||||||
file -- for here we assume that if a gzip file is being written, then
|
file -- for here we assume that if a gzip file is being written, then
|
||||||
the header will be written in a single operation, so that reading a
|
the header will be written in a single operation, so that reading a
|
||||||
single byte is sufficient indication that it is not a gzip file) */
|
single byte is sufficient indication that it is not a gzip file) */
|
||||||
//printf("strm->next_in[0]=%d strm->next_in[1]=%d\n", strm->next_in[0], strm->next_in[1]);
|
|
||||||
if (strm->avail_in > 1 &&
|
if (strm->avail_in > 1 &&
|
||||||
((strm->next_in[0] == 31 && strm->next_in[1] == 139) /* gz header */
|
((strm->next_in[0] == 31 && strm->next_in[1] == 139) /* gz header */
|
||||||
|| (strm->next_in[0] == 40 && strm->next_in[1] == 181))) { /* zstd header */
|
|| (strm->next_in[0] == 40 && strm->next_in[1] == 181))) { /* zstd header */
|
||||||
@@ -170,9 +172,9 @@ local int gz_look(state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Decompress from input to the provided next_out and avail_out in the state.
|
/* Decompress from input to the provided next_out and avail_out in the state.
|
||||||
On return, state->x.have and state->x.next point to the just decompressed
|
On return, state.state->x.have and state.state->x.next point to the just decompressed
|
||||||
data. If the gzip stream completes, state->how is reset to LOOK to look for
|
data. If the gzip stream completes, state.state->how is reset to LOOK to look for
|
||||||
the next gzip stream or raw data, once state->x.have is depleted. Returns 0
|
the next gzip stream or raw data, once state.state->x.have is depleted. Returns 0
|
||||||
on success, -1 on failure. */
|
on success, -1 on failure. */
|
||||||
local int gz_decomp(state)
|
local int gz_decomp(state)
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
@@ -222,11 +224,11 @@ local int gz_decomp(state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
|
/* Fetch data and put it in the output buffer. Assumes state.state->x.have is 0.
|
||||||
Data is either copied from the input file or decompressed from the input
|
Data is either copied from the input file or decompressed from the input
|
||||||
file depending on state->how. If state->how is LOOK, then a gzip header is
|
file depending on state.state->how. If state.state->how is LOOK, then a gzip header is
|
||||||
looked for to determine whether to copy or decompress. Returns -1 on error,
|
looked for to determine whether to copy or decompress. Returns -1 on error,
|
||||||
otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
|
otherwise 0. gz_fetch() will leave state.state->how as COPY or GZIP unless the
|
||||||
end of the input file has been reached and all data has been processed. */
|
end of the input file has been reached and all data has been processed. */
|
||||||
local int gz_fetch(state)
|
local int gz_fetch(state)
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
@@ -289,33 +291,17 @@ local int gz_skip(state, len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
/* Read len bytes into buf from file, or less than len up to the end of the
|
||||||
int ZEXPORT gzread(file, buf, len)
|
input. Return the number of bytes read. If zero is returned, either the
|
||||||
gzFile file;
|
end of file was reached, or there was an error. state.state->err must be
|
||||||
voidp buf;
|
consulted in that case to determine which. */
|
||||||
unsigned len;
|
local z_size_t gz_read(state, buf, len)
|
||||||
{
|
|
||||||
unsigned got, n;
|
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
z_streamp strm;
|
voidp buf;
|
||||||
|
z_size_t len;
|
||||||
/* get internal structure */
|
{
|
||||||
if (file == NULL)
|
z_size_t got;
|
||||||
return -1;
|
unsigned n;
|
||||||
state = (gz_statep)file;
|
|
||||||
strm = &(state.state->strm);
|
|
||||||
|
|
||||||
/* check that we're reading and that there's no (serious) error */
|
|
||||||
if (state.state->mode != GZ_READ ||
|
|
||||||
(state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* since an int is returned, make sure len fits in one, otherwise return
|
|
||||||
with an error (this avoids the flaw in the interface) */
|
|
||||||
if ((int)len < 0) {
|
|
||||||
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if len is zero, avoid unnecessary operations */
|
/* if len is zero, avoid unnecessary operations */
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
@@ -325,32 +311,38 @@ int ZEXPORT gzread(file, buf, len)
|
|||||||
if (state.state->seek) {
|
if (state.state->seek) {
|
||||||
state.state->seek = 0;
|
state.state->seek = 0;
|
||||||
if (gz_skip(state, state.state->skip) == -1)
|
if (gz_skip(state, state.state->skip) == -1)
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get len bytes to buf, or less than len if at the end */
|
/* get len bytes to buf, or less than len if at the end */
|
||||||
got = 0;
|
got = 0;
|
||||||
do {
|
do {
|
||||||
|
/* set n to the maximum amount of len that fits in an unsigned int */
|
||||||
|
n = -1;
|
||||||
|
if (n > len)
|
||||||
|
n = (unsigned)len;
|
||||||
|
|
||||||
/* first just try copying data from the output buffer */
|
/* first just try copying data from the output buffer */
|
||||||
if (state.state->x.have) {
|
if (state.state->x.have) {
|
||||||
n = state.state->x.have > len ? len : state.state->x.have;
|
if (state.state->x.have < n)
|
||||||
|
n = state.state->x.have;
|
||||||
memcpy(buf, state.state->x.next, n);
|
memcpy(buf, state.state->x.next, n);
|
||||||
state.state->x.next += n;
|
state.state->x.next += n;
|
||||||
state.state->x.have -= n;
|
state.state->x.have -= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output buffer empty -- return if we're at the end of the input */
|
/* output buffer empty -- return if we're at the end of the input */
|
||||||
else if (state.state->eof && strm->avail_in == 0) {
|
else if (state.state->eof && state.state->strm.avail_in == 0) {
|
||||||
state.state->past = 1; /* tried to read past end */
|
state.state->past = 1; /* tried to read past end */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* need output data -- for small len or new stream load up our output
|
/* need output data -- for small len or new stream load up our output
|
||||||
buffer */
|
buffer */
|
||||||
else if (state.state->how == LOOK || len < (state.state->size << 1)) {
|
else if (state.state->how == LOOK || n < (state.state->size << 1)) {
|
||||||
/* get more output, looking for header if required */
|
/* get more output, looking for header if required */
|
||||||
if (gz_fetch(state) == -1)
|
if (gz_fetch(state) == -1)
|
||||||
return -1;
|
return 0;
|
||||||
continue; /* no progress yet -- go back to copy above */
|
continue; /* no progress yet -- go back to copy above */
|
||||||
/* the copy above assures that we will leave with space in the
|
/* the copy above assures that we will leave with space in the
|
||||||
output buffer, allowing at least one gzungetc() to succeed */
|
output buffer, allowing at least one gzungetc() to succeed */
|
||||||
@@ -358,16 +350,16 @@ int ZEXPORT gzread(file, buf, len)
|
|||||||
|
|
||||||
/* large len -- read directly into user buffer */
|
/* large len -- read directly into user buffer */
|
||||||
else if (state.state->how == COPY) { /* read directly */
|
else if (state.state->how == COPY) { /* read directly */
|
||||||
if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
|
if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* large len -- decompress directly into user buffer */
|
/* large len -- decompress directly into user buffer */
|
||||||
else { /* state->how == GZIP */
|
else { /* state.state->how == GZIP */
|
||||||
strm->avail_out = len;
|
state.state->strm.avail_out = n;
|
||||||
strm->next_out = (unsigned char *)buf;
|
state.state->strm.next_out = (unsigned char *)buf;
|
||||||
if (gz_decomp(state) == -1)
|
if (gz_decomp(state) == -1)
|
||||||
return -1;
|
return 0;
|
||||||
n = state.state->x.have;
|
n = state.state->x.have;
|
||||||
state.state->x.have = 0;
|
state.state->x.have = 0;
|
||||||
}
|
}
|
||||||
@@ -379,8 +371,75 @@ int ZEXPORT gzread(file, buf, len)
|
|||||||
state.state->x.pos += n;
|
state.state->x.pos += n;
|
||||||
} while (len);
|
} while (len);
|
||||||
|
|
||||||
/* return number of bytes read into user buffer (will fit in int) */
|
/* return number of bytes read into user buffer */
|
||||||
return (int)got;
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- see zlib.h -- */
|
||||||
|
int ZEXPORT gzread(file, buf, len)
|
||||||
|
gzFile file;
|
||||||
|
voidp buf;
|
||||||
|
unsigned len;
|
||||||
|
{
|
||||||
|
gz_statep state;
|
||||||
|
|
||||||
|
/* get internal structure */
|
||||||
|
if (file == NULL)
|
||||||
|
return -1;
|
||||||
|
state = (gz_statep)file;
|
||||||
|
|
||||||
|
/* check that we're reading and that there's no (serious) error */
|
||||||
|
if (state.state->mode != GZ_READ ||
|
||||||
|
(state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* since an int is returned, make sure len fits in one, otherwise return
|
||||||
|
with an error (this avoids a flaw in the interface) */
|
||||||
|
if ((int)len < 0) {
|
||||||
|
gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read len or fewer bytes to buf */
|
||||||
|
len = (unsigned)gz_read(state, buf, len);
|
||||||
|
|
||||||
|
/* check for an error */
|
||||||
|
if (len == 0 && state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* return the number of bytes read (this is assured to fit in an int) */
|
||||||
|
return (int)len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- see zlib.h -- */
|
||||||
|
z_size_t ZEXPORT gzfread(buf, size, nitems, file)
|
||||||
|
voidp buf;
|
||||||
|
z_size_t size;
|
||||||
|
z_size_t nitems;
|
||||||
|
gzFile file;
|
||||||
|
{
|
||||||
|
z_size_t len;
|
||||||
|
gz_statep state;
|
||||||
|
|
||||||
|
/* get internal structure */
|
||||||
|
if (file == NULL)
|
||||||
|
return 0;
|
||||||
|
state = (gz_statep)file;
|
||||||
|
|
||||||
|
/* check that we're reading and that there's no (serious) error */
|
||||||
|
if (state.state->mode != GZ_READ ||
|
||||||
|
(state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* compute bytes to read -- error on overflow */
|
||||||
|
len = nitems * size;
|
||||||
|
if (size && len / size != nitems) {
|
||||||
|
gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read len or fewer bytes to buf, return the number of full items read */
|
||||||
|
return len ? gz_read(state, buf, len) / size : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
/* -- see zlib.h -- */
|
||||||
@@ -401,7 +460,6 @@ ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
|
|||||||
ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));
|
ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int ZEXPORT gzgetc(file)
|
int ZEXPORT gzgetc(file)
|
||||||
gzFile file;
|
gzFile file;
|
||||||
{
|
{
|
||||||
@@ -426,8 +484,8 @@ int ZEXPORT gzgetc(file)
|
|||||||
return *(state.state->x.next)++;
|
return *(state.state->x.next)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nothing there -- try gzread() */
|
/* nothing there -- try gz_read() */
|
||||||
ret = gzread(file, buf, 1);
|
ret = (unsigned)gz_read(state, buf, 1);
|
||||||
return ret < 1 ? -1 : buf[0];
|
return ret < 1 ? -1 : buf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,7 +527,7 @@ int ZEXPORT gzungetc(c, file)
|
|||||||
if (state.state->x.have == 0) {
|
if (state.state->x.have == 0) {
|
||||||
state.state->x.have = 1;
|
state.state->x.have = 1;
|
||||||
state.state->x.next = state.state->out + (state.state->size << 1) - 1;
|
state.state->x.next = state.state->out + (state.state->size << 1) - 1;
|
||||||
state.state->x.next[0] = c;
|
state.state->x.next[0] = (unsigned char)c;
|
||||||
state.state->x.pos--;
|
state.state->x.pos--;
|
||||||
state.state->past = 0;
|
state.state->past = 0;
|
||||||
return c;
|
return c;
|
||||||
@@ -491,7 +549,7 @@ int ZEXPORT gzungetc(c, file)
|
|||||||
}
|
}
|
||||||
state.state->x.have++;
|
state.state->x.have++;
|
||||||
state.state->x.next--;
|
state.state->x.next--;
|
||||||
state.state->x.next[0] = c;
|
state.state->x.next[0] = (unsigned char)c;
|
||||||
state.state->x.pos--;
|
state.state->x.pos--;
|
||||||
state.state->past = 0;
|
state.state->past = 0;
|
||||||
return c;
|
return c;
|
||||||
|
|||||||
+216
-128
@@ -1,8 +1,8 @@
|
|||||||
/* gzwrite.c contains minimal changes required to be compiled with zlibWrapper:
|
/* gzwrite.c contains minimal changes required to be compiled with zlibWrapper:
|
||||||
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
||||||
|
|
||||||
/* gzwrite.c -- zlib functions for writing gzip files
|
/* gzwrite.c -- zlib functions for writing gzip files
|
||||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
* Copyright (C) 2004-2017 Mark Adler
|
||||||
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
|
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -12,17 +12,19 @@
|
|||||||
local int gz_init OF((gz_statep));
|
local int gz_init OF((gz_statep));
|
||||||
local int gz_comp OF((gz_statep, int));
|
local int gz_comp OF((gz_statep, int));
|
||||||
local int gz_zero OF((gz_statep, z_off64_t));
|
local int gz_zero OF((gz_statep, z_off64_t));
|
||||||
|
local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
|
||||||
|
|
||||||
/* Initialize state for writing a gzip file. Mark initialization by setting
|
/* Initialize state for writing a gzip file. Mark initialization by setting
|
||||||
state->size to non-zero. Return -1 on failure or 0 on success. */
|
state.state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
|
||||||
|
success. */
|
||||||
local int gz_init(state)
|
local int gz_init(state)
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
z_streamp strm = &(state.state->strm);
|
z_streamp strm = &(state.state->strm);
|
||||||
|
|
||||||
/* allocate input buffer */
|
/* allocate input buffer (double size for gzprintf) */
|
||||||
state.state->in = (unsigned char *)malloc(state.state->want);
|
state.state->in = (unsigned char *)malloc(state.state->want << 1);
|
||||||
if (state.state->in == NULL) {
|
if (state.state->in == NULL) {
|
||||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -50,6 +52,7 @@ local int gz_init(state)
|
|||||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
strm->next_in = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mark state as initialized */
|
/* mark state as initialized */
|
||||||
@@ -65,17 +68,17 @@ local int gz_init(state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Compress whatever is at avail_in and next_in and write to the output file.
|
/* Compress whatever is at avail_in and next_in and write to the output file.
|
||||||
Return -1 if there is an error writing to the output file, otherwise 0.
|
Return -1 if there is an error writing to the output file or if gz_init()
|
||||||
flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
|
fails to allocate memory, otherwise 0. flush is assumed to be a valid
|
||||||
then the deflate() state is reset to start a new gzip stream. If gz->direct
|
deflate() flush value. If flush is Z_FINISH, then the deflate() state is
|
||||||
is true, then simply write to the output file without compressing, and
|
reset to start a new gzip stream. If gz->direct is true, then simply write
|
||||||
ignore flush. */
|
to the output file without compressing, and ignore flush. */
|
||||||
local int gz_comp(state, flush)
|
local int gz_comp(state, flush)
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
int flush;
|
int flush;
|
||||||
{
|
{
|
||||||
int ret, got;
|
int ret, writ;
|
||||||
unsigned have;
|
unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
|
||||||
z_streamp strm = &(state.state->strm);
|
z_streamp strm = &(state.state->strm);
|
||||||
|
|
||||||
/* allocate memory if this is the first time through */
|
/* allocate memory if this is the first time through */
|
||||||
@@ -84,12 +87,16 @@ local int gz_comp(state, flush)
|
|||||||
|
|
||||||
/* write directly if requested */
|
/* write directly if requested */
|
||||||
if (state.state->direct) {
|
if (state.state->direct) {
|
||||||
got = write(state.state->fd, strm->next_in, strm->avail_in);
|
while (strm->avail_in) {
|
||||||
if (got < 0 || (unsigned)got != strm->avail_in) {
|
put = strm->avail_in > max ? max : strm->avail_in;
|
||||||
gz_error(state, Z_ERRNO, zstrerror());
|
writ = (int)write(state.state->fd, strm->next_in, put);
|
||||||
return -1;
|
if (writ < 0) {
|
||||||
|
gz_error(state, Z_ERRNO, zstrerror());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strm->avail_in -= (unsigned)writ;
|
||||||
|
strm->next_in += writ;
|
||||||
}
|
}
|
||||||
strm->avail_in = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,17 +107,21 @@ local int gz_comp(state, flush)
|
|||||||
doing Z_FINISH then don't write until we get to Z_STREAM_END */
|
doing Z_FINISH then don't write until we get to Z_STREAM_END */
|
||||||
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
|
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
|
||||||
(flush != Z_FINISH || ret == Z_STREAM_END))) {
|
(flush != Z_FINISH || ret == Z_STREAM_END))) {
|
||||||
have = (unsigned)(strm->next_out - state.state->x.next);
|
while (strm->next_out > state.state->x.next) {
|
||||||
if (have && ((got = write(state.state->fd, state.state->x.next, have)) < 0 ||
|
put = strm->next_out - state.state->x.next > (int)max ? max :
|
||||||
(unsigned)got != have)) {
|
(unsigned)(strm->next_out - state.state->x.next);
|
||||||
gz_error(state, Z_ERRNO, zstrerror());
|
writ = (int)write(state.state->fd, state.state->x.next, put);
|
||||||
return -1;
|
if (writ < 0) {
|
||||||
|
gz_error(state, Z_ERRNO, zstrerror());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
state.state->x.next += writ;
|
||||||
}
|
}
|
||||||
if (strm->avail_out == 0) {
|
if (strm->avail_out == 0) {
|
||||||
strm->avail_out = state.state->size;
|
strm->avail_out = state.state->size;
|
||||||
strm->next_out = state.state->out;
|
strm->next_out = state.state->out;
|
||||||
|
state.state->x.next = state.state->out;
|
||||||
}
|
}
|
||||||
state.state->x.next = strm->next_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compress */
|
/* compress */
|
||||||
@@ -132,7 +143,8 @@ local int gz_comp(state, flush)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compress len zeros to output. Return -1 on error, 0 on success. */
|
/* Compress len zeros to output. Return -1 on a write error or memory
|
||||||
|
allocation failure by gz_comp(), or 0 on success. */
|
||||||
local int gz_zero(state, len)
|
local int gz_zero(state, len)
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
z_off64_t len;
|
z_off64_t len;
|
||||||
@@ -164,32 +176,14 @@ local int gz_zero(state, len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
/* Write len bytes from buf to file. Return the number of bytes written. If
|
||||||
int ZEXPORT gzwrite(file, buf, len)
|
the returned value is less than len, then there was an error. */
|
||||||
gzFile file;
|
local z_size_t gz_write(state, buf, len)
|
||||||
voidpc buf;
|
|
||||||
unsigned len;
|
|
||||||
{
|
|
||||||
unsigned put = len;
|
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
z_streamp strm;
|
voidpc buf;
|
||||||
|
z_size_t len;
|
||||||
/* get internal structure */
|
{
|
||||||
if (file == NULL)
|
z_size_t put = len;
|
||||||
return 0;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
strm = &(state.state->strm);
|
|
||||||
|
|
||||||
/* check that we're writing and that there's no error */
|
|
||||||
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* since an int is returned, make sure len fits in one, otherwise return
|
|
||||||
with an error (this avoids the flaw in the interface) */
|
|
||||||
if ((int)len < 0) {
|
|
||||||
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if len is zero, avoid unnecessary operations */
|
/* if len is zero, avoid unnecessary operations */
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
@@ -210,16 +204,17 @@ int ZEXPORT gzwrite(file, buf, len)
|
|||||||
if (len < state.state->size) {
|
if (len < state.state->size) {
|
||||||
/* copy to input buffer, compress when full */
|
/* copy to input buffer, compress when full */
|
||||||
do {
|
do {
|
||||||
unsigned have, copy;
|
z_size_t have, copy;
|
||||||
|
|
||||||
if (strm->avail_in == 0)
|
if (state.state->strm.avail_in == 0)
|
||||||
strm->next_in = state.state->in;
|
state.state->strm.next_in = state.state->in;
|
||||||
have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in);
|
have = (unsigned)((state.state->strm.next_in + state.state->strm.avail_in) -
|
||||||
|
state.state->in);
|
||||||
copy = state.state->size - have;
|
copy = state.state->size - have;
|
||||||
if (copy > len)
|
if (copy > len)
|
||||||
copy = len;
|
copy = len;
|
||||||
memcpy(state.state->in + have, buf, copy);
|
memcpy(state.state->in + have, buf, copy);
|
||||||
strm->avail_in += copy;
|
state.state->strm.avail_in += copy;
|
||||||
state.state->x.pos += copy;
|
state.state->x.pos += copy;
|
||||||
buf = (const char *)buf + copy;
|
buf = (const char *)buf + copy;
|
||||||
len -= copy;
|
len -= copy;
|
||||||
@@ -229,19 +224,83 @@ int ZEXPORT gzwrite(file, buf, len)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* consume whatever's left in the input buffer */
|
/* consume whatever's left in the input buffer */
|
||||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
if (state.state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* directly compress user buffer to file */
|
/* directly compress user buffer to file */
|
||||||
strm->avail_in = len;
|
state.state->strm.next_in = (z_const Bytef *)buf;
|
||||||
strm->next_in = (z_const Bytef *)buf;
|
do {
|
||||||
state.state->x.pos += len;
|
z_size_t n = (unsigned)-1;
|
||||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
if (n > len)
|
||||||
return 0;
|
n = len;
|
||||||
|
state.state->strm.avail_in = (z_uInt)n;
|
||||||
|
state.state->x.pos += n;
|
||||||
|
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||||
|
return 0;
|
||||||
|
len -= n;
|
||||||
|
} while (len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* input was all buffered or compressed (put will fit in int) */
|
/* input was all buffered or compressed */
|
||||||
return (int)put;
|
return put;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- see zlib.h -- */
|
||||||
|
int ZEXPORT gzwrite(file, buf, len)
|
||||||
|
gzFile file;
|
||||||
|
voidpc buf;
|
||||||
|
unsigned len;
|
||||||
|
{
|
||||||
|
gz_statep state;
|
||||||
|
|
||||||
|
/* get internal structure */
|
||||||
|
if (file == NULL)
|
||||||
|
return 0;
|
||||||
|
state = (gz_statep)file;
|
||||||
|
|
||||||
|
/* check that we're writing and that there's no error */
|
||||||
|
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* since an int is returned, make sure len fits in one, otherwise return
|
||||||
|
with an error (this avoids a flaw in the interface) */
|
||||||
|
if ((int)len < 0) {
|
||||||
|
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write len bytes from buf (the return value will fit in an int) */
|
||||||
|
return (int)gz_write(state, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- see zlib.h -- */
|
||||||
|
z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
|
||||||
|
voidpc buf;
|
||||||
|
z_size_t size;
|
||||||
|
z_size_t nitems;
|
||||||
|
gzFile file;
|
||||||
|
{
|
||||||
|
z_size_t len;
|
||||||
|
gz_statep state;
|
||||||
|
|
||||||
|
/* get internal structure */
|
||||||
|
if (file == NULL)
|
||||||
|
return 0;
|
||||||
|
state = (gz_statep)file;
|
||||||
|
|
||||||
|
/* check that we're writing and that there's no error */
|
||||||
|
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* compute bytes to read -- error on overflow */
|
||||||
|
len = nitems * size;
|
||||||
|
if (size && len / size != nitems) {
|
||||||
|
gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write len bytes to buf, return the number of full items written */
|
||||||
|
return len ? gz_write(state, buf, len) / size : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
/* -- see zlib.h -- */
|
||||||
@@ -271,14 +330,14 @@ int ZEXPORT gzputc(file, c)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try writing to input buffer for speed (state->size == 0 if buffer not
|
/* try writing to input buffer for speed (state.state->size == 0 if buffer not
|
||||||
initialized) */
|
initialized) */
|
||||||
if (state.state->size) {
|
if (state.state->size) {
|
||||||
if (strm->avail_in == 0)
|
if (strm->avail_in == 0)
|
||||||
strm->next_in = state.state->in;
|
strm->next_in = state.state->in;
|
||||||
have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in);
|
have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in);
|
||||||
if (have < state.state->size) {
|
if (have < state.state->size) {
|
||||||
state.state->in[have] = c;
|
state.state->in[have] = (unsigned char)c;
|
||||||
strm->avail_in++;
|
strm->avail_in++;
|
||||||
state.state->x.pos++;
|
state.state->x.pos++;
|
||||||
return c & 0xff;
|
return c & 0xff;
|
||||||
@@ -286,8 +345,8 @@ int ZEXPORT gzputc(file, c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* no room in buffer or not initialized, use gz_write() */
|
/* no room in buffer or not initialized, use gz_write() */
|
||||||
buf[0] = c;
|
buf[0] = (unsigned char)c;
|
||||||
if (gzwrite(file, buf, 1) != 1)
|
if (gz_write(state, buf, 1) != 1)
|
||||||
return -1;
|
return -1;
|
||||||
return c & 0xff;
|
return c & 0xff;
|
||||||
}
|
}
|
||||||
@@ -298,11 +357,21 @@ int ZEXPORT gzputs(file, str)
|
|||||||
const char *str;
|
const char *str;
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned len;
|
z_size_t len;
|
||||||
|
gz_statep state;
|
||||||
|
|
||||||
|
/* get internal structure */
|
||||||
|
if (file == NULL)
|
||||||
|
return -1;
|
||||||
|
state = (gz_statep)file;
|
||||||
|
|
||||||
|
/* check that we're writing and that there's no error */
|
||||||
|
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* write string */
|
/* write string */
|
||||||
len = (unsigned)strlen(str);
|
len = strlen(str);
|
||||||
ret = gzwrite(file, str, len);
|
ret = (int)gz_write(state, str, len);
|
||||||
return ret == 0 && len != 0 ? -1 : ret;
|
return ret == 0 && len != 0 ? -1 : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,63 +381,73 @@ int ZEXPORT gzputs(file, str)
|
|||||||
/* -- see zlib.h -- */
|
/* -- see zlib.h -- */
|
||||||
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
|
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
|
||||||
{
|
{
|
||||||
int size, len;
|
int len;
|
||||||
|
unsigned left;
|
||||||
|
char *next;
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
z_streamp strm;
|
z_streamp strm;
|
||||||
|
|
||||||
/* get internal structure */
|
/* get internal structure */
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return -1;
|
return Z_STREAM_ERROR;
|
||||||
state = (gz_statep)file;
|
state = (gz_statep)file;
|
||||||
strm = &(state.state->strm);
|
strm = &(state.state->strm);
|
||||||
|
|
||||||
/* check that we're writing and that there's no error */
|
/* check that we're writing and that there's no error */
|
||||||
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
|
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
|
||||||
return 0;
|
return Z_STREAM_ERROR;
|
||||||
|
|
||||||
/* make sure we have some buffer space */
|
/* make sure we have some buffer space */
|
||||||
if (state.state->size == 0 && gz_init(state) == -1)
|
if (state.state->size == 0 && gz_init(state) == -1)
|
||||||
return 0;
|
return state.state->err;
|
||||||
|
|
||||||
/* check for seek request */
|
/* check for seek request */
|
||||||
if (state.state->seek) {
|
if (state.state->seek) {
|
||||||
state.state->seek = 0;
|
state.state->seek = 0;
|
||||||
if (gz_zero(state, state.state->skip) == -1)
|
if (gz_zero(state, state.state->skip) == -1)
|
||||||
return 0;
|
return state.state->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* consume whatever's left in the input buffer */
|
/* do the printf() into the input buffer, put length in len -- the input
|
||||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
buffer is double-sized just for this function, so there is guaranteed to
|
||||||
return 0;
|
be state.state->size bytes available after the current contents */
|
||||||
|
if (strm->avail_in == 0)
|
||||||
/* do the printf() into the input buffer, put length in len */
|
strm->next_in = state.state->in;
|
||||||
size = (int)(state.state->size);
|
next = (char *)(state.state->in + (strm->next_in - state.state->in) + strm->avail_in);
|
||||||
state.state->in[size - 1] = 0;
|
next[state.state->size - 1] = 0;
|
||||||
#ifdef NO_vsnprintf
|
#ifdef NO_vsnprintf
|
||||||
# ifdef HAS_vsprintf_void
|
# ifdef HAS_vsprintf_void
|
||||||
(void)vsprintf((char *)(state.state->in), format, va);
|
(void)vsprintf(next, format, va);
|
||||||
for (len = 0; len < size; len++)
|
for (len = 0; len < state.state->size; len++)
|
||||||
if (state.state->in[len] == 0) break;
|
if (next[len] == 0) break;
|
||||||
# else
|
# else
|
||||||
len = vsprintf((char *)(state.state->in), format, va);
|
len = vsprintf(next, format, va);
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# ifdef HAS_vsnprintf_void
|
# ifdef HAS_vsnprintf_void
|
||||||
(void)vsnprintf((char *)(state.state->in), size, format, va);
|
(void)vsnprintf(next, state.state->size, format, va);
|
||||||
len = strlen((char *)(state.state->in));
|
len = strlen(next);
|
||||||
# else
|
# else
|
||||||
len = vsnprintf((char *)(state.state->in), size, format, va);
|
len = vsnprintf(next, state.state->size, format, va);
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* check that printf() results fit in buffer */
|
/* check that printf() results fit in buffer */
|
||||||
if (len <= 0 || len >= (int)size || state.state->in[size - 1] != 0)
|
if (len == 0 || (unsigned)len >= state.state->size || next[state.state->size - 1] != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* update buffer and position, defer compression until needed */
|
/* update buffer and position, compress first half if past that */
|
||||||
strm->avail_in = (unsigned)len;
|
strm->avail_in += (unsigned)len;
|
||||||
strm->next_in = state.state->in;
|
|
||||||
state.state->x.pos += len;
|
state.state->x.pos += len;
|
||||||
|
if (strm->avail_in >= state.state->size) {
|
||||||
|
left = strm->avail_in - state.state->size;
|
||||||
|
strm->avail_in = state.state->size;
|
||||||
|
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||||
|
return state.state->err;
|
||||||
|
memcpy(state.state->in, state.state->in + state.state->size, left);
|
||||||
|
strm->next_in = state.state->in;
|
||||||
|
strm->avail_in = left;
|
||||||
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,73 +472,82 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
|||||||
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
||||||
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
|
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
|
||||||
{
|
{
|
||||||
int size, len;
|
unsigned len, left;
|
||||||
|
char *next;
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
z_streamp strm;
|
z_streamp strm;
|
||||||
|
|
||||||
/* get internal structure */
|
/* get internal structure */
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return -1;
|
return Z_STREAM_ERROR;
|
||||||
state = (gz_statep)file;
|
state = (gz_statep)file;
|
||||||
strm = &(state.state->strm);
|
strm = &(state.state->strm);
|
||||||
|
|
||||||
/* check that can really pass pointer in ints */
|
/* check that can really pass pointer in ints */
|
||||||
if (sizeof(int) != sizeof(void *))
|
if (sizeof(int) != sizeof(void *))
|
||||||
return 0;
|
return Z_STREAM_ERROR;
|
||||||
|
|
||||||
/* check that we're writing and that there's no error */
|
/* check that we're writing and that there's no error */
|
||||||
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
|
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
|
||||||
return 0;
|
return Z_STREAM_ERROR;
|
||||||
|
|
||||||
/* make sure we have some buffer space */
|
/* make sure we have some buffer space */
|
||||||
if (state.state->size == 0 && gz_init(state) == -1)
|
if (state.state->size == 0 && gz_init(state) == -1)
|
||||||
return 0;
|
return state.state->error;
|
||||||
|
|
||||||
/* check for seek request */
|
/* check for seek request */
|
||||||
if (state.state->seek) {
|
if (state.state->seek) {
|
||||||
state.state->seek = 0;
|
state.state->seek = 0;
|
||||||
if (gz_zero(state, state.state->skip) == -1)
|
if (gz_zero(state, state.state->skip) == -1)
|
||||||
return 0;
|
return state.state->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* consume whatever's left in the input buffer */
|
/* do the printf() into the input buffer, put length in len -- the input
|
||||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
buffer is double-sized just for this function, so there is guaranteed to
|
||||||
return 0;
|
be state.state->size bytes available after the current contents */
|
||||||
|
if (strm->avail_in == 0)
|
||||||
/* do the printf() into the input buffer, put length in len */
|
strm->next_in = state.state->in;
|
||||||
size = (int)(state.state->size);
|
next = (char *)(strm->next_in + strm->avail_in);
|
||||||
state.state->in[size - 1] = 0;
|
next[state.state->size - 1] = 0;
|
||||||
#ifdef NO_snprintf
|
#ifdef NO_snprintf
|
||||||
# ifdef HAS_sprintf_void
|
# ifdef HAS_sprintf_void
|
||||||
sprintf((char *)(state.state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
|
sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
|
||||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
a13, a14, a15, a16, a17, a18, a19, a20);
|
||||||
for (len = 0; len < size; len++)
|
for (len = 0; len < size; len++)
|
||||||
if (state.state->in[len] == 0) break;
|
if (next[len] == 0)
|
||||||
|
break;
|
||||||
# else
|
# else
|
||||||
len = sprintf((char *)(state.state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
|
len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
|
||||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# ifdef HAS_snprintf_void
|
# ifdef HAS_snprintf_void
|
||||||
snprintf((char *)(state.state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
|
snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
|
||||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||||
len = strlen((char *)(state.state->in));
|
len = strlen(next);
|
||||||
# else
|
# else
|
||||||
len = snprintf((char *)(state.state->in), size, format, a1, a2, a3, a4, a5, a6,
|
len = snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||||
a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
|
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||||
a19, a20);
|
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* check that printf() results fit in buffer */
|
/* check that printf() results fit in buffer */
|
||||||
if (len <= 0 || len >= (int)size || state.state->in[size - 1] != 0)
|
if (len == 0 || len >= state.state->size || next[state.state->size - 1] != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* update buffer and position, defer compression until needed */
|
/* update buffer and position, compress first half if past that */
|
||||||
strm->avail_in = (unsigned)len;
|
strm->avail_in += len;
|
||||||
strm->next_in = state.state->in;
|
|
||||||
state.state->x.pos += len;
|
state.state->x.pos += len;
|
||||||
return len;
|
if (strm->avail_in >= state.state->size) {
|
||||||
|
left = strm->avail_in - state.state->size;
|
||||||
|
strm->avail_in = state.state->size;
|
||||||
|
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||||
|
return state.state->err;
|
||||||
|
memcpy(state.state->in, state.state->in + state.state->size, left);
|
||||||
|
strm->next_in = state.state->in;
|
||||||
|
strm->avail_in = left;
|
||||||
|
}
|
||||||
|
return (int)len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -473,7 +561,7 @@ int ZEXPORT gzflush(file, flush)
|
|||||||
|
|
||||||
/* get internal structure */
|
/* get internal structure */
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return -1;
|
return Z_STREAM_ERROR;
|
||||||
state = (gz_statep)file;
|
state = (gz_statep)file;
|
||||||
|
|
||||||
/* check that we're writing and that there's no error */
|
/* check that we're writing and that there's no error */
|
||||||
@@ -488,11 +576,11 @@ int ZEXPORT gzflush(file, flush)
|
|||||||
if (state.state->seek) {
|
if (state.state->seek) {
|
||||||
state.state->seek = 0;
|
state.state->seek = 0;
|
||||||
if (gz_zero(state, state.state->skip) == -1)
|
if (gz_zero(state, state.state->skip) == -1)
|
||||||
return -1;
|
return state.state->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compress remaining data with requested flush */
|
/* compress remaining data with requested flush */
|
||||||
gz_comp(state, flush);
|
(void)gz_comp(state, flush);
|
||||||
return state.state->err;
|
return state.state->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,13 +611,13 @@ int ZEXPORT gzsetparams(file, level, strategy)
|
|||||||
if (state.state->seek) {
|
if (state.state->seek) {
|
||||||
state.state->seek = 0;
|
state.state->seek = 0;
|
||||||
if (gz_zero(state, state.state->skip) == -1)
|
if (gz_zero(state, state.state->skip) == -1)
|
||||||
return -1;
|
return state.state->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* change compression parameters for subsequent input */
|
/* change compression parameters for subsequent input */
|
||||||
if (state.state->size) {
|
if (state.state->size) {
|
||||||
/* flush previous input with previous parameters before changing */
|
/* flush previous input with previous parameters before changing */
|
||||||
if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
|
if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
|
||||||
return state.state->err;
|
return state.state->err;
|
||||||
deflateParams(strm, level, strategy);
|
deflateParams(strm, level, strategy);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ ZEXTERN const char * ZEXPORT z_zlibVersion OF((void)) { return zlibVersion(); }
|
|||||||
static void* ZWRAP_allocFunction(void* opaque, size_t size)
|
static void* ZWRAP_allocFunction(void* opaque, size_t size)
|
||||||
{
|
{
|
||||||
z_streamp strm = (z_streamp) opaque;
|
z_streamp strm = (z_streamp) opaque;
|
||||||
void* address = strm->zalloc(strm->opaque, 1, size);
|
void* address = strm->zalloc(strm->opaque, 1, (uInt)size);
|
||||||
/* printf("ZWRAP alloc %p, %d \n", address, (int)size); */
|
/* printf("ZWRAP alloc %p, %d \n", address, (int)size); */
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,8 @@ typedef enum { ZWRAP_useInit, ZWRAP_useReset, ZWRAP_streamEnd } ZWRAP_state_t;
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
ZSTD_CStream* zbc;
|
ZSTD_CStream* zbc;
|
||||||
int compressionLevel;
|
int compressionLevel;
|
||||||
int streamEnd;
|
int streamEnd; /* a flag to signal the end of a stream */
|
||||||
|
unsigned long long totalInBytes; /* we need it as strm->total_in can be reset by user */
|
||||||
ZSTD_customMem customMem;
|
ZSTD_customMem customMem;
|
||||||
z_stream allocFunc; /* copy of zalloc, zfree, opaque */
|
z_stream allocFunc; /* copy of zalloc, zfree, opaque */
|
||||||
ZSTD_inBuffer inBuffer;
|
ZSTD_inBuffer inBuffer;
|
||||||
@@ -130,7 +131,7 @@ int ZWRAP_initializeCStream(ZWRAP_CCtx* zwc, const void* dict, size_t dictSize,
|
|||||||
{
|
{
|
||||||
LOG_WRAPPERC("- ZWRAP_initializeCStream=%p\n", zwc);
|
LOG_WRAPPERC("- ZWRAP_initializeCStream=%p\n", zwc);
|
||||||
if (zwc == NULL || zwc->zbc == NULL) return Z_STREAM_ERROR;
|
if (zwc == NULL || zwc->zbc == NULL) return Z_STREAM_ERROR;
|
||||||
|
|
||||||
if (!pledgedSrcSize) pledgedSrcSize = zwc->pledgedSrcSize;
|
if (!pledgedSrcSize) pledgedSrcSize = zwc->pledgedSrcSize;
|
||||||
{ ZSTD_parameters const params = ZSTD_getParams(zwc->compressionLevel, pledgedSrcSize, dictSize);
|
{ ZSTD_parameters const params = ZSTD_getParams(zwc->compressionLevel, pledgedSrcSize, dictSize);
|
||||||
size_t errorCode;
|
size_t errorCode;
|
||||||
@@ -156,7 +157,7 @@ int ZWRAPC_finishWithErrorMsg(z_streamp strm, char* message)
|
|||||||
ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
||||||
strm->msg = message;
|
strm->msg = message;
|
||||||
if (zwc == NULL) return Z_STREAM_ERROR;
|
if (zwc == NULL) return Z_STREAM_ERROR;
|
||||||
|
|
||||||
return ZWRAPC_finishWithError(zwc, strm, 0);
|
return ZWRAPC_finishWithError(zwc, strm, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +166,7 @@ int ZWRAP_setPledgedSrcSize(z_streamp strm, unsigned long long pledgedSrcSize)
|
|||||||
{
|
{
|
||||||
ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
||||||
if (zwc == NULL) return Z_STREAM_ERROR;
|
if (zwc == NULL) return Z_STREAM_ERROR;
|
||||||
|
|
||||||
zwc->pledgedSrcSize = pledgedSrcSize;
|
zwc->pledgedSrcSize = pledgedSrcSize;
|
||||||
zwc->comprState = ZWRAP_useInit;
|
zwc->comprState = ZWRAP_useInit;
|
||||||
return Z_OK;
|
return Z_OK;
|
||||||
@@ -189,6 +190,7 @@ ZEXTERN int ZEXPORT z_deflateInit_ OF((z_streamp strm, int level,
|
|||||||
level = ZWRAP_DEFAULT_CLEVEL;
|
level = ZWRAP_DEFAULT_CLEVEL;
|
||||||
|
|
||||||
zwc->streamEnd = 0;
|
zwc->streamEnd = 0;
|
||||||
|
zwc->totalInBytes = 0;
|
||||||
zwc->compressionLevel = level;
|
zwc->compressionLevel = level;
|
||||||
strm->state = (struct internal_state*) zwc; /* use state which in not used by user */
|
strm->state = (struct internal_state*) zwc; /* use state which in not used by user */
|
||||||
strm->total_in = 0;
|
strm->total_in = 0;
|
||||||
@@ -217,7 +219,10 @@ int ZWRAP_deflateReset_keepDict(z_streamp strm)
|
|||||||
return deflateReset(strm);
|
return deflateReset(strm);
|
||||||
|
|
||||||
{ ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
{ ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
||||||
if (zwc) zwc->streamEnd = 0;
|
if (zwc) {
|
||||||
|
zwc->streamEnd = 0;
|
||||||
|
zwc->totalInBytes = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strm->total_in = 0;
|
strm->total_in = 0;
|
||||||
@@ -232,7 +237,7 @@ ZEXTERN int ZEXPORT z_deflateReset OF((z_streamp strm))
|
|||||||
LOG_WRAPPERC("- deflateReset\n");
|
LOG_WRAPPERC("- deflateReset\n");
|
||||||
if (!g_ZWRAP_useZSTDcompression)
|
if (!g_ZWRAP_useZSTDcompression)
|
||||||
return deflateReset(strm);
|
return deflateReset(strm);
|
||||||
|
|
||||||
ZWRAP_deflateReset_keepDict(strm);
|
ZWRAP_deflateReset_keepDict(strm);
|
||||||
|
|
||||||
{ ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
{ ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
||||||
@@ -284,12 +289,12 @@ ZEXTERN int ZEXPORT z_deflate OF((z_streamp strm, int flush))
|
|||||||
if (zwc->zbc == NULL) {
|
if (zwc->zbc == NULL) {
|
||||||
int res;
|
int res;
|
||||||
zwc->zbc = ZSTD_createCStream_advanced(zwc->customMem);
|
zwc->zbc = ZSTD_createCStream_advanced(zwc->customMem);
|
||||||
if (zwc->zbc == NULL) return ZWRAPC_finishWithError(zwc, strm, 0);
|
if (zwc->zbc == NULL) return ZWRAPC_finishWithError(zwc, strm, 0);
|
||||||
res = ZWRAP_initializeCStream(zwc, NULL, 0, (flush == Z_FINISH) ? strm->avail_in : 0);
|
res = ZWRAP_initializeCStream(zwc, NULL, 0, (flush == Z_FINISH) ? strm->avail_in : 0);
|
||||||
if (res != Z_OK) return ZWRAPC_finishWithError(zwc, strm, res);
|
if (res != Z_OK) return ZWRAPC_finishWithError(zwc, strm, res);
|
||||||
if (flush != Z_FINISH) zwc->comprState = ZWRAP_useReset;
|
if (flush != Z_FINISH) zwc->comprState = ZWRAP_useReset;
|
||||||
} else {
|
} else {
|
||||||
if (strm->total_in == 0) {
|
if (zwc->totalInBytes == 0) {
|
||||||
if (zwc->comprState == ZWRAP_useReset) {
|
if (zwc->comprState == ZWRAP_useReset) {
|
||||||
size_t const errorCode = ZSTD_resetCStream(zwc->zbc, (flush == Z_FINISH) ? strm->avail_in : zwc->pledgedSrcSize);
|
size_t const errorCode = ZSTD_resetCStream(zwc->zbc, (flush == Z_FINISH) ? strm->avail_in : zwc->pledgedSrcSize);
|
||||||
if (ZSTD_isError(errorCode)) { LOG_WRAPPERC("ERROR: ZSTD_resetCStream errorCode=%s\n", ZSTD_getErrorName(errorCode)); return ZWRAPC_finishWithError(zwc, strm, 0); }
|
if (ZSTD_isError(errorCode)) { LOG_WRAPPERC("ERROR: ZSTD_resetCStream errorCode=%s\n", ZSTD_getErrorName(errorCode)); return ZWRAPC_finishWithError(zwc, strm, 0); }
|
||||||
@@ -317,13 +322,14 @@ ZEXTERN int ZEXPORT z_deflate OF((z_streamp strm, int flush))
|
|||||||
strm->total_out += zwc->outBuffer.pos;
|
strm->total_out += zwc->outBuffer.pos;
|
||||||
strm->avail_out -= zwc->outBuffer.pos;
|
strm->avail_out -= zwc->outBuffer.pos;
|
||||||
strm->total_in += zwc->inBuffer.pos;
|
strm->total_in += zwc->inBuffer.pos;
|
||||||
|
zwc->totalInBytes += zwc->inBuffer.pos;
|
||||||
strm->next_in += zwc->inBuffer.pos;
|
strm->next_in += zwc->inBuffer.pos;
|
||||||
strm->avail_in -= zwc->inBuffer.pos;
|
strm->avail_in -= zwc->inBuffer.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flush == Z_FULL_FLUSH
|
if (flush == Z_FULL_FLUSH
|
||||||
#if ZLIB_VERNUM >= 0x1240
|
#if ZLIB_VERNUM >= 0x1240
|
||||||
|| flush == Z_TREES
|
|| flush == Z_TREES
|
||||||
#endif
|
#endif
|
||||||
|| flush == Z_BLOCK)
|
|| flush == Z_BLOCK)
|
||||||
return ZWRAPC_finishWithErrorMsg(strm, "Z_FULL_FLUSH, Z_BLOCK and Z_TREES are not supported!");
|
return ZWRAPC_finishWithErrorMsg(strm, "Z_FULL_FLUSH, Z_BLOCK and Z_TREES are not supported!");
|
||||||
@@ -411,6 +417,7 @@ typedef struct {
|
|||||||
ZSTD_DStream* zbd;
|
ZSTD_DStream* zbd;
|
||||||
char headerBuf[16]; /* should be equal or bigger than ZSTD_frameHeaderSize_min */
|
char headerBuf[16]; /* should be equal or bigger than ZSTD_frameHeaderSize_min */
|
||||||
int errorCount;
|
int errorCount;
|
||||||
|
unsigned long long totalInBytes; /* we need it as strm->total_in can be reset by user */
|
||||||
ZWRAP_state_t decompState;
|
ZWRAP_state_t decompState;
|
||||||
ZSTD_inBuffer inBuffer;
|
ZSTD_inBuffer inBuffer;
|
||||||
ZSTD_outBuffer outBuffer;
|
ZSTD_outBuffer outBuffer;
|
||||||
@@ -424,7 +431,7 @@ typedef struct {
|
|||||||
} ZWRAP_DCtx;
|
} ZWRAP_DCtx;
|
||||||
|
|
||||||
|
|
||||||
int ZWRAP_isUsingZSTDdecompression(z_streamp strm)
|
int ZWRAP_isUsingZSTDdecompression(z_streamp strm)
|
||||||
{
|
{
|
||||||
if (strm == NULL) return 0;
|
if (strm == NULL) return 0;
|
||||||
return (strm->reserved == ZWRAP_ZSTD_STREAM);
|
return (strm->reserved == ZWRAP_ZSTD_STREAM);
|
||||||
@@ -458,7 +465,7 @@ ZWRAP_DCtx* ZWRAP_createDCtx(z_streamp strm)
|
|||||||
memcpy(&zwd->customMem, &defaultCustomMem, sizeof(ZSTD_customMem));
|
memcpy(&zwd->customMem, &defaultCustomMem, sizeof(ZSTD_customMem));
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_STATIC_ASSERT(sizeof(zwd->headerBuf) >= ZSTD_frameHeaderSize_min); /* if compilation fails here, assertion is false */
|
MEM_STATIC_ASSERT(sizeof(zwd->headerBuf) >= ZSTD_FRAMEHEADERSIZE_MIN); /* if compilation fails here, assertion is false */
|
||||||
ZWRAP_initDCtx(zwd);
|
ZWRAP_initDCtx(zwd);
|
||||||
return zwd;
|
return zwd;
|
||||||
}
|
}
|
||||||
@@ -488,7 +495,7 @@ int ZWRAPD_finishWithErrorMsg(z_streamp strm, char* message)
|
|||||||
ZWRAP_DCtx* zwd = (ZWRAP_DCtx*) strm->state;
|
ZWRAP_DCtx* zwd = (ZWRAP_DCtx*) strm->state;
|
||||||
strm->msg = message;
|
strm->msg = message;
|
||||||
if (zwd == NULL) return Z_STREAM_ERROR;
|
if (zwd == NULL) return Z_STREAM_ERROR;
|
||||||
|
|
||||||
return ZWRAPD_finishWithError(zwd, strm, 0);
|
return ZWRAPD_finishWithError(zwd, strm, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,6 +518,7 @@ ZEXTERN int ZEXPORT z_inflateInit_ OF((z_streamp strm,
|
|||||||
strcpy(zwd->version, version);
|
strcpy(zwd->version, version);
|
||||||
|
|
||||||
zwd->stream_size = stream_size;
|
zwd->stream_size = stream_size;
|
||||||
|
zwd->totalInBytes = 0;
|
||||||
strm->state = (struct internal_state*) zwd; /* use state which in not used by user */
|
strm->state = (struct internal_state*) zwd; /* use state which in not used by user */
|
||||||
strm->total_in = 0;
|
strm->total_in = 0;
|
||||||
strm->total_out = 0;
|
strm->total_out = 0;
|
||||||
@@ -528,7 +536,7 @@ ZEXTERN int ZEXPORT z_inflateInit2_ OF((z_streamp strm, int windowBits,
|
|||||||
if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB) {
|
if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB) {
|
||||||
return inflateInit2_(strm, windowBits, version, stream_size);
|
return inflateInit2_(strm, windowBits, version, stream_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int ret = z_inflateInit_ (strm, version, stream_size);
|
int ret = z_inflateInit_ (strm, version, stream_size);
|
||||||
LOG_WRAPPERD("- inflateInit2 windowBits=%d\n", windowBits);
|
LOG_WRAPPERD("- inflateInit2 windowBits=%d\n", windowBits);
|
||||||
@@ -551,8 +559,9 @@ int ZWRAP_inflateReset_keepDict(z_streamp strm)
|
|||||||
if (zwd == NULL) return Z_STREAM_ERROR;
|
if (zwd == NULL) return Z_STREAM_ERROR;
|
||||||
ZWRAP_initDCtx(zwd);
|
ZWRAP_initDCtx(zwd);
|
||||||
zwd->decompState = ZWRAP_useReset;
|
zwd->decompState = ZWRAP_useReset;
|
||||||
|
zwd->totalInBytes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strm->total_in = 0;
|
strm->total_in = 0;
|
||||||
strm->total_out = 0;
|
strm->total_out = 0;
|
||||||
return Z_OK;
|
return Z_OK;
|
||||||
@@ -569,7 +578,7 @@ ZEXTERN int ZEXPORT z_inflateReset OF((z_streamp strm))
|
|||||||
if (ret != Z_OK) return ret; }
|
if (ret != Z_OK) return ret; }
|
||||||
|
|
||||||
{ ZWRAP_DCtx* zwd = (ZWRAP_DCtx*) strm->state;
|
{ ZWRAP_DCtx* zwd = (ZWRAP_DCtx*) strm->state;
|
||||||
if (zwd == NULL) return Z_STREAM_ERROR;
|
if (zwd == NULL) return Z_STREAM_ERROR;
|
||||||
zwd->decompState = ZWRAP_useInit; }
|
zwd->decompState = ZWRAP_useInit; }
|
||||||
|
|
||||||
return Z_OK;
|
return Z_OK;
|
||||||
@@ -608,11 +617,11 @@ ZEXTERN int ZEXPORT z_inflateSetDictionary OF((z_streamp strm,
|
|||||||
if (zwd == NULL || zwd->zbd == NULL) return Z_STREAM_ERROR;
|
if (zwd == NULL || zwd->zbd == NULL) return Z_STREAM_ERROR;
|
||||||
errorCode = ZSTD_initDStream_usingDict(zwd->zbd, dictionary, dictLength);
|
errorCode = ZSTD_initDStream_usingDict(zwd->zbd, dictionary, dictLength);
|
||||||
if (ZSTD_isError(errorCode)) return ZWRAPD_finishWithError(zwd, strm, 0);
|
if (ZSTD_isError(errorCode)) return ZWRAPD_finishWithError(zwd, strm, 0);
|
||||||
zwd->decompState = ZWRAP_useReset;
|
zwd->decompState = ZWRAP_useReset;
|
||||||
|
|
||||||
if (strm->total_in == ZSTD_HEADERSIZE) {
|
if (zwd->totalInBytes == ZSTD_HEADERSIZE) {
|
||||||
zwd->inBuffer.src = zwd->headerBuf;
|
zwd->inBuffer.src = zwd->headerBuf;
|
||||||
zwd->inBuffer.size = strm->total_in;
|
zwd->inBuffer.size = zwd->totalInBytes;
|
||||||
zwd->inBuffer.pos = 0;
|
zwd->inBuffer.pos = 0;
|
||||||
zwd->outBuffer.dst = strm->next_out;
|
zwd->outBuffer.dst = strm->next_out;
|
||||||
zwd->outBuffer.size = 0;
|
zwd->outBuffer.size = 0;
|
||||||
@@ -650,8 +659,8 @@ ZEXTERN int ZEXPORT z_inflate OF((z_streamp strm, int flush))
|
|||||||
if (zwd == NULL) return Z_STREAM_ERROR;
|
if (zwd == NULL) return Z_STREAM_ERROR;
|
||||||
if (zwd->decompState == ZWRAP_streamEnd) return Z_STREAM_END;
|
if (zwd->decompState == ZWRAP_streamEnd) return Z_STREAM_END;
|
||||||
|
|
||||||
if (strm->total_in < ZLIB_HEADERSIZE) {
|
if (zwd->totalInBytes < ZLIB_HEADERSIZE) {
|
||||||
if (strm->total_in == 0 && strm->avail_in >= ZLIB_HEADERSIZE) {
|
if (zwd->totalInBytes == 0 && strm->avail_in >= ZLIB_HEADERSIZE) {
|
||||||
if (MEM_readLE32(strm->next_in) != ZSTD_MAGICNUMBER) {
|
if (MEM_readLE32(strm->next_in) != ZSTD_MAGICNUMBER) {
|
||||||
if (zwd->windowBits)
|
if (zwd->windowBits)
|
||||||
errorCode = inflateInit2_(strm, zwd->windowBits, zwd->version, zwd->stream_size);
|
errorCode = inflateInit2_(strm, zwd->windowBits, zwd->version, zwd->stream_size);
|
||||||
@@ -668,12 +677,13 @@ ZEXTERN int ZEXPORT z_inflate OF((z_streamp strm, int flush))
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
srcSize = MIN(strm->avail_in, ZLIB_HEADERSIZE - strm->total_in);
|
srcSize = MIN(strm->avail_in, ZLIB_HEADERSIZE - zwd->totalInBytes);
|
||||||
memcpy(zwd->headerBuf+strm->total_in, strm->next_in, srcSize);
|
memcpy(zwd->headerBuf+zwd->totalInBytes, strm->next_in, srcSize);
|
||||||
strm->total_in += srcSize;
|
strm->total_in += srcSize;
|
||||||
|
zwd->totalInBytes += srcSize;
|
||||||
strm->next_in += srcSize;
|
strm->next_in += srcSize;
|
||||||
strm->avail_in -= srcSize;
|
strm->avail_in -= srcSize;
|
||||||
if (strm->total_in < ZLIB_HEADERSIZE) return Z_OK;
|
if (zwd->totalInBytes < ZLIB_HEADERSIZE) return Z_OK;
|
||||||
|
|
||||||
if (MEM_readLE32(zwd->headerBuf) != ZSTD_MAGICNUMBER) {
|
if (MEM_readLE32(zwd->headerBuf) != ZSTD_MAGICNUMBER) {
|
||||||
z_stream strm2;
|
z_stream strm2;
|
||||||
@@ -725,9 +735,9 @@ ZEXTERN int ZEXPORT z_inflate OF((z_streamp strm, int flush))
|
|||||||
zwd->decompState = ZWRAP_useInit;
|
zwd->decompState = ZWRAP_useInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strm->total_in < ZSTD_HEADERSIZE)
|
if (zwd->totalInBytes < ZSTD_HEADERSIZE)
|
||||||
{
|
{
|
||||||
if (strm->total_in == 0 && strm->avail_in >= ZSTD_HEADERSIZE) {
|
if (zwd->totalInBytes == 0 && strm->avail_in >= ZSTD_HEADERSIZE) {
|
||||||
if (zwd->decompState == ZWRAP_useInit) {
|
if (zwd->decompState == ZWRAP_useInit) {
|
||||||
errorCode = ZSTD_initDStream(zwd->zbd);
|
errorCode = ZSTD_initDStream(zwd->zbd);
|
||||||
if (ZSTD_isError(errorCode)) { LOG_WRAPPERD("ERROR: ZSTD_initDStream errorCode=%s\n", ZSTD_getErrorName(errorCode)); goto error; }
|
if (ZSTD_isError(errorCode)) { LOG_WRAPPERD("ERROR: ZSTD_initDStream errorCode=%s\n", ZSTD_getErrorName(errorCode)); goto error; }
|
||||||
@@ -736,12 +746,13 @@ ZEXTERN int ZEXPORT z_inflate OF((z_streamp strm, int flush))
|
|||||||
if (ZSTD_isError(errorCode)) goto error;
|
if (ZSTD_isError(errorCode)) goto error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
srcSize = MIN(strm->avail_in, ZSTD_HEADERSIZE - strm->total_in);
|
srcSize = MIN(strm->avail_in, ZSTD_HEADERSIZE - zwd->totalInBytes);
|
||||||
memcpy(zwd->headerBuf+strm->total_in, strm->next_in, srcSize);
|
memcpy(zwd->headerBuf+zwd->totalInBytes, strm->next_in, srcSize);
|
||||||
strm->total_in += srcSize;
|
strm->total_in += srcSize;
|
||||||
|
zwd->totalInBytes += srcSize;
|
||||||
strm->next_in += srcSize;
|
strm->next_in += srcSize;
|
||||||
strm->avail_in -= srcSize;
|
strm->avail_in -= srcSize;
|
||||||
if (strm->total_in < ZSTD_HEADERSIZE) return Z_OK;
|
if (zwd->totalInBytes < ZSTD_HEADERSIZE) return Z_OK;
|
||||||
|
|
||||||
if (zwd->decompState == ZWRAP_useInit) {
|
if (zwd->decompState == ZWRAP_useInit) {
|
||||||
errorCode = ZSTD_initDStream(zwd->zbd);
|
errorCode = ZSTD_initDStream(zwd->zbd);
|
||||||
@@ -785,11 +796,12 @@ ZEXTERN int ZEXPORT z_inflate OF((z_streamp strm, int flush))
|
|||||||
strm->total_out += zwd->outBuffer.pos;
|
strm->total_out += zwd->outBuffer.pos;
|
||||||
strm->avail_out -= zwd->outBuffer.pos;
|
strm->avail_out -= zwd->outBuffer.pos;
|
||||||
strm->total_in += zwd->inBuffer.pos;
|
strm->total_in += zwd->inBuffer.pos;
|
||||||
|
zwd->totalInBytes += zwd->inBuffer.pos;
|
||||||
strm->next_in += zwd->inBuffer.pos;
|
strm->next_in += zwd->inBuffer.pos;
|
||||||
strm->avail_in -= zwd->inBuffer.pos;
|
strm->avail_in -= zwd->inBuffer.pos;
|
||||||
if (errorCode == 0) {
|
if (errorCode == 0) {
|
||||||
LOG_WRAPPERD("inflate Z_STREAM_END1 avail_in=%d avail_out=%d total_in=%d total_out=%d\n", (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);
|
LOG_WRAPPERD("inflate Z_STREAM_END1 avail_in=%d avail_out=%d total_in=%d total_out=%d\n", (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);
|
||||||
zwd->decompState = ZWRAP_streamEnd;
|
zwd->decompState = ZWRAP_streamEnd;
|
||||||
return Z_STREAM_END;
|
return Z_STREAM_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1042,3 +1054,24 @@ ZEXTERN uLong ZEXPORT z_crc32 OF((uLong crc, const Bytef *buf, uInt len))
|
|||||||
{
|
{
|
||||||
return crc32(crc, buf, len);
|
return crc32(crc, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if ZLIB_VERNUM >= 0x12B0
|
||||||
|
ZEXTERN uLong ZEXPORT z_adler32_z OF((uLong adler, const Bytef *buf, z_size_t len))
|
||||||
|
{
|
||||||
|
return adler32_z(adler, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZEXTERN uLong ZEXPORT z_crc32_z OF((uLong crc, const Bytef *buf, z_size_t len))
|
||||||
|
{
|
||||||
|
return crc32_z(crc, buf, len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if ZLIB_VERNUM >= 0x1270
|
||||||
|
ZEXTERN const z_crc_t FAR * ZEXPORT z_get_crc_table OF((void))
|
||||||
|
{
|
||||||
|
return get_crc_table();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user