diff --git a/.gitattributes b/.gitattributes
index 387080198..6212bd405 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -14,7 +14,7 @@
*.vcxproj* text eol=crlf
*.vcproj* text eol=crlf
*.suo binary
-*.rc binary
+*.rc text eol=crlf
# Windows
*.bat text eol=crlf
diff --git a/.gitignore b/.gitignore
index 5f2ca97de..751b674e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# Object files
*.o
*.ko
+*.dSYM
# Libraries
*.lib
@@ -30,3 +31,4 @@ _zstdbench/
*.idea
*.swp
.DS_Store
+googletest/
diff --git a/.travis.yml b/.travis.yml
index 350fc1e6b..ff6ab0f79 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,13 +3,26 @@ compiler: gcc
matrix:
fast_finish: true
include:
+ # OS X Mavericks
+ - os: osx
+ env: PLATFORM="OS X Mavericks" CMD="make gnu90test && make clean && make test && make clean && make travis-install"
# Container-based Ubuntu 12.04 LTS Server Edition 64 bit (doesn't support 32-bit includes)
- os: linux
sudo: false
env: PLATFORM="Ubuntu 12.04 container" CMD="make test && make clean && make travis-install"
- os: linux
sudo: false
- env: PLATFORM="Ubuntu 12.04 container" CMD="make -C tests test-zstd_nolegacy && make clean && make zlibwrapper && make clean && make cmaketest"
+ language: cpp
+ install:
+ - export CXX="g++-4.8" CC="gcc-4.8"
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-4.8
+ - g++-4.8
+ env: PLATFORM="Ubuntu 12.04 container" CMD="make zlibwrapper && make clean && make -C tests test-zstd_nolegacy && make clean && make clean && make cmaketest && make clean && make -C contrib/pzstd pzstd && make -C contrib/pzstd googletest && make -C contrib/pzstd test && make -C contrib/pzstd clean"
- os: linux
sudo: false
env: PLATFORM="Ubuntu 12.04 container" CMD="make usan"
@@ -17,14 +30,6 @@ matrix:
sudo: false
env: PLATFORM="Ubuntu 12.04 container" CMD="make asan"
# Standard Ubuntu 12.04 LTS Server Edition 64 bit
- - os: linux
- sudo: required
- env: PLATFORM="Ubuntu 12.04" CMD="make gpptest && make clean && make gnu90test && make clean && make c99test && make clean && make gnu99test && make clean && make clangtest"
- addons:
- apt:
- packages:
- - libc6-dev-i386
- - g++-multilib
- os: linux
sudo: required
env: PLATFORM="Ubuntu 12.04" CMD="make armtest"
@@ -37,14 +42,6 @@ matrix:
- binfmt-support
- qemu
- qemu-user-static
- - os: linux
- sudo: required
- env: PLATFORM="Ubuntu 12.04" CMD="make -C tests test32"
- addons:
- apt:
- packages:
- - libc6-dev-i386
- - gcc-multilib
- os: linux
sudo: required
env: PLATFORM="Ubuntu 12.04" CMD="make -C tests versionsTest"
@@ -53,21 +50,48 @@ matrix:
env: PLATFORM="Ubuntu 12.04" CMD="make asan32"
addons:
apt:
+ sources:
+ - ubuntu-toolchain-r-test
packages:
- libc6-dev-i386
- gcc-multilib
- - os: linux
- sudo: required
- env: PLATFORM="Ubuntu 12.04" CMD="make -C tests valgrindTest"
- addons:
- apt:
- packages:
- - valgrind
# Ubuntu 14.04 LTS Server Edition 64 bit
- os: linux
dist: trusty
sudo: required
- env: PLATFORM="Ubuntu 14.04" CMD="make zlibwrapper && make clean && make gcc5test && make clean && make gcc6test && sudo apt-get install -y -q qemu-system-ppc binfmt-support qemu-user-static gcc-powerpc-linux-gnu && make clean && make ppctest"
+ env: PLATFORM="Ubuntu 14.04" CMD='make -C lib all && CFLAGS="-O1 -g" make -C zlibWrapper valgrindTest && make -C tests valgrindTest'
+ addons:
+ apt:
+ packages:
+ - valgrind
+ - os: linux
+ dist: trusty
+ sudo: required
+ install:
+ - export CXX="g++-4.8" CC="gcc-4.8"
+ env: PLATFORM="Ubuntu 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 pzstd32 && make -C contrib/pzstd googletest32 && make -C contrib/pzstd test32 && make -C contrib/pzstd clean"
+ addons:
+ apt:
+ packages:
+ - libc6-dev-i386
+ - g++-multilib
+ - gcc-4.8
+ - gcc-4.8-multilib
+ - g++-4.8
+ - g++-4.8-multilib
+ - os: linux
+ dist: trusty
+ sudo: required
+ env: PLATFORM="Ubuntu 14.04" CMD="make -C tests test32"
+ addons:
+ apt:
+ packages:
+ - libc6-dev-i386
+ - gcc-multilib
+ - os: linux
+ dist: trusty
+ sudo: required
+ env: PLATFORM="Ubuntu 14.04" CMD="make gcc5test && make clean && make gcc6test && sudo apt-get install -y -q qemu-system-ppc binfmt-support qemu-user-static gcc-powerpc-linux-gnu && make clean && make ppctest"
addons:
apt:
sources:
@@ -78,9 +102,6 @@ matrix:
- gcc-5-multilib
- gcc-6
- gcc-6-multilib
- # OS X Mavericks
- - os: osx
- env: PLATFORM="OS X Mavericks" CMD="make gnu90test && make clean && make test && make clean && make travis-install"
exclude:
- compiler: gcc
diff --git a/Makefile b/Makefile
index 0ca7714c2..ac0c583f4 100644
--- a/Makefile
+++ b/Makefile
@@ -7,8 +7,9 @@
# of patent rights can be found in the PATENTS file in the same directory.
# ################################################################
-PRGDIR = programs
-ZSTDDIR = lib
+PRGDIR = programs
+ZSTDDIR = lib
+BUILDIR = build
ZWRAPDIR = zlibWrapper
TESTDIR = tests
@@ -33,8 +34,7 @@ zstd:
cp $(PRGDIR)/zstd .
zlibwrapper:
- $(MAKE) -C $(ZSTDDIR) all
- $(MAKE) -C $(ZWRAPDIR) all
+ $(MAKE) -C $(ZWRAPDIR) test
test:
$(MAKE) -C $(TESTDIR) $@
@@ -44,14 +44,14 @@ clean:
@$(MAKE) -C $(PRGDIR) $@ > $(VOID)
@$(MAKE) -C $(TESTDIR) $@ > $(VOID)
@$(MAKE) -C $(ZWRAPDIR) $@ > $(VOID)
- @rm -f zstd
+ @$(RM) zstd
@echo Cleaning completed
#----------------------------------------------------------------------------------
#make install is validated only for Linux, OSX, kFreeBSD, Hurd and some BSD targets
#----------------------------------------------------------------------------------
-ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU FreeBSD DragonFly))
+ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU FreeBSD DragonFly NetBSD))
HOST_OS = POSIX
install:
$(MAKE) -C $(ZSTDDIR) $@
@@ -121,9 +121,9 @@ endif
ifneq (,$(filter $(HOST_OS),MSYS POSIX))
cmaketest:
cmake --version
- rm -rf projects/cmake/build
- mkdir projects/cmake/build
- cd projects/cmake/build ; cmake -DPREFIX:STRING=~/install_test_dir $(CMAKE_PARAMS) .. ; $(MAKE) install ; $(MAKE) uninstall
+ $(RM) -r $(BUILDIR)/cmake/build
+ mkdir $(BUILDIR)/cmake/build
+ cd $(BUILDIR)/cmake/build ; cmake -DPREFIX:STRING=~/install_test_dir $(CMAKE_PARAMS) .. ; $(MAKE) install ; $(MAKE) uninstall
c90test: clean
CFLAGS="-std=c90" $(MAKE) all # will fail, due to // and long long
diff --git a/NEWS b/NEWS
index 2e300726c..ad56d17a8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,17 @@
+v1.1.0
+New : contrib/pzstd, parallel version of zstd, by Nick Terrell
+added : NetBSD install target (#338)
+Improved : speed for batches of small files
+Improved : speed of zlib wrapper, by Przemyslaw Skibinski
+Changed : libzstd on Windows supports legacy formats, by Christophe Chevalier
+Fixed : CLI -d output to stdout by default when input is stdin (#322)
+Fixed : CLI correctly detects console on Mac OS-X
+Fixed : CLI supports recursive mode `-r` on Mac OS-X
+Fixed : Legacy decoders use unified error codes, reported by benrg (#341), fixed by Przemyslaw Skibinski
+Fixed : compatibility with OpenBSD, reported by Juan Francisco Cantero Hurtado (#319)
+Fixed : compatibility with Hurd, by Przemyslaw Skibinski (#365)
+Fixed : zstd-pgo, reported by octoploid (#329)
+
v1.0.0
Change Licensing, all project is now BSD, Copyright Facebook
Small decompression speed improvement
@@ -29,6 +43,9 @@ Modified : minor compression level adaptations
Updated : compression format specification to v0.2.0
changed : zstd.h moved to /lib directory
+v0.7.5
+Transition version, supporting decoding of v0.8.x
+
v0.7.4
Added : homebrew for Mac, by Daniel Cade
Added : more examples
@@ -179,6 +196,6 @@ frame concatenation support
v0.1.1
fix compression bug
detects write-flush errors
-git@github.com:Cyan4973/zstd.git
+
v0.1.0
first release
diff --git a/README.md b/README.md
index e4af99036..53609a146 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ you can consult a list of known ports on [Zstandard homepage](http://www.zstd.ne
|master | [](https://travis-ci.org/facebook/zstd) |
|dev | [](https://travis-ci.org/facebook/zstd) |
-As a reference, several fast compression algorithms were tested and compared on a Core i7-3930K CPU @ 4.5GHz, using [lzbench], an open-source in-memory benchmark by @inikep compiled with gcc 5.4.0, with the [Silesia compression corpus].
+As a reference, several fast compression algorithms were tested and compared on a Core i7-3930K CPU @ 4.5GHz, using [lzbench], an open-source in-memory benchmark by @inikep compiled with GCC 5.4.0, with the [Silesia compression corpus].
[lzbench]: https://github.com/inikep/lzbench
[Silesia compression corpus]: http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia
@@ -32,32 +32,32 @@ As a reference, several fast compression algorithms were tested and compared on
[LZ4]: http://www.lz4.org/
Zstd can also offer stronger compression ratios at the cost of compression speed.
-Speed vs Compression trade-off is configurable by small increment. Decompression speed is preserved and remain roughly the same at all settings, a property shared by most LZ compression algorithms, such as [zlib] or lzma.
+Speed vs Compression trade-off is configurable by small increments. Decompression speed is preserved and remains roughly the same at all settings, a property shared by most LZ compression algorithms, such as [zlib] or lzma.
-The following tests were run on a Core i7-3930K CPU @ 4.5GHz, using [lzbench], an open-source in-memory benchmark by @inikep compiled with gcc 5.2.1, on the [Silesia compression corpus].
+The following tests were run on a Core i7-3930K CPU @ 4.5GHz, using [lzbench], an open-source in-memory benchmark by @inikep compiled with GCC 5.2.1, on the [Silesia compression corpus].
Compression Speed vs Ratio | Decompression Speed
---------------------------|--------------------
 | 
-Several algorithms can produce higher compression ratio but at slower speed, falling outside of the graph.
+Several algorithms can produce higher compression ratios, but at slower speeds, falling outside of the graph.
For a larger picture including very slow modes, [click on this link](images/DCspeed5.png) .
### The case for Small Data compression
-Previous charts provide results applicable to typical files and streams scenarios (several MB). Small data come 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. The smaller the amount of data to compress, the more difficult it is to achieve any significant compression.
-This problem is common to any compression algorithm. 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.
+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.
-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, 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:

These compression gains are achieved while simultaneously providing faster compression and decompression speeds.
-Dictionary work 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 greater 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.
+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.
#### Dictionary compression How To :
@@ -73,9 +73,38 @@ Hence, deploying one dictionary per type of data will provide the greater benefi
`zstd --decompress FILE.zst -D dictionaryName`
+### Build
+
+Once you have the repository cloned, there are multiple ways provided to build Zstandard.
+
+#### Makefile
+
+If your system is compatible with a standard `make` (or `gmake`) binary generator,
+you can simply run it at the root directory.
+It will generate `zstd` within root directory.
+
+Other available options include :
+- `make install` : create and install zstd binary, library and man page
+- `make test` : create and run `zstd` and test tools on local platform
+
+#### cmake
+
+A `cmake` project generator is provided within `build/cmake`.
+It can generate Makefiles or other build scripts
+to create `zstd` binary, and `libzstd` dynamic and static libraries.
+
+#### Visual (Windows)
+
+Going into `build` directory, you will find additional possibilities :
+- Projects for Visual Studio 2005, 2008 and 2010
+ + VS2010 project is compatible with VS2012, VS2013 and VS2015
+- Automated build scripts for Visual compiler by @KrzysFR , in `build/VS_scripts`,
+ which will build `zstd` cli and `libzstd` library without any need to open Visual Studio solution.
+
+
### Status
-Zstandard is currently deployed within Facebook. It is used daily to compress and decompress very large amount of data in multiple formats and use cases.
+Zstandard is currently deployed within Facebook. It is used daily to compress and decompress very large amounts of data in multiple formats and use cases.
Zstandard is considered safe for production environments.
### License
diff --git a/appveyor.yml b/appveyor.yml
index 4e21db1c4..6345c7b39 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,27 +1,28 @@
version: 1.0.{build}
environment:
matrix:
- - COMPILER: "visual"
- CONFIGURATION: "Debug"
- PLATFORM: "x64"
- - COMPILER: "visual"
- CONFIGURATION: "Debug"
- PLATFORM: "Win32"
- - COMPILER: "visual"
- CONFIGURATION: "Release"
- PLATFORM: "x64"
- - COMPILER: "visual"
- CONFIGURATION: "Release"
- PLATFORM: "Win32"
- COMPILER: "gcc"
MAKE_PARAMS: "test"
PLATFORM: "mingw64"
- COMPILER: "gcc"
MAKE_PARAMS: "test"
PLATFORM: "mingw32"
+ - COMPILER: "visual"
+ CONFIGURATION: "Debug"
+ PLATFORM: "x64"
+ - COMPILER: "visual"
+ CONFIGURATION: "Debug"
+ PLATFORM: "Win32"
+ - COMPILER: "visual"
+ CONFIGURATION: "Release"
+ PLATFORM: "x64"
+ - COMPILER: "visual"
+ CONFIGURATION: "Release"
+ PLATFORM: "Win32"
install:
- ECHO Installing %COMPILER% %PLATFORM% %CONFIGURATION%
+ - MKDIR bin
- if [%COMPILER%]==[gcc] SET PATH_ORIGINAL=%PATH%
- if [%COMPILER%]==[gcc] (
SET "CLANG_PARAMS=-C tests zstd fullbench fuzzer zbufftest paramgrill datagen CC=clang MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion"" &&
@@ -35,8 +36,8 @@ install:
build_script:
- ECHO Building %COMPILER% %PLATFORM% %CONFIGURATION%
- - if [%PLATFORM%]==[mingw32] SET PATH=%PATH_MINGW32%;%PATH_ORIGINAL%
- - if [%PLATFORM%]==[mingw64] SET PATH=%PATH_MINGW64%;%PATH_ORIGINAL%
+ - if [%PLATFORM%]==[mingw32] SET PATH=%PATH_MINGW32%;%PATH_ORIGINAL%
+ - if [%PLATFORM%]==[mingw64] SET PATH=%PATH_MINGW64%;%PATH_ORIGINAL%
- if [%PLATFORM%]==[mingw64] (
make clean &&
ECHO *** &&
@@ -45,7 +46,15 @@ build_script:
ECHO make %CLANG_PARAMS% &&
make %CLANG_PARAMS% &&
COPY tests\fuzzer.exe tests\fuzzer_clang.exe &&
- make clean
+ make clean &&
+ ECHO *** &&
+ ECHO *** Building pzstd for %PLATFORM% &&
+ ECHO *** &&
+ ECHO make -C contrib\pzstd pzstd &&
+ make -C contrib\pzstd pzstd &&
+ make -C contrib\pzstd googletest-mingw64 &&
+ make -C contrib\pzstd test &&
+ make -C contrib\pzstd clean
)
- if [%COMPILER%]==[gcc] (
ECHO *** &&
@@ -54,58 +63,66 @@ build_script:
make -v &&
cc -v &&
ECHO make %MAKE_PARAMS% &&
- make %MAKE_PARAMS% &&
- make clean
+ make %MAKE_PARAMS%
)
+ - if [%COMPILER%]==[gcc] if [%PLATFORM%]==[mingw64] (
+ COPY programs\zstd.exe bin\zstd.exe &&
+ appveyor PushArtifact bin\zstd.exe
+ )
+ - if [%COMPILER%]==[gcc] if [%PLATFORM%]==[mingw32] (
+ COPY programs\zstd.exe bin\zstd32.exe &&
+ appveyor PushArtifact bin\zstd32.exe
+ )
+ - if [%COMPILER%]==[gcc] make clean
- if [%COMPILER%]==[visual] (
ECHO *** &&
ECHO *** Building Visual Studio 2008 %PLATFORM%\%CONFIGURATION% in %APPVEYOR_BUILD_FOLDER% &&
ECHO *** &&
- msbuild "projects\VS2008\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v90 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
- DIR projects\VS2008\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
- MD5sum projects/VS2008/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
- COPY projects\VS2008\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2008_%PLATFORM%_%CONFIGURATION%.exe &&
+ msbuild "build\VS2008\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v90 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ DIR build\VS2008\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
+ MD5sum build/VS2008/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
+ COPY build\VS2008\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2008_%PLATFORM%_%CONFIGURATION%.exe &&
ECHO *** &&
ECHO *** Building Visual Studio 2010 %PLATFORM%\%CONFIGURATION% &&
ECHO *** &&
- msbuild "projects\VS2010\zstd.sln" %ADDITIONALPARAM% /m /verbosity:minimal /property:PlatformToolset=v100 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\projects\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
- DIR projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
- MD5sum projects/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
- msbuild "projects\VS2010\zstd.sln" %ADDITIONALPARAM% /m /verbosity:minimal /property:PlatformToolset=v100 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
- DIR projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
- MD5sum projects/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
- COPY projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2010_%PLATFORM%_%CONFIGURATION%.exe &&
+ msbuild "build\VS2010\zstd.sln" %ADDITIONALPARAM% /m /verbosity:minimal /property:PlatformToolset=v100 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\build\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ DIR build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
+ MD5sum build/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
+ msbuild "build\VS2010\zstd.sln" %ADDITIONALPARAM% /m /verbosity:minimal /property:PlatformToolset=v100 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ DIR build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
+ MD5sum build/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
+ COPY build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2010_%PLATFORM%_%CONFIGURATION%.exe &&
ECHO *** &&
ECHO *** Building Visual Studio 2012 %PLATFORM%\%CONFIGURATION% &&
ECHO *** &&
- msbuild "projects\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\projects\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
- DIR projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
- MD5sum projects/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
- msbuild "projects\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
- DIR projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
- MD5sum projects/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
- COPY projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2012_%PLATFORM%_%CONFIGURATION%.exe &&
+ msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\build\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ DIR build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
+ MD5sum build/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
+ msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ DIR build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
+ MD5sum build/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
+ COPY build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2012_%PLATFORM%_%CONFIGURATION%.exe &&
ECHO *** &&
ECHO *** Building Visual Studio 2013 %PLATFORM%\%CONFIGURATION% &&
ECHO *** &&
- msbuild "projects\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v120 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\projects\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
- DIR projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
- MD5sum projects/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
- msbuild "projects\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v120 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
- DIR projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
- MD5sum projects/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
- COPY projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2013_%PLATFORM%_%CONFIGURATION%.exe &&
+ msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v120 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\build\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ DIR build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
+ MD5sum build/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
+ msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v120 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ DIR build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
+ MD5sum build/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
+ COPY build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2013_%PLATFORM%_%CONFIGURATION%.exe &&
ECHO *** &&
ECHO *** Building Visual Studio 2015 %PLATFORM%\%CONFIGURATION% &&
ECHO *** &&
- msbuild "projects\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v140 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\projects\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
- DIR projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
- MD5sum projects/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
- msbuild "projects\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v140 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
- DIR projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
- MD5sum projects/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
- COPY projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2015_%PLATFORM%_%CONFIGURATION%.exe &&
- COPY projects\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe tests\
+ msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v140 /p:ForceImportBeforeCppTargets=%APPVEYOR_BUILD_FOLDER%\build\VS2010\CompileAsCpp.props /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ DIR build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
+ MD5sum build/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
+ msbuild "build\VS2010\zstd.sln" /m /verbosity:minimal /property:PlatformToolset=v140 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ DIR build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe &&
+ MD5sum build/VS2010/bin/%PLATFORM%/%CONFIGURATION%/*.exe &&
+ COPY build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\fuzzer.exe tests\fuzzer_VS2015_%PLATFORM%_%CONFIGURATION%.exe &&
+ COPY build\VS2010\bin\%PLATFORM%\%CONFIGURATION%\*.exe tests\
)
test_script:
@@ -126,3 +143,29 @@ test_script:
fuzzer_VS2013_%PLATFORM%_Release.exe %FUZZERTEST% &&
fuzzer_VS2015_%PLATFORM%_Release.exe %FUZZERTEST%
)
+
+artifacts:
+ - path: bin\zstd.exe
+ - path: bin\zstd32.exe
+
+deploy:
+- provider: GitHub
+ auth_token:
+ secure: LgJo8emYc3sFnlNWkGl4/VYK3nk/8+RagcsqDlAi3xeqNGNutnKjcftjg84uJoT4
+ artifact: bin\zstd.exe
+ force_update: true
+ on:
+ branch: autobuild
+ COMPILER: gcc
+ PLATFORM: "mingw64"
+ appveyor_repo_tag: true
+- provider: GitHub
+ auth_token:
+ secure: LgJo8emYc3sFnlNWkGl4/VYK3nk/8+RagcsqDlAi3xeqNGNutnKjcftjg84uJoT4
+ artifact: bin\zstd32.exe
+ force_update: true
+ on:
+ branch: autobuild
+ COMPILER: gcc
+ PLATFORM: "mingw32"
+ appveyor_repo_tag: true
diff --git a/projects/.gitignore b/build/.gitignore
similarity index 92%
rename from projects/.gitignore
rename to build/.gitignore
index 7ceb958ea..86ed710bd 100644
--- a/projects/.gitignore
+++ b/build/.gitignore
@@ -1,7 +1,7 @@
*Copy
# Visual C++
-build/
+bin/
VS2005/
VS2008/
VS2010/
diff --git a/projects/README.md b/build/README.md
similarity index 85%
rename from projects/README.md
rename to build/README.md
index 39742fb1a..8dc67326b 100644
--- a/projects/README.md
+++ b/build/README.md
@@ -8,13 +8,13 @@ The following projects are included with the zstd distribution:
- `VS2005` - Visual Studio 2005 project
- `VS2008` - Visual Studio 2008 project
- `VS2010` - Visual Studio 2010 project (which also works well with Visual Studio 2012, 2013, 2015)
-- `build` - command line scripts prepared for Visual Studio compilation without IDE
+- `VS_scripts` - command line scripts prepared for Visual Studio compilation without IDE
#### How to compile zstd with Visual Studio
1. Install Visual Studio e.g. VS 2015 Community Edition (it's free).
-2. Download the latest version of zstd from https://github.com/Cyan4973/zstd/releases
+2. Download the latest version of zstd from https://github.com/facebook/zstd/releases
3. Decompress ZIP archive.
4. Go to decompressed directory then to `projects` then `VS2010` and open `zstd.sln`
5. Visual Studio will ask about converting VS2010 project to VS2015 and you should agree.
diff --git a/projects/VS2005/fullbench/fullbench.vcproj b/build/VS2005/fullbench/fullbench.vcproj
similarity index 100%
rename from projects/VS2005/fullbench/fullbench.vcproj
rename to build/VS2005/fullbench/fullbench.vcproj
diff --git a/projects/VS2005/fuzzer/fuzzer.vcproj b/build/VS2005/fuzzer/fuzzer.vcproj
similarity index 100%
rename from projects/VS2005/fuzzer/fuzzer.vcproj
rename to build/VS2005/fuzzer/fuzzer.vcproj
diff --git a/projects/VS2005/zstd.sln b/build/VS2005/zstd.sln
similarity index 100%
rename from projects/VS2005/zstd.sln
rename to build/VS2005/zstd.sln
diff --git a/projects/VS2005/zstd/zstd.vcproj b/build/VS2005/zstd/zstd.vcproj
similarity index 97%
rename from projects/VS2005/zstd/zstd.vcproj
rename to build/VS2005/zstd/zstd.vcproj
index ff45e3932..68c3578ea 100644
--- a/projects/VS2005/zstd/zstd.vcproj
+++ b/build/VS2005/zstd/zstd.vcproj
@@ -44,7 +44,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -121,7 +121,7 @@
EnableIntrinsicFunctions="true"
OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
@@ -196,7 +196,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -274,7 +274,7 @@
EnableIntrinsicFunctions="true"
OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ PreprocessorDefinitions="ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
diff --git a/projects/VS2005/zstdlib/zstdlib.vcproj b/build/VS2005/zstdlib/zstdlib.vcproj
similarity index 90%
rename from projects/VS2005/zstdlib/zstdlib.vcproj
rename to build/VS2005/zstdlib/zstdlib.vcproj
index 2313c87aa..7ea3d9b7b 100644
--- a/projects/VS2005/zstdlib/zstdlib.vcproj
+++ b/build/VS2005/zstdlib/zstdlib.vcproj
@@ -44,7 +44,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\dictBuilder"
- PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE"
+ PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -120,7 +120,7 @@
EnableIntrinsicFunctions="true"
OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\dictBuilder"
- PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE"
+ PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
@@ -194,7 +194,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\dictBuilder"
- PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE"
+ PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -271,7 +271,7 @@
EnableIntrinsicFunctions="true"
OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\dictBuilder"
- PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE"
+ PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
@@ -379,6 +379,34 @@
RelativePath="..\..\..\lib\decompress\zstd_decompress.c"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*****************************************************************************\
+* *
+* verrsrc.h - Version Resource definitions *
+* *
+* Include file declaring version resources in rc files *
+* *
+* Copyright (c) Microsoft Corporation. All rights reserved. *
+* *
+\*****************************************************************************/
+
+#pragma region Application Family
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+
+/* ----- Symbols ----- */
+#define VS_FILE_INFO RT_VERSION
+#define VS_VERSION_INFO 1
+#define VS_USER_DEFINED 100
+
+/* ----- VS_VERSION.dwFileFlags ----- */
+#ifndef _MAC
+#define VS_FFI_SIGNATURE 0xFEEF04BDL
+#else
+#define VS_FFI_SIGNATURE 0xBD04EFFEL
+#endif
+#define VS_FFI_STRUCVERSION 0x00010000L
+#define VS_FFI_FILEFLAGSMASK 0x0000003FL
+
+/* ----- VS_VERSION.dwFileFlags ----- */
+#define VS_FF_DEBUG 0x00000001L
+#define VS_FF_PRERELEASE 0x00000002L
+#define VS_FF_PATCHED 0x00000004L
+#define VS_FF_PRIVATEBUILD 0x00000008L
+#define VS_FF_INFOINFERRED 0x00000010L
+#define VS_FF_SPECIALBUILD 0x00000020L
+
+/* ----- VS_VERSION.dwFileOS ----- */
+#define VOS_UNKNOWN 0x00000000L
+#define VOS_DOS 0x00010000L
+#define VOS_OS216 0x00020000L
+#define VOS_OS232 0x00030000L
+#define VOS_NT 0x00040000L
+#define VOS_WINCE 0x00050000L
+
+#define VOS__BASE 0x00000000L
+#define VOS__WINDOWS16 0x00000001L
+#define VOS__PM16 0x00000002L
+#define VOS__PM32 0x00000003L
+#define VOS__WINDOWS32 0x00000004L
+
+#define VOS_DOS_WINDOWS16 0x00010001L
+#define VOS_DOS_WINDOWS32 0x00010004L
+#define VOS_OS216_PM16 0x00020002L
+#define VOS_OS232_PM32 0x00030003L
+#define VOS_NT_WINDOWS32 0x00040004L
+
+/* ----- VS_VERSION.dwFileType ----- */
+#define VFT_UNKNOWN 0x00000000L
+#define VFT_APP 0x00000001L
+#define VFT_DLL 0x00000002L
+#define VFT_DRV 0x00000003L
+#define VFT_FONT 0x00000004L
+#define VFT_VXD 0x00000005L
+#define VFT_STATIC_LIB 0x00000007L
+
+/* ----- VS_VERSION.dwFileSubtype for VFT_WINDOWS_DRV ----- */
+#define VFT2_UNKNOWN 0x00000000L
+#define VFT2_DRV_PRINTER 0x00000001L
+#define VFT2_DRV_KEYBOARD 0x00000002L
+#define VFT2_DRV_LANGUAGE 0x00000003L
+#define VFT2_DRV_DISPLAY 0x00000004L
+#define VFT2_DRV_MOUSE 0x00000005L
+#define VFT2_DRV_NETWORK 0x00000006L
+#define VFT2_DRV_SYSTEM 0x00000007L
+#define VFT2_DRV_INSTALLABLE 0x00000008L
+#define VFT2_DRV_SOUND 0x00000009L
+#define VFT2_DRV_COMM 0x0000000AL
+#define VFT2_DRV_INPUTMETHOD 0x0000000BL
+#define VFT2_DRV_VERSIONED_PRINTER 0x0000000CL
+
+/* ----- VS_VERSION.dwFileSubtype for VFT_WINDOWS_FONT ----- */
+#define VFT2_FONT_RASTER 0x00000001L
+#define VFT2_FONT_VECTOR 0x00000002L
+#define VFT2_FONT_TRUETYPE 0x00000003L
+
+#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
+#pragma endregion
+
+#pragma region Desktop Family
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+
+/* ----- VerFindFile() flags ----- */
+#define VFFF_ISSHAREDFILE 0x0001
+
+#define VFF_CURNEDEST 0x0001
+#define VFF_FILEINUSE 0x0002
+#define VFF_BUFFTOOSMALL 0x0004
+
+/* ----- VerInstallFile() flags ----- */
+#define VIFF_FORCEINSTALL 0x0001
+#define VIFF_DONTDELETEOLD 0x0002
+
+#define VIF_TEMPFILE 0x00000001L
+#define VIF_MISMATCH 0x00000002L
+#define VIF_SRCOLD 0x00000004L
+
+#define VIF_DIFFLANG 0x00000008L
+#define VIF_DIFFCODEPG 0x00000010L
+#define VIF_DIFFTYPE 0x00000020L
+
+#define VIF_WRITEPROT 0x00000040L
+#define VIF_FILEINUSE 0x00000080L
+#define VIF_OUTOFSPACE 0x00000100L
+#define VIF_ACCESSVIOLATION 0x00000200L
+#define VIF_SHARINGVIOLATION 0x00000400L
+#define VIF_CANNOTCREATE 0x00000800L
+#define VIF_CANNOTDELETE 0x00001000L
+#define VIF_CANNOTRENAME 0x00002000L
+#define VIF_CANNOTDELETECUR 0x00004000L
+#define VIF_OUTOFMEMORY 0x00008000L
+
+#define VIF_CANNOTREADSRC 0x00010000L
+#define VIF_CANNOTREADDST 0x00020000L
+
+#define VIF_BUFFTOOSMALL 0x00040000L
+#define VIF_CANNOTLOADLZ32 0x00080000L
+#define VIF_CANNOTLOADCABINET 0x00100000L
+
+#ifndef RC_INVOKED /* RC doesn't need to see the rest of this */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ FILE_VER_GET_... flags are for use by
+ GetFileVersionInfoSizeEx
+ GetFileVersionInfoExW
+*/
+#define FILE_VER_GET_LOCALISED 0x01
+#define FILE_VER_GET_NEUTRAL 0x02
+#define FILE_VER_GET_PREFETCHED 0x04
+
+/* ----- Types and structures ----- */
+
+typedef struct tagVS_FIXEDFILEINFO
+{
+ DWORD dwSignature; /* e.g. 0xfeef04bd */
+ DWORD dwStrucVersion; /* e.g. 0x00000042 = "0.42" */
+ DWORD dwFileVersionMS; /* e.g. 0x00030075 = "3.75" */
+ DWORD dwFileVersionLS; /* e.g. 0x00000031 = "0.31" */
+ DWORD dwProductVersionMS; /* e.g. 0x00030010 = "3.10" */
+ DWORD dwProductVersionLS; /* e.g. 0x00000031 = "0.31" */
+ DWORD dwFileFlagsMask; /* = 0x3F for version "0.42" */
+ DWORD dwFileFlags; /* e.g. VFF_DEBUG | VFF_PRERELEASE */
+ DWORD dwFileOS; /* e.g. VOS_DOS_WINDOWS16 */
+ DWORD dwFileType; /* e.g. VFT_DRIVER */
+ DWORD dwFileSubtype; /* e.g. VFT2_DRV_KEYBOARD */
+ DWORD dwFileDateMS; /* e.g. 0 */
+ DWORD dwFileDateLS; /* e.g. 0 */
+} VS_FIXEDFILEINFO;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !RC_INVOKED */
+
+#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
+#pragma endregion
+
diff --git a/build/VS2010/zstd/generate_res/zstd32.res b/build/VS2010/zstd/generate_res/zstd32.res
new file mode 100644
index 000000000..362d9c22d
Binary files /dev/null and b/build/VS2010/zstd/generate_res/zstd32.res differ
diff --git a/build/VS2010/zstd/generate_res/zstd64.res b/build/VS2010/zstd/generate_res/zstd64.res
new file mode 100644
index 000000000..d726146f2
Binary files /dev/null and b/build/VS2010/zstd/generate_res/zstd64.res differ
diff --git a/build/VS2010/zstd/zstd.rc b/build/VS2010/zstd/zstd.rc
new file mode 100644
index 000000000..464b2f143
--- /dev/null
+++ b/build/VS2010/zstd/zstd.rc
@@ -0,0 +1,51 @@
+// Microsoft Visual C++ generated resource script.
+//
+
+#include "zstd.h" /* ZSTD_VERSION_STRING */
+#define APSTUDIO_READONLY_SYMBOLS
+#include "verrsrc.h"
+#undef APSTUDIO_READONLY_SYMBOLS
+
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE 9, 1
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION ZSTD_VERSION_MAJOR,ZSTD_VERSION_MINOR,ZSTD_VERSION_RELEASE,0
+ PRODUCTVERSION ZSTD_VERSION_MAJOR,ZSTD_VERSION_MINOR,ZSTD_VERSION_RELEASE,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS_NT_WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "Yann Collet"
+ VALUE "FileDescription", "Fast and efficient compression algorithm"
+ VALUE "FileVersion", ZSTD_VERSION_STRING
+ VALUE "InternalName", "zstd.exe"
+ VALUE "LegalCopyright", "Copyright (C) 2013-2016, Yann Collet"
+ VALUE "OriginalFilename", "zstd.exe"
+ VALUE "ProductName", "Zstandard"
+ VALUE "ProductVersion", ZSTD_VERSION_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 1200
+ END
+END
+
+#endif
diff --git a/projects/VS2010/zstd/zstd.vcxproj b/build/VS2010/zstd/zstd.vcxproj
similarity index 95%
rename from projects/VS2010/zstd/zstd.vcxproj
rename to build/VS2010/zstd/zstd.vcxproj
index 5922d925e..eb7e7b504 100644
--- a/projects/VS2010/zstd/zstd.vcxproj
+++ b/build/VS2010/zstd/zstd.vcxproj
@@ -69,6 +69,9 @@
+
+
+
{4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}
Win32Proj
@@ -146,7 +149,7 @@
Level4
Disabled
- WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
false
@@ -162,7 +165,7 @@
Level4
Disabled
- WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
false
@@ -180,7 +183,7 @@
MaxSpeed
true
true
- WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
false
false
MultiThreaded
@@ -201,7 +204,7 @@
MaxSpeed
true
true
- WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
false
false
MultiThreaded
@@ -217,4 +220,4 @@
-
+
\ No newline at end of file
diff --git a/projects/VS2010/zstdlib/zstdlib.rc b/build/VS2010/zstdlib/zstdlib.rc
similarity index 83%
rename from projects/VS2010/zstdlib/zstdlib.rc
rename to build/VS2010/zstdlib/zstdlib.rc
index 6c4dde486..de8ecbcf8 100644
--- a/projects/VS2010/zstdlib/zstdlib.rc
+++ b/build/VS2010/zstdlib/zstdlib.rc
@@ -1,51 +1,51 @@
-// Microsoft Visual C++ generated resource script.
-//
-
-#include "zstd.h" /* ZSTD_VERSION_STRING */
-#define APSTUDIO_READONLY_SYMBOLS
-#include "verrsrc.h"
-#undef APSTUDIO_READONLY_SYMBOLS
-
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE 9, 1
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION ZSTD_LIB_VERSION
- PRODUCTVERSION ZSTD_LIB_VERSION
- FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
-#ifdef _DEBUG
- FILEFLAGS VS_FF_DEBUG
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS VOS_NT_WINDOWS32
- FILETYPE VFT_DLL
- FILESUBTYPE VFT2_UNKNOWN
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904B0"
- BEGIN
- VALUE "CompanyName", "Yann Collet"
- VALUE "FileDescription", "Fast and efficient compression algorithm"
- VALUE "FileVersion", ZSTD_VERSION_STRING
- VALUE "InternalName", "zstdlib.dll"
- VALUE "LegalCopyright", "Copyright (C) 2013-2015, Yann Collet"
- VALUE "OriginalFilename", "zstdlib.dll"
- VALUE "ProductName", "Zstandard"
- VALUE "ProductVersion", ZSTD_VERSION_STRING
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x0409, 1200
- END
-END
-
-#endif
+// Microsoft Visual C++ generated resource script.
+//
+
+#include "zstd.h" /* ZSTD_VERSION_STRING */
+#define APSTUDIO_READONLY_SYMBOLS
+#include "verrsrc.h"
+#undef APSTUDIO_READONLY_SYMBOLS
+
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE 9, 1
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION ZSTD_VERSION_MAJOR,ZSTD_VERSION_MINOR,ZSTD_VERSION_RELEASE,0
+ PRODUCTVERSION ZSTD_VERSION_MAJOR,ZSTD_VERSION_MINOR,ZSTD_VERSION_RELEASE,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS_NT_WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "Yann Collet"
+ VALUE "FileDescription", "Fast and efficient compression algorithm"
+ VALUE "FileVersion", ZSTD_VERSION_STRING
+ VALUE "InternalName", "zstdlib.dll"
+ VALUE "LegalCopyright", "Copyright (C) 2013-2016, Yann Collet"
+ VALUE "OriginalFilename", "zstdlib.dll"
+ VALUE "ProductName", "Zstandard"
+ VALUE "ProductVersion", ZSTD_VERSION_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 1200
+ END
+END
+
+#endif
diff --git a/projects/VS2010/zstdlib/zstdlib.vcxproj b/build/VS2010/zstdlib/zstdlib.vcxproj
similarity index 87%
rename from projects/VS2010/zstdlib/zstdlib.vcxproj
rename to build/VS2010/zstdlib/zstdlib.vcxproj
index 232fdf442..b97808dd0 100644
--- a/projects/VS2010/zstdlib/zstdlib.vcxproj
+++ b/build/VS2010/zstdlib/zstdlib.vcxproj
@@ -32,6 +32,13 @@
+
+
+
+
+
+
+
@@ -40,6 +47,14 @@
+
+
+
+
+
+
+
+
@@ -126,7 +141,7 @@
Level4
Disabled
- ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
true
EnableFastChecks
MultiThreadedDebugDLL
@@ -146,7 +161,7 @@
Level4
Disabled
- ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=1;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
true
EnableFastChecks
MultiThreadedDebugDLL
@@ -166,7 +181,7 @@
MaxSpeed
true
true
- ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
false
MultiThreaded
ProgramDatabase
@@ -188,7 +203,7 @@
MaxSpeed
true
true
- ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=1;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
false
false
MultiThreaded
diff --git a/projects/build/README.md b/build/VS_scripts/README.md
similarity index 100%
rename from projects/build/README.md
rename to build/VS_scripts/README.md
diff --git a/projects/build/build.VS2010.cmd b/build/VS_scripts/build.VS2010.cmd
similarity index 100%
rename from projects/build/build.VS2010.cmd
rename to build/VS_scripts/build.VS2010.cmd
diff --git a/projects/build/build.VS2012.cmd b/build/VS_scripts/build.VS2012.cmd
similarity index 100%
rename from projects/build/build.VS2012.cmd
rename to build/VS_scripts/build.VS2012.cmd
diff --git a/projects/build/build.VS2013.cmd b/build/VS_scripts/build.VS2013.cmd
similarity index 100%
rename from projects/build/build.VS2013.cmd
rename to build/VS_scripts/build.VS2013.cmd
diff --git a/projects/build/build.VS2015.cmd b/build/VS_scripts/build.VS2015.cmd
similarity index 100%
rename from projects/build/build.VS2015.cmd
rename to build/VS_scripts/build.VS2015.cmd
diff --git a/projects/build/build.generic.cmd b/build/VS_scripts/build.generic.cmd
similarity index 100%
rename from projects/build/build.generic.cmd
rename to build/VS_scripts/build.generic.cmd
diff --git a/projects/cmake/.gitignore b/build/cmake/.gitignore
similarity index 100%
rename from projects/cmake/.gitignore
rename to build/cmake/.gitignore
diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt
new file mode 100644
index 000000000..b8f5d18e4
--- /dev/null
+++ b/build/cmake/CMakeLists.txt
@@ -0,0 +1,36 @@
+# ################################################################
+# 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.
+# ################################################################
+
+PROJECT(zstd)
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7)
+
+OPTION(ZSTD_LEGACY_SUPPORT "LEGACY SUPPORT" OFF)
+
+IF (ZSTD_LEGACY_SUPPORT)
+ MESSAGE(STATUS "ZSTD_LEGACY_SUPPORT defined!")
+ ADD_DEFINITIONS(-DZSTD_LEGACY_SUPPORT=1)
+ELSE (ZSTD_LEGACY_SUPPORT)
+ MESSAGE(STATUS "ZSTD_LEGACY_SUPPORT not defined!")
+ ADD_DEFINITIONS(-DZSTD_LEGACY_SUPPORT=0)
+ENDIF (ZSTD_LEGACY_SUPPORT)
+
+ADD_SUBDIRECTORY(lib)
+ADD_SUBDIRECTORY(programs)
+ADD_SUBDIRECTORY(tests)
+
+#-----------------------------------------------------------------------------
+# Add extra compilation flags
+#-----------------------------------------------------------------------------
+INCLUDE(CMakeModules/AddExtraCompilationFlags.cmake)
+ADD_EXTRA_COMPILATION_FLAGS()
+
+ADD_CUSTOM_TARGET(clean-all
+ COMMAND ${CMAKE_BUILD_TOOL} clean
+ COMMAND rm -rf ${CMAKE_BINARY_DIR}/
+)
diff --git a/projects/cmake/CMakeModules/AddExtraCompilationFlags.cmake b/build/cmake/CMakeModules/AddExtraCompilationFlags.cmake
similarity index 100%
rename from projects/cmake/CMakeModules/AddExtraCompilationFlags.cmake
rename to build/cmake/CMakeModules/AddExtraCompilationFlags.cmake
diff --git a/projects/cmake/cmake_uninstall.cmake.in b/build/cmake/cmake_uninstall.cmake.in
similarity index 100%
rename from projects/cmake/cmake_uninstall.cmake.in
rename to build/cmake/cmake_uninstall.cmake.in
diff --git a/projects/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt
similarity index 99%
rename from projects/cmake/lib/CMakeLists.txt
rename to build/cmake/lib/CMakeLists.txt
index 36e8afa1d..c984145ba 100644
--- a/projects/cmake/lib/CMakeLists.txt
+++ b/build/cmake/lib/CMakeLists.txt
@@ -108,7 +108,7 @@ IF (ZSTD_LEGACY_SUPPORT)
ENDIF (ZSTD_LEGACY_SUPPORT)
IF (MSVC)
- SET(MSVC_RESOURCE_DIR ${ROOT_DIR}/projects/VS2010/zstdlib)
+ SET(MSVC_RESOURCE_DIR ${ROOT_DIR}/build/VS2010/zstdlib)
SET(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstdlib.rc)
ENDIF (MSVC)
diff --git a/projects/cmake/programs/.gitignore b/build/cmake/programs/.gitignore
similarity index 100%
rename from projects/cmake/programs/.gitignore
rename to build/cmake/programs/.gitignore
diff --git a/projects/cmake/programs/CMakeLists.txt b/build/cmake/programs/CMakeLists.txt
similarity index 100%
rename from projects/cmake/programs/CMakeLists.txt
rename to build/cmake/programs/CMakeLists.txt
diff --git a/projects/cmake/tests/.gitignore b/build/cmake/tests/.gitignore
similarity index 100%
rename from projects/cmake/tests/.gitignore
rename to build/cmake/tests/.gitignore
diff --git a/projects/cmake/tests/CMakeLists.txt b/build/cmake/tests/CMakeLists.txt
similarity index 100%
rename from projects/cmake/tests/CMakeLists.txt
rename to build/cmake/tests/CMakeLists.txt
diff --git a/contrib/pzstd/.gitignore b/contrib/pzstd/.gitignore
new file mode 100644
index 000000000..84e68fb07
--- /dev/null
+++ b/contrib/pzstd/.gitignore
@@ -0,0 +1,2 @@
+# compilation result
+pzstd
diff --git a/contrib/pzstd/ErrorHolder.h b/contrib/pzstd/ErrorHolder.h
new file mode 100644
index 000000000..188badcad
--- /dev/null
+++ b/contrib/pzstd/ErrorHolder.h
@@ -0,0 +1,54 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace pzstd {
+
+// Coordinates graceful shutdown of the pzstd pipeline
+class ErrorHolder {
+ std::atomic error_;
+ std::string message_;
+
+ public:
+ ErrorHolder() : error_(false) {}
+
+ bool hasError() noexcept {
+ return error_.load();
+ }
+
+ void setError(std::string message) noexcept {
+ // Given multiple possibly concurrent calls, exactly one will ever succeed.
+ bool expected = false;
+ if (error_.compare_exchange_strong(expected, true)) {
+ message_ = std::move(message);
+ }
+ }
+
+ bool check(bool predicate, std::string message) noexcept {
+ if (!predicate) {
+ setError(std::move(message));
+ }
+ return !hasError();
+ }
+
+ std::string getError() noexcept {
+ error_.store(false);
+ return std::move(message_);
+ }
+
+ ~ErrorHolder() {
+ assert(!hasError());
+ }
+};
+}
diff --git a/contrib/pzstd/Makefile b/contrib/pzstd/Makefile
new file mode 100644
index 000000000..e30be0bed
--- /dev/null
+++ b/contrib/pzstd/Makefile
@@ -0,0 +1,118 @@
+# ##########################################################################
+# 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.
+# ##########################################################################
+
+ZSTDDIR = ../../lib
+PROGDIR = ../../programs
+
+CPPFLAGS = -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(PROGDIR) -I.
+CXXFLAGS ?= -O3
+CXXFLAGS += -std=c++11
+CXXFLAGS += $(MOREFLAGS)
+FLAGS = $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS)
+
+
+ZSTDCOMMON_FILES := $(ZSTDDIR)/common/*.c
+ZSTDCOMP_FILES := $(ZSTDDIR)/compress/zstd_compress.c $(ZSTDDIR)/compress/fse_compress.c $(ZSTDDIR)/compress/huf_compress.c
+ZSTDDECOMP_FILES := $(ZSTDDIR)/decompress/huf_decompress.c
+ZSTD_FILES := $(ZSTDDECOMP_FILES) $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES)
+
+
+# Define *.exe as extension for Windows systems
+ifneq (,$(filter Windows%,$(OS)))
+EXT =.exe
+else
+EXT =
+endif
+
+.PHONY: default all test clean test32 googletest googletest32
+
+default: pzstd
+
+all: pzstd
+
+
+libzstd.a: $(ZSTD_FILES)
+ $(MAKE) -C $(ZSTDDIR) libzstd
+ @cp $(ZSTDDIR)/libzstd.a .
+
+Pzstd.o: Pzstd.h Pzstd.cpp ErrorHolder.h utils/*.h
+ $(CXX) $(FLAGS) -c Pzstd.cpp -o $@
+
+SkippableFrame.o: SkippableFrame.h SkippableFrame.cpp utils/*.h
+ $(CXX) $(FLAGS) -c SkippableFrame.cpp -o $@
+
+Options.o: Options.h Options.cpp
+ $(CXX) $(FLAGS) -c Options.cpp -o $@
+
+main.o: main.cpp *.h utils/*.h
+ $(CXX) $(FLAGS) -c main.cpp -o $@
+
+pzstd: Pzstd.o SkippableFrame.o Options.o main.o libzstd.a
+ $(CXX) $(FLAGS) $^ -o $@$(EXT) -lpthread
+
+libzstd32.a: $(ZSTD_FILES)
+ $(MAKE) -C $(ZSTDDIR) libzstd MOREFLAGS="-m32"
+ @cp $(ZSTDDIR)/libzstd.a libzstd32.a
+
+Pzstd32.o: Pzstd.h Pzstd.cpp ErrorHolder.h utils/*.h
+ $(CXX) -m32 $(FLAGS) -c Pzstd.cpp -o $@
+
+SkippableFrame32.o: SkippableFrame.h SkippableFrame.cpp utils/*.h
+ $(CXX) -m32 $(FLAGS) -c SkippableFrame.cpp -o $@
+
+Options32.o: Options.h Options.cpp
+ $(CXX) -m32 $(FLAGS) -c Options.cpp -o $@
+
+main32.o: main.cpp *.h utils/*.h
+ $(CXX) -m32 $(FLAGS) -c main.cpp -o $@
+
+pzstd32: Pzstd32.o SkippableFrame32.o Options32.o main32.o libzstd32.a
+ $(CXX) -m32 $(FLAGS) $^ -o $@$(EXT) -lpthread
+
+googletest:
+ @$(RM) -rf googletest
+ @git clone https://github.com/google/googletest
+ @mkdir -p googletest/build
+ @cd googletest/build && cmake .. && make
+
+googletest32:
+ @$(RM) -rf googletest
+ @git clone https://github.com/google/googletest
+ @mkdir -p googletest/build
+ @cd googletest/build && cmake .. -DCMAKE_CXX_FLAGS=-m32 && make
+
+googletest-mingw64:
+ $(RM) -rf googletest
+ git clone https://github.com/google/googletest
+ mkdir -p googletest/build
+ cd googletest/build && cmake -G "MSYS Makefiles" .. && $(MAKE)
+
+test:
+ $(MAKE) libzstd.a
+ $(MAKE) pzstd MOREFLAGS="-Wall -Wextra -pedantic -Werror"
+ $(MAKE) -C utils/test clean
+ $(MAKE) -C utils/test test MOREFLAGS="-Wall -Wextra -pedantic -Werror"
+ $(MAKE) -C test clean
+ $(MAKE) -C test test MOREFLAGS="-Wall -Wextra -pedantic -Werror"
+
+test32:
+ $(MAKE) libzstd.a MOREFLAGS="-m32"
+ $(MAKE) pzstd MOREFLAGS="-m32 -Wall -Wextra -pedantic -Werror"
+ $(MAKE) -C utils/test clean
+ $(MAKE) -C utils/test test MOREFLAGS="-m32 -Wall -Wextra -pedantic -Werror"
+ $(MAKE) -C test clean
+ $(MAKE) -C test test MOREFLAGS="-m32 -Wall -Wextra -pedantic -Werror"
+
+
+clean:
+ $(MAKE) -C $(ZSTDDIR) clean
+ $(MAKE) -C utils/test clean
+ $(MAKE) -C test clean
+ @$(RM) -rf libzstd.a *.o pzstd$(EXT) pzstd32$(EXT)
+ @echo Cleaning completed
diff --git a/contrib/pzstd/Options.cpp b/contrib/pzstd/Options.cpp
new file mode 100644
index 000000000..ece8c0782
--- /dev/null
+++ b/contrib/pzstd/Options.cpp
@@ -0,0 +1,426 @@
+/**
+ * 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.
+ */
+#include "Options.h"
+#include "utils/ScopeGuard.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || \
+ defined(__CYGWIN__)
+#include /* _isatty */
+#define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
+#else
+#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE) || \
+ defined(_POSIX_SOURCE) || \
+ (defined(__APPLE__) && \
+ defined( \
+ __MACH__)) /* https://sourceforge.net/p/predef/wiki/OperatingSystems/ \
+ */
+#include /* isatty */
+#define IS_CONSOLE(stdStream) isatty(fileno(stdStream))
+#else
+#define IS_CONSOLE(stdStream) 0
+#endif
+#endif
+
+namespace pzstd {
+
+namespace {
+unsigned defaultNumThreads() {
+#ifdef PZSTD_NUM_THREADS
+ return PZSTD_NUM_THREADS;
+#else
+ return std::thread::hardware_concurrency();
+#endif
+}
+
+unsigned parseUnsigned(const char **arg) {
+ unsigned result = 0;
+ while (**arg >= '0' && **arg <= '9') {
+ result *= 10;
+ result += **arg - '0';
+ ++(*arg);
+ }
+ return result;
+}
+
+const char *getArgument(const char *options, const char **argv, int &i,
+ int argc) {
+ if (options[1] != 0) {
+ return options + 1;
+ }
+ ++i;
+ if (i == argc) {
+ std::fprintf(stderr, "Option -%c requires an argument, but none provided\n",
+ *options);
+ return nullptr;
+ }
+ return argv[i];
+}
+
+const std::string kZstdExtension = ".zst";
+constexpr char kStdIn[] = "-";
+constexpr char kStdOut[] = "-";
+constexpr unsigned kDefaultCompressionLevel = 3;
+constexpr unsigned kMaxNonUltraCompressionLevel = 19;
+
+#ifdef _WIN32
+const char nullOutput[] = "nul";
+#else
+const char nullOutput[] = "/dev/null";
+#endif
+
+void notSupported(const char *option) {
+ std::fprintf(stderr, "Operation not supported: %s\n", option);
+}
+
+void usage() {
+ std::fprintf(stderr, "Usage:\n");
+ std::fprintf(stderr, " pzstd [args] [FILE(s)]\n");
+ std::fprintf(stderr, "Parallel ZSTD options:\n");
+ std::fprintf(stderr, " -p, --processes # : number of threads to use for (de)compression (default:%d)\n", defaultNumThreads());
+
+ std::fprintf(stderr, "ZSTD options:\n");
+ std::fprintf(stderr, " -# : # compression level (1-%d, default:%d)\n", kMaxNonUltraCompressionLevel, kDefaultCompressionLevel);
+ std::fprintf(stderr, " -d, --decompress : decompression\n");
+ std::fprintf(stderr, " -o file : result stored into `file` (only if 1 input file)\n");
+ std::fprintf(stderr, " -f, --force : overwrite output without prompting\n");
+ std::fprintf(stderr, " --rm : remove source file(s) after successful (de)compression\n");
+ std::fprintf(stderr, " -k, --keep : preserve source file(s) (default)\n");
+ std::fprintf(stderr, " -h, --help : display help and exit\n");
+ std::fprintf(stderr, " -V, --version : display version number and exit\n");
+ std::fprintf(stderr, " -v, --verbose : verbose mode; specify multiple times to increase log level (default:2)\n");
+ std::fprintf(stderr, " -q, --quiet : suppress warnings; specify twice to suppress errors too\n");
+ std::fprintf(stderr, " -c, --stdout : force write to standard output, even if it is the console\n");
+#ifdef UTIL_HAS_CREATEFILELIST
+ std::fprintf(stderr, " -r : operate recursively on directories\n");
+#endif
+ std::fprintf(stderr, " --ultra : enable levels beyond %i, up to %i (requires more memory)\n", kMaxNonUltraCompressionLevel, ZSTD_maxCLevel());
+ std::fprintf(stderr, " -C, --check : integrity check (default)\n");
+ std::fprintf(stderr, " --no-check : no integrity check\n");
+ std::fprintf(stderr, " -t, --test : test compressed file integrity\n");
+ std::fprintf(stderr, " -- : all arguments after \"--\" are treated as files\n");
+}
+} // anonymous namespace
+
+Options::Options()
+ : numThreads(defaultNumThreads()), maxWindowLog(23),
+ compressionLevel(kDefaultCompressionLevel), decompress(false),
+ overwrite(false), keepSource(true), writeMode(WriteMode::Auto),
+ checksum(true), verbosity(2) {}
+
+Options::Status Options::parse(int argc, const char **argv) {
+ bool test = false;
+ bool recursive = false;
+ bool ultra = false;
+ bool forceStdout = false;
+ // Local copy of input files, which are pointers into argv.
+ std::vector localInputFiles;
+ for (int i = 1; i < argc; ++i) {
+ const char *arg = argv[i];
+ // Protect against empty arguments
+ if (arg[0] == 0) {
+ continue;
+ }
+ // Everything after "--" is an input file
+ if (!std::strcmp(arg, "--")) {
+ ++i;
+ std::copy(argv + i, argv + argc, std::back_inserter(localInputFiles));
+ break;
+ }
+ // Long arguments that don't have a short option
+ {
+ bool isLongOption = true;
+ if (!std::strcmp(arg, "--rm")) {
+ keepSource = false;
+ } else if (!std::strcmp(arg, "--ultra")) {
+ ultra = true;
+ maxWindowLog = 0;
+ } else if (!std::strcmp(arg, "--no-check")) {
+ checksum = false;
+ } else if (!std::strcmp(arg, "--sparse")) {
+ writeMode = WriteMode::Sparse;
+ notSupported("Sparse mode");
+ return Status::Failure;
+ } else if (!std::strcmp(arg, "--no-sparse")) {
+ writeMode = WriteMode::Regular;
+ notSupported("Sparse mode");
+ return Status::Failure;
+ } else if (!std::strcmp(arg, "--dictID")) {
+ notSupported(arg);
+ return Status::Failure;
+ } else if (!std::strcmp(arg, "--no-dictID")) {
+ notSupported(arg);
+ return Status::Failure;
+ } else {
+ isLongOption = false;
+ }
+ if (isLongOption) {
+ continue;
+ }
+ }
+ // Arguments with a short option simply set their short option.
+ const char *options = nullptr;
+ if (!std::strcmp(arg, "--processes")) {
+ options = "p";
+ } else if (!std::strcmp(arg, "--version")) {
+ options = "V";
+ } else if (!std::strcmp(arg, "--help")) {
+ options = "h";
+ } else if (!std::strcmp(arg, "--decompress")) {
+ options = "d";
+ } else if (!std::strcmp(arg, "--force")) {
+ options = "f";
+ } else if (!std::strcmp(arg, "--stdout")) {
+ options = "c";
+ } else if (!std::strcmp(arg, "--keep")) {
+ options = "k";
+ } else if (!std::strcmp(arg, "--verbose")) {
+ options = "v";
+ } else if (!std::strcmp(arg, "--quiet")) {
+ options = "q";
+ } else if (!std::strcmp(arg, "--check")) {
+ options = "C";
+ } else if (!std::strcmp(arg, "--test")) {
+ options = "t";
+ } else if (arg[0] == '-' && arg[1] != 0) {
+ options = arg + 1;
+ } else {
+ localInputFiles.emplace_back(arg);
+ continue;
+ }
+ assert(options != nullptr);
+
+ bool finished = false;
+ while (!finished && *options != 0) {
+ // Parse the compression level
+ if (*options >= '0' && *options <= '9') {
+ compressionLevel = parseUnsigned(&options);
+ continue;
+ }
+
+ switch (*options) {
+ case 'h':
+ case 'H':
+ usage();
+ return Status::Message;
+ case 'V':
+ std::fprintf(stderr, "PZSTD version: %s.\n", ZSTD_VERSION_STRING);
+ return Status::Message;
+ case 'p': {
+ finished = true;
+ const char *optionArgument = getArgument(options, argv, i, argc);
+ if (optionArgument == nullptr) {
+ return Status::Failure;
+ }
+ if (*optionArgument < '0' || *optionArgument > '9') {
+ std::fprintf(stderr, "Option -p expects a number, but %s provided\n",
+ optionArgument);
+ return Status::Failure;
+ }
+ numThreads = parseUnsigned(&optionArgument);
+ if (*optionArgument != 0) {
+ std::fprintf(stderr,
+ "Option -p expects a number, but %u%s provided\n",
+ numThreads, optionArgument);
+ return Status::Failure;
+ }
+ break;
+ }
+ case 'o': {
+ finished = true;
+ const char *optionArgument = getArgument(options, argv, i, argc);
+ if (optionArgument == nullptr) {
+ return Status::Failure;
+ }
+ outputFile = optionArgument;
+ break;
+ }
+ case 'C':
+ checksum = true;
+ break;
+ case 'k':
+ keepSource = true;
+ break;
+ case 'd':
+ decompress = true;
+ break;
+ case 'f':
+ overwrite = true;
+ forceStdout = true;
+ break;
+ case 't':
+ test = true;
+ decompress = true;
+ break;
+#ifdef UTIL_HAS_CREATEFILELIST
+ case 'r':
+ recursive = true;
+ break;
+#endif
+ case 'c':
+ outputFile = kStdOut;
+ forceStdout = true;
+ break;
+ case 'v':
+ ++verbosity;
+ break;
+ case 'q':
+ --verbosity;
+ // Ignore them for now
+ break;
+ // Unsupported options from Zstd
+ case 'D':
+ case 's':
+ notSupported("Zstd dictionaries.");
+ return Status::Failure;
+ case 'b':
+ case 'e':
+ case 'i':
+ case 'B':
+ notSupported("Zstd benchmarking options.");
+ return Status::Failure;
+ default:
+ std::fprintf(stderr, "Invalid argument: %s\n", arg);
+ return Status::Failure;
+ }
+ if (!finished) {
+ ++options;
+ }
+ } // while (*options != 0);
+ } // for (int i = 1; i < argc; ++i);
+
+ // Input file defaults to standard input if not provided.
+ if (localInputFiles.empty()) {
+ localInputFiles.emplace_back(kStdIn);
+ }
+
+ // Check validity of input files
+ if (localInputFiles.size() > 1) {
+ const auto it = std::find(localInputFiles.begin(), localInputFiles.end(),
+ std::string{kStdIn});
+ if (it != localInputFiles.end()) {
+ std::fprintf(
+ stderr,
+ "Cannot specify standard input when handling multiple files\n");
+ return Status::Failure;
+ }
+ }
+ if (localInputFiles.size() > 1 || recursive) {
+ if (!outputFile.empty() && outputFile != nullOutput) {
+ std::fprintf(
+ stderr,
+ "Cannot specify an output file when handling multiple inputs\n");
+ return Status::Failure;
+ }
+ }
+
+ // Translate input files/directories into files to (de)compress
+ if (recursive) {
+ char *scratchBuffer = nullptr;
+ unsigned numFiles = 0;
+ const char **files =
+ UTIL_createFileList(localInputFiles.data(), localInputFiles.size(),
+ &scratchBuffer, &numFiles);
+ if (files == nullptr) {
+ std::fprintf(stderr, "Error traversing directories\n");
+ return Status::Failure;
+ }
+ auto guard =
+ makeScopeGuard([&] { UTIL_freeFileList(files, scratchBuffer); });
+ if (numFiles == 0) {
+ std::fprintf(stderr, "No files found\n");
+ return Status::Failure;
+ }
+ inputFiles.resize(numFiles);
+ std::copy(files, files + numFiles, inputFiles.begin());
+ } else {
+ inputFiles.resize(localInputFiles.size());
+ std::copy(localInputFiles.begin(), localInputFiles.end(),
+ inputFiles.begin());
+ }
+ localInputFiles.clear();
+ assert(!inputFiles.empty());
+
+ // If reading from standard input, default to standard output
+ if (inputFiles[0] == kStdIn && outputFile.empty()) {
+ assert(inputFiles.size() == 1);
+ outputFile = "-";
+ }
+
+ if (inputFiles[0] == kStdIn && IS_CONSOLE(stdin)) {
+ assert(inputFiles.size() == 1);
+ std::fprintf(stderr, "Cannot read input from interactive console\n");
+ return Status::Failure;
+ }
+ if (outputFile == "-" && IS_CONSOLE(stdout) && !(forceStdout && decompress)) {
+ std::fprintf(stderr, "Will not write to console stdout unless -c or -f is "
+ "specified and decompressing\n");
+ return Status::Failure;
+ }
+
+ // Check compression level
+ {
+ unsigned maxCLevel =
+ ultra ? ZSTD_maxCLevel() : kMaxNonUltraCompressionLevel;
+ if (compressionLevel > maxCLevel || compressionLevel == 0) {
+ std::fprintf(stderr, "Invalid compression level %u.\n", compressionLevel);
+ return Status::Failure;
+ }
+ }
+
+ // Check that numThreads is set
+ if (numThreads == 0) {
+ std::fprintf(stderr, "Invalid arguments: # of threads not specified "
+ "and unable to determine hardware concurrency.\n");
+ return Status::Failure;
+ }
+
+ // Modify verbosity
+ // If we are piping input and output, turn off interaction
+ if (inputFiles[0] == kStdIn && outputFile == kStdOut && verbosity == 2) {
+ verbosity = 1;
+ }
+ // If we are in multi-file mode, turn off interaction
+ if (inputFiles.size() > 1 && verbosity == 2) {
+ verbosity = 1;
+ }
+
+ // Set options for test mode
+ if (test) {
+ outputFile = nullOutput;
+ keepSource = true;
+ }
+ return Status::Success;
+}
+
+std::string Options::getOutputFile(const std::string &inputFile) const {
+ if (!outputFile.empty()) {
+ return outputFile;
+ }
+ // Attempt to add/remove zstd extension from the input file
+ if (decompress) {
+ int stemSize = inputFile.size() - kZstdExtension.size();
+ if (stemSize > 0 && inputFile.substr(stemSize) == kZstdExtension) {
+ return inputFile.substr(0, stemSize);
+ } else {
+ return "";
+ }
+ } else {
+ return inputFile + kZstdExtension;
+ }
+}
+}
diff --git a/contrib/pzstd/Options.h b/contrib/pzstd/Options.h
new file mode 100644
index 000000000..97c3885ec
--- /dev/null
+++ b/contrib/pzstd/Options.h
@@ -0,0 +1,68 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#define ZSTD_STATIC_LINKING_ONLY
+#include "zstd.h"
+#undef ZSTD_STATIC_LINKING_ONLY
+
+#include
+#include
+#include
+
+namespace pzstd {
+
+struct Options {
+ enum class WriteMode { Regular, Auto, Sparse };
+
+ unsigned numThreads;
+ unsigned maxWindowLog;
+ unsigned compressionLevel;
+ bool decompress;
+ std::vector inputFiles;
+ std::string outputFile;
+ bool overwrite;
+ bool keepSource;
+ WriteMode writeMode;
+ bool checksum;
+ int verbosity;
+
+ enum class Status {
+ Success, // Successfully parsed options
+ Failure, // Failure to parse options
+ Message // Options specified to print a message (e.g. "-h")
+ };
+
+ Options();
+ Options(unsigned numThreads, unsigned maxWindowLog, unsigned compressionLevel,
+ bool decompress, std::vector inputFiles,
+ std::string outputFile, bool overwrite, bool keepSource,
+ WriteMode writeMode, bool checksum, int verbosity)
+ : numThreads(numThreads), maxWindowLog(maxWindowLog),
+ compressionLevel(compressionLevel), decompress(decompress),
+ inputFiles(std::move(inputFiles)), outputFile(std::move(outputFile)),
+ overwrite(overwrite), keepSource(keepSource), writeMode(writeMode),
+ checksum(checksum), verbosity(verbosity) {}
+
+ Status parse(int argc, const char **argv);
+
+ ZSTD_parameters determineParameters() const {
+ ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, 0);
+ params.fParams.contentSizeFlag = 1;
+ params.fParams.checksumFlag = checksum;
+ if (maxWindowLog != 0 && params.cParams.windowLog > maxWindowLog) {
+ params.cParams.windowLog = maxWindowLog;
+ params.cParams = ZSTD_adjustCParams(params.cParams, 0, 0);
+ }
+ return params;
+ }
+
+ std::string getOutputFile(const std::string &inputFile) const;
+};
+}
diff --git a/contrib/pzstd/Pzstd.cpp b/contrib/pzstd/Pzstd.cpp
new file mode 100644
index 000000000..e0826b9d8
--- /dev/null
+++ b/contrib/pzstd/Pzstd.cpp
@@ -0,0 +1,641 @@
+/**
+ * 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.
+ */
+#include "Pzstd.h"
+#include "SkippableFrame.h"
+#include "utils/FileSystem.h"
+#include "utils/Range.h"
+#include "utils/ScopeGuard.h"
+#include "utils/ThreadPool.h"
+#include "utils/WorkQueue.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
+# include /* _O_BINARY */
+# include /* _setmode, _isatty */
+# define SET_BINARY_MODE(file) { if (_setmode(_fileno(file), _O_BINARY) == -1) perror("Cannot set _O_BINARY"); }
+#else
+# include /* isatty */
+# define SET_BINARY_MODE(file)
+#endif
+
+namespace pzstd {
+
+namespace {
+#ifdef _WIN32
+const std::string nullOutput = "nul";
+#else
+const std::string nullOutput = "/dev/null";
+#endif
+}
+
+using std::size_t;
+
+static std::uintmax_t fileSizeOrZero(const std::string &file) {
+ if (file == "-") {
+ return 0;
+ }
+ std::error_code ec;
+ auto size = file_size(file, ec);
+ if (ec) {
+ size = 0;
+ }
+ return size;
+}
+
+static std::uint64_t handleOneInput(const Options &options,
+ const std::string &inputFile,
+ FILE* inputFd,
+ const std::string &outputFile,
+ FILE* outputFd,
+ ErrorHolder &errorHolder) {
+ auto inputSize = fileSizeOrZero(inputFile);
+ // WorkQueue outlives ThreadPool so in the case of error we are certain
+ // we don't accidently try to call push() on it after it is destroyed.
+ WorkQueue> outs{options.numThreads + 1};
+ std::uint64_t bytesRead;
+ std::uint64_t bytesWritten;
+ {
+ // Initialize the thread pool with numThreads + 1
+ // We add one because the read thread spends most of its time waiting.
+ // This also sets the minimum number of threads to 2, so the algorithm
+ // doesn't deadlock.
+ ThreadPool executor(options.numThreads + 1);
+ if (!options.decompress) {
+ // Add a job that reads the input and starts all the compression jobs
+ executor.add(
+ [&errorHolder, &outs, &executor, inputFd, inputSize, &options,
+ &bytesRead] {
+ bytesRead = asyncCompressChunks(
+ errorHolder,
+ outs,
+ executor,
+ inputFd,
+ inputSize,
+ options.numThreads,
+ options.determineParameters());
+ });
+ // Start writing
+ bytesWritten = writeFile(errorHolder, outs, outputFd, options.decompress,
+ options.verbosity);
+ } else {
+ // Add a job that reads the input and starts all the decompression jobs
+ executor.add([&errorHolder, &outs, &executor, inputFd, &bytesRead] {
+ bytesRead = asyncDecompressFrames(errorHolder, outs, executor, inputFd);
+ });
+ // Start writing
+ bytesWritten = writeFile(errorHolder, outs, outputFd, options.decompress,
+ options.verbosity);
+ }
+ }
+ if (options.verbosity > 1 && !errorHolder.hasError()) {
+ std::string inputFileName = inputFile == "-" ? "stdin" : inputFile;
+ std::string outputFileName = outputFile == "-" ? "stdout" : outputFile;
+ if (!options.decompress) {
+ double ratio = static_cast(bytesWritten) /
+ static_cast(bytesRead + !bytesRead);
+ std::fprintf(stderr, "%-20s :%6.2f%% (%6llu => %6llu bytes, %s)\n",
+ inputFileName.c_str(), ratio * 100, bytesRead, bytesWritten,
+ outputFileName.c_str());
+ } else {
+ std::fprintf(stderr, "%-20s: %llu bytes \n",
+ inputFileName.c_str(),bytesWritten);
+ }
+ }
+ return bytesWritten;
+}
+
+static FILE *openInputFile(const std::string &inputFile,
+ ErrorHolder &errorHolder) {
+ if (inputFile == "-") {
+ SET_BINARY_MODE(stdin);
+ return stdin;
+ }
+ // Check if input file is a directory
+ {
+ std::error_code ec;
+ if (is_directory(inputFile, ec)) {
+ errorHolder.setError("Output file is a directory -- ignored");
+ return nullptr;
+ }
+ }
+ auto inputFd = std::fopen(inputFile.c_str(), "rb");
+ if (!errorHolder.check(inputFd != nullptr, "Failed to open input file")) {
+ return nullptr;
+ }
+ return inputFd;
+}
+
+static FILE *openOutputFile(const Options &options,
+ const std::string &outputFile,
+ ErrorHolder &errorHolder) {
+ if (outputFile == "-") {
+ SET_BINARY_MODE(stdout);
+ return stdout;
+ }
+ // Check if the output file exists and then open it
+ if (!options.overwrite && outputFile != nullOutput) {
+ auto outputFd = std::fopen(outputFile.c_str(), "rb");
+ if (outputFd != nullptr) {
+ std::fclose(outputFd);
+ if (options.verbosity <= 1) {
+ errorHolder.setError("Output file exists");
+ return nullptr;
+ }
+ std::fprintf(
+ stderr,
+ "pzstd: %s already exists; do you wish to overwrite (y/n) ? ",
+ outputFile.c_str());
+ int c = getchar();
+ if (c != 'y' && c != 'Y') {
+ errorHolder.setError("Not overwritten");
+ return nullptr;
+ }
+ }
+ }
+ auto outputFd = std::fopen(outputFile.c_str(), "wb");
+ if (!errorHolder.check(
+ outputFd != nullptr, "Failed to open output file")) {
+ return 0;
+ }
+ return outputFd;
+}
+
+int pzstdMain(const Options &options) {
+ int returnCode = 0;
+ for (const auto& input : options.inputFiles) {
+ // Setup the error holder
+ ErrorHolder errorHolder;
+ auto printErrorGuard = makeScopeGuard([&] {
+ if (errorHolder.hasError()) {
+ returnCode = 1;
+ if (options.verbosity > 0) {
+ std::fprintf(stderr, "pzstd: %s: %s.\n", input.c_str(),
+ errorHolder.getError().c_str());
+ }
+ } else {
+
+ }
+ });
+ // Open the input file
+ auto inputFd = openInputFile(input, errorHolder);
+ if (inputFd == nullptr) {
+ continue;
+ }
+ auto closeInputGuard = makeScopeGuard([&] { std::fclose(inputFd); });
+ // Open the output file
+ auto outputFile = options.getOutputFile(input);
+ if (!errorHolder.check(outputFile != "",
+ "Input file does not have extension .zst")) {
+ continue;
+ }
+ auto outputFd = openOutputFile(options, outputFile, errorHolder);
+ if (outputFd == nullptr) {
+ continue;
+ }
+ auto closeOutputGuard = makeScopeGuard([&] { std::fclose(outputFd); });
+ // (de)compress the file
+ handleOneInput(options, input, inputFd, outputFile, outputFd, errorHolder);
+ if (errorHolder.hasError()) {
+ continue;
+ }
+ // Delete the input file if necessary
+ if (!options.keepSource) {
+ // Be sure that we are done and have written everything before we delete
+ if (!errorHolder.check(std::fclose(inputFd) == 0,
+ "Failed to close input file")) {
+ continue;
+ }
+ closeInputGuard.dismiss();
+ if (!errorHolder.check(std::fclose(outputFd) == 0,
+ "Failed to close output file")) {
+ continue;
+ }
+ closeOutputGuard.dismiss();
+ if (std::remove(input.c_str()) != 0) {
+ errorHolder.setError("Failed to remove input file");
+ continue;
+ }
+ }
+ }
+ // Returns 1 if any of the files failed to (de)compress.
+ return returnCode;
+}
+
+/// Construct a `ZSTD_inBuffer` that points to the data in `buffer`.
+static ZSTD_inBuffer makeZstdInBuffer(const Buffer& buffer) {
+ return ZSTD_inBuffer{buffer.data(), buffer.size(), 0};
+}
+
+/**
+ * Advance `buffer` and `inBuffer` by the amount of data read, as indicated by
+ * `inBuffer.pos`.
+ */
+void advance(Buffer& buffer, ZSTD_inBuffer& inBuffer) {
+ auto pos = inBuffer.pos;
+ inBuffer.src = static_cast(inBuffer.src) + pos;
+ inBuffer.size -= pos;
+ inBuffer.pos = 0;
+ return buffer.advance(pos);
+}
+
+/// Construct a `ZSTD_outBuffer` that points to the data in `buffer`.
+static ZSTD_outBuffer makeZstdOutBuffer(Buffer& buffer) {
+ return ZSTD_outBuffer{buffer.data(), buffer.size(), 0};
+}
+
+/**
+ * Split `buffer` and advance `outBuffer` by the amount of data written, as
+ * indicated by `outBuffer.pos`.
+ */
+Buffer split(Buffer& buffer, ZSTD_outBuffer& outBuffer) {
+ auto pos = outBuffer.pos;
+ outBuffer.dst = static_cast(outBuffer.dst) + pos;
+ outBuffer.size -= pos;
+ outBuffer.pos = 0;
+ return buffer.splitAt(pos);
+}
+
+/**
+ * Stream chunks of input from `in`, compress it, and stream it out to `out`.
+ *
+ * @param errorHolder Used to report errors and check if an error occured
+ * @param in Queue that we `pop()` input buffers from
+ * @param out Queue that we `push()` compressed output buffers to
+ * @param maxInputSize An upper bound on the size of the input
+ * @param parameters The zstd parameters to use for compression
+ */
+static void compress(
+ ErrorHolder& errorHolder,
+ std::shared_ptr in,
+ std::shared_ptr out,
+ size_t maxInputSize,
+ ZSTD_parameters parameters) {
+ auto guard = makeScopeGuard([&] { out->finish(); });
+ // Initialize the CCtx
+ std::unique_ptr ctx(
+ ZSTD_createCStream(), ZSTD_freeCStream);
+ if (!errorHolder.check(ctx != nullptr, "Failed to allocate ZSTD_CStream")) {
+ return;
+ }
+ {
+ auto err = ZSTD_initCStream_advanced(ctx.get(), nullptr, 0, parameters, 0);
+ if (!errorHolder.check(!ZSTD_isError(err), ZSTD_getErrorName(err))) {
+ return;
+ }
+ }
+
+ // Allocate space for the result
+ auto outBuffer = Buffer(ZSTD_compressBound(maxInputSize));
+ auto zstdOutBuffer = makeZstdOutBuffer(outBuffer);
+ {
+ Buffer inBuffer;
+ // Read a buffer in from the input queue
+ while (in->pop(inBuffer) && !errorHolder.hasError()) {
+ auto zstdInBuffer = makeZstdInBuffer(inBuffer);
+ // Compress the whole buffer and send it to the output queue
+ while (!inBuffer.empty() && !errorHolder.hasError()) {
+ if (!errorHolder.check(
+ !outBuffer.empty(), "ZSTD_compressBound() was too small")) {
+ return;
+ }
+ // Compress
+ auto err =
+ ZSTD_compressStream(ctx.get(), &zstdOutBuffer, &zstdInBuffer);
+ if (!errorHolder.check(!ZSTD_isError(err), ZSTD_getErrorName(err))) {
+ return;
+ }
+ // Split the compressed data off outBuffer and pass to the output queue
+ out->push(split(outBuffer, zstdOutBuffer));
+ // Forget about the data we already compressed
+ advance(inBuffer, zstdInBuffer);
+ }
+ }
+ }
+ // Write the epilog
+ size_t bytesLeft;
+ do {
+ if (!errorHolder.check(
+ !outBuffer.empty(), "ZSTD_compressBound() was too small")) {
+ return;
+ }
+ bytesLeft = ZSTD_endStream(ctx.get(), &zstdOutBuffer);
+ if (!errorHolder.check(
+ !ZSTD_isError(bytesLeft), ZSTD_getErrorName(bytesLeft))) {
+ return;
+ }
+ out->push(split(outBuffer, zstdOutBuffer));
+ } while (bytesLeft != 0 && !errorHolder.hasError());
+}
+
+/**
+ * Calculates how large each independently compressed frame should be.
+ *
+ * @param size The size of the source if known, 0 otherwise
+ * @param numThreads The number of threads available to run compression jobs on
+ * @param params The zstd parameters to be used for compression
+ */
+static size_t calculateStep(
+ std::uintmax_t size,
+ size_t numThreads,
+ const ZSTD_parameters ¶ms) {
+ size_t step = size_t{1} << (params.cParams.windowLog + 2);
+ // If file size is known, see if a smaller step will spread work more evenly
+ if (size != 0) {
+ const std::uintmax_t newStep = size / numThreads;
+ if (newStep != 0 && newStep <= std::numeric_limits::max()) {
+ step = std::min(step, static_cast(newStep));
+ }
+ }
+ return step;
+}
+
+namespace {
+enum class FileStatus { Continue, Done, Error };
+/// Determines the status of the file descriptor `fd`.
+FileStatus fileStatus(FILE* fd) {
+ if (std::feof(fd)) {
+ return FileStatus::Done;
+ } else if (std::ferror(fd)) {
+ return FileStatus::Error;
+ }
+ return FileStatus::Continue;
+}
+} // anonymous namespace
+
+/**
+ * Reads `size` data in chunks of `chunkSize` and puts it into `queue`.
+ * Will read less if an error or EOF occurs.
+ * Returns the status of the file after all of the reads have occurred.
+ */
+static FileStatus
+readData(BufferWorkQueue& queue, size_t chunkSize, size_t size, FILE* fd,
+ std::uint64_t *totalBytesRead) {
+ Buffer buffer(size);
+ while (!buffer.empty()) {
+ auto bytesRead =
+ std::fread(buffer.data(), 1, std::min(chunkSize, buffer.size()), fd);
+ *totalBytesRead += bytesRead;
+ queue.push(buffer.splitAt(bytesRead));
+ auto status = fileStatus(fd);
+ if (status != FileStatus::Continue) {
+ return status;
+ }
+ }
+ return FileStatus::Continue;
+}
+
+std::uint64_t asyncCompressChunks(
+ ErrorHolder& errorHolder,
+ WorkQueue>& chunks,
+ ThreadPool& executor,
+ FILE* fd,
+ std::uintmax_t size,
+ size_t numThreads,
+ ZSTD_parameters params) {
+ auto chunksGuard = makeScopeGuard([&] { chunks.finish(); });
+ std::uint64_t bytesRead = 0;
+
+ // Break the input up into chunks of size `step` and compress each chunk
+ // independently.
+ size_t step = calculateStep(size, numThreads, params);
+ auto status = FileStatus::Continue;
+ while (status == FileStatus::Continue && !errorHolder.hasError()) {
+ // Make a new input queue that we will put the chunk's input data into.
+ auto in = std::make_shared();
+ auto inGuard = makeScopeGuard([&] { in->finish(); });
+ // Make a new output queue that compress will put the compressed data into.
+ auto out = std::make_shared();
+ // Start compression in the thread pool
+ executor.add([&errorHolder, in, out, step, params] {
+ return compress(
+ errorHolder, std::move(in), std::move(out), step, params);
+ });
+ // Pass the output queue to the writer thread.
+ chunks.push(std::move(out));
+ // Fill the input queue for the compression job we just started
+ status = readData(*in, ZSTD_CStreamInSize(), step, fd, &bytesRead);
+ }
+ errorHolder.check(status != FileStatus::Error, "Error reading input");
+ return bytesRead;
+}
+
+/**
+ * Decompress a frame, whose data is streamed into `in`, and stream the output
+ * to `out`.
+ *
+ * @param errorHolder Used to report errors and check if an error occured
+ * @param in Queue that we `pop()` input buffers from. It contains
+ * exactly one compressed frame.
+ * @param out Queue that we `push()` decompressed output buffers to
+ */
+static void decompress(
+ ErrorHolder& errorHolder,
+ std::shared_ptr in,
+ std::shared_ptr out) {
+ auto guard = makeScopeGuard([&] { out->finish(); });
+ // Initialize the DCtx
+ std::unique_ptr ctx(
+ ZSTD_createDStream(), ZSTD_freeDStream);
+ if (!errorHolder.check(ctx != nullptr, "Failed to allocate ZSTD_DStream")) {
+ return;
+ }
+ {
+ auto err = ZSTD_initDStream(ctx.get());
+ if (!errorHolder.check(!ZSTD_isError(err), ZSTD_getErrorName(err))) {
+ return;
+ }
+ }
+
+ const size_t outSize = ZSTD_DStreamOutSize();
+ Buffer inBuffer;
+ size_t returnCode = 0;
+ // Read a buffer in from the input queue
+ while (in->pop(inBuffer) && !errorHolder.hasError()) {
+ auto zstdInBuffer = makeZstdInBuffer(inBuffer);
+ // Decompress the whole buffer and send it to the output queue
+ while (!inBuffer.empty() && !errorHolder.hasError()) {
+ // Allocate a buffer with at least outSize bytes.
+ Buffer outBuffer(outSize);
+ auto zstdOutBuffer = makeZstdOutBuffer(outBuffer);
+ // Decompress
+ returnCode =
+ ZSTD_decompressStream(ctx.get(), &zstdOutBuffer, &zstdInBuffer);
+ if (!errorHolder.check(
+ !ZSTD_isError(returnCode), ZSTD_getErrorName(returnCode))) {
+ return;
+ }
+ // Pass the buffer with the decompressed data to the output queue
+ out->push(split(outBuffer, zstdOutBuffer));
+ // Advance past the input we already read
+ advance(inBuffer, zstdInBuffer);
+ if (returnCode == 0) {
+ // The frame is over, prepare to (maybe) start a new frame
+ ZSTD_initDStream(ctx.get());
+ }
+ }
+ }
+ if (!errorHolder.check(returnCode <= 1, "Incomplete block")) {
+ return;
+ }
+ // We've given ZSTD_decompressStream all of our data, but there may still
+ // be data to read.
+ while (returnCode == 1) {
+ // Allocate a buffer with at least outSize bytes.
+ Buffer outBuffer(outSize);
+ auto zstdOutBuffer = makeZstdOutBuffer(outBuffer);
+ // Pass in no input.
+ ZSTD_inBuffer zstdInBuffer{nullptr, 0, 0};
+ // Decompress
+ returnCode =
+ ZSTD_decompressStream(ctx.get(), &zstdOutBuffer, &zstdInBuffer);
+ if (!errorHolder.check(
+ !ZSTD_isError(returnCode), ZSTD_getErrorName(returnCode))) {
+ return;
+ }
+ // Pass the buffer with the decompressed data to the output queue
+ out->push(split(outBuffer, zstdOutBuffer));
+ }
+}
+
+std::uint64_t asyncDecompressFrames(
+ ErrorHolder& errorHolder,
+ WorkQueue>& frames,
+ ThreadPool& executor,
+ FILE* fd) {
+ auto framesGuard = makeScopeGuard([&] { frames.finish(); });
+ std::uint64_t totalBytesRead = 0;
+
+ // Split the source up into its component frames.
+ // If we find our recognized skippable frame we know the next frames size
+ // which means that we can decompress each standard frame in independently.
+ // Otherwise, we will decompress using only one decompression task.
+ const size_t chunkSize = ZSTD_DStreamInSize();
+ auto status = FileStatus::Continue;
+ while (status == FileStatus::Continue && !errorHolder.hasError()) {
+ // Make a new input queue that we will put the frames's bytes into.
+ auto in = std::make_shared();
+ auto inGuard = makeScopeGuard([&] { in->finish(); });
+ // Make a output queue that decompress will put the decompressed data into
+ auto out = std::make_shared();
+
+ size_t frameSize;
+ {
+ // Calculate the size of the next frame.
+ // frameSize is 0 if the frame info can't be decoded.
+ Buffer buffer(SkippableFrame::kSize);
+ auto bytesRead = std::fread(buffer.data(), 1, buffer.size(), fd);
+ totalBytesRead += bytesRead;
+ status = fileStatus(fd);
+ if (bytesRead == 0 && status != FileStatus::Continue) {
+ break;
+ }
+ buffer.subtract(buffer.size() - bytesRead);
+ frameSize = SkippableFrame::tryRead(buffer.range());
+ in->push(std::move(buffer));
+ }
+ if (frameSize == 0) {
+ // We hit a non SkippableFrame, so this will be the last job.
+ // Make sure that we don't use too much memory
+ in->setMaxSize(64);
+ out->setMaxSize(64);
+ }
+ // Start decompression in the thread pool
+ executor.add([&errorHolder, in, out] {
+ return decompress(errorHolder, std::move(in), std::move(out));
+ });
+ // Pass the output queue to the writer thread
+ frames.push(std::move(out));
+ if (frameSize == 0) {
+ // We hit a non SkippableFrame ==> not compressed by pzstd or corrupted
+ // Pass the rest of the source to this decompression task
+ while (status == FileStatus::Continue && !errorHolder.hasError()) {
+ status = readData(*in, chunkSize, chunkSize, fd, &totalBytesRead);
+ }
+ break;
+ }
+ // Fill the input queue for the decompression job we just started
+ status = readData(*in, chunkSize, frameSize, fd, &totalBytesRead);
+ }
+ errorHolder.check(status != FileStatus::Error, "Error reading input");
+ return totalBytesRead;
+}
+
+/// Write `data` to `fd`, returns true iff success.
+static bool writeData(ByteRange data, FILE* fd) {
+ while (!data.empty()) {
+ data.advance(std::fwrite(data.begin(), 1, data.size(), fd));
+ if (std::ferror(fd)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void updateWritten(int verbosity, std::uint64_t bytesWritten) {
+ if (verbosity <= 1) {
+ return;
+ }
+ using Clock = std::chrono::system_clock;
+ static Clock::time_point then;
+ constexpr std::chrono::milliseconds refreshRate{150};
+
+ auto now = Clock::now();
+ if (now - then > refreshRate) {
+ then = now;
+ std::fprintf(stderr, "\rWritten: %u MB ",
+ static_cast(bytesWritten >> 20));
+ }
+}
+
+std::uint64_t writeFile(
+ ErrorHolder& errorHolder,
+ WorkQueue>& outs,
+ FILE* outputFd,
+ bool decompress,
+ int verbosity) {
+ auto lineClearGuard = makeScopeGuard([verbosity] {
+ if (verbosity > 1) {
+ std::fprintf(stderr, "\r%79s\r", "");
+ }
+ });
+ std::uint64_t bytesWritten = 0;
+ std::shared_ptr out;
+ // Grab the output queue for each decompression job (in order).
+ while (outs.pop(out) && !errorHolder.hasError()) {
+ if (!decompress) {
+ // If we are compressing and want to write skippable frames we can't
+ // start writing before compression is done because we need to know the
+ // compressed size.
+ // Wait for the compressed size to be available and write skippable frame
+ SkippableFrame frame(out->size());
+ if (!writeData(frame.data(), outputFd)) {
+ errorHolder.setError("Failed to write output");
+ return bytesWritten;
+ }
+ bytesWritten += frame.kSize;
+ }
+ // For each chunk of the frame: Pop it from the queue and write it
+ Buffer buffer;
+ while (out->pop(buffer) && !errorHolder.hasError()) {
+ if (!writeData(buffer.range(), outputFd)) {
+ errorHolder.setError("Failed to write output");
+ return bytesWritten;
+ }
+ bytesWritten += buffer.size();
+ updateWritten(verbosity, bytesWritten);
+ }
+ }
+ return bytesWritten;
+}
+}
diff --git a/contrib/pzstd/Pzstd.h b/contrib/pzstd/Pzstd.h
new file mode 100644
index 000000000..fe44ccfde
--- /dev/null
+++ b/contrib/pzstd/Pzstd.h
@@ -0,0 +1,96 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include "ErrorHolder.h"
+#include "Options.h"
+#include "utils/Buffer.h"
+#include "utils/Range.h"
+#include "utils/ThreadPool.h"
+#include "utils/WorkQueue.h"
+#define ZSTD_STATIC_LINKING_ONLY
+#include "zstd.h"
+#undef ZSTD_STATIC_LINKING_ONLY
+
+#include
+#include
+#include
+
+namespace pzstd {
+/**
+ * Runs pzstd with `options` and returns the number of bytes written.
+ * An error occurred if `errorHandler.hasError()`.
+ *
+ * @param options The pzstd options to use for (de)compression
+ * @returns 0 upon success and non-zero on failure.
+ */
+int pzstdMain(const Options& options);
+
+/**
+ * Streams input from `fd`, breaks input up into chunks, and compresses each
+ * chunk independently. Output of each chunk gets streamed to a queue, and
+ * the output queues get put into `chunks` in order.
+ *
+ * @param errorHolder Used to report errors and coordinate early shutdown
+ * @param chunks Each compression jobs output queue gets `pushed()` here
+ * as soon as it is available
+ * @param executor The thread pool to run compression jobs in
+ * @param fd The input file descriptor
+ * @param size The size of the input file if known, 0 otherwise
+ * @param numThreads The number of threads in the thread pool
+ * @param parameters The zstd parameters to use for compression
+ * @returns The number of bytes read from the file
+ */
+std::uint64_t asyncCompressChunks(
+ ErrorHolder& errorHolder,
+ WorkQueue>& chunks,
+ ThreadPool& executor,
+ FILE* fd,
+ std::uintmax_t size,
+ std::size_t numThreads,
+ ZSTD_parameters parameters);
+
+/**
+ * Streams input from `fd`. If pzstd headers are available it breaks the input
+ * up into independent frames. It sends each frame to an independent
+ * decompression job. Output of each frame gets streamed to a queue, and
+ * the output queues get put into `frames` in order.
+ *
+ * @param errorHolder Used to report errors and coordinate early shutdown
+ * @param frames Each decompression jobs output queue gets `pushed()` here
+ * as soon as it is available
+ * @param executor The thread pool to run compression jobs in
+ * @param fd The input file descriptor
+ * @returns The number of bytes read from the file
+ */
+std::uint64_t asyncDecompressFrames(
+ ErrorHolder& errorHolder,
+ WorkQueue>& frames,
+ ThreadPool& executor,
+ FILE* fd);
+
+/**
+ * Streams input in from each queue in `outs` in order, and writes the data to
+ * `outputFd`.
+ *
+ * @param errorHolder Used to report errors and coordinate early exit
+ * @param outs A queue of output queues, one for each
+ * (de)compression job.
+ * @param outputFd The file descriptor to write to
+ * @param decompress Are we decompressing?
+ * @param verbosity The verbosity level to log at
+ * @returns The number of bytes written
+ */
+std::uint64_t writeFile(
+ ErrorHolder& errorHolder,
+ WorkQueue>& outs,
+ FILE* outputFd,
+ bool decompress,
+ int verbosity);
+}
diff --git a/contrib/pzstd/README.md b/contrib/pzstd/README.md
new file mode 100644
index 000000000..05ceb5599
--- /dev/null
+++ b/contrib/pzstd/README.md
@@ -0,0 +1,55 @@
+# Parallel Zstandard (PZstandard)
+
+Parallel Zstandard is a Pigz-like tool for Zstandard.
+It provides Zstandard format compatible compression and decompression that is able to utilize multiple cores.
+It breaks the input up into equal sized chunks and compresses each chunk independently into a Zstandard frame.
+It then concatenates the frames together to produce the final compressed output.
+Pzstandard will write a 12 byte header for each frame that is a skippable frame in the Zstandard format, which tells PZstandard the size of the next compressed frame.
+PZstandard supports parallel decompression of files compressed with PZstandard.
+When decompressing files compressed with Zstandard, PZstandard does IO in one thread, and decompression in another.
+
+## Usage
+
+PZstandard supports the same command line interface as Zstandard, but also provies the `-p` option to specify the number of threads.
+Dictionary mode is not currently supported.
+
+Basic usage
+
+ pzstd input-file -o output-file -p num-threads -# # Compression
+ pzstd -d input-file -o output-file -p num-threads # Decompression
+
+PZstandard also supports piping and fifo pipes
+
+ cat input-file | pzstd -p num-threads -# -c > /dev/null
+
+For more options
+
+ pzstd --help
+
+PZstandard tries to pick a smart default number of threads if not specified (displayed in `pzstd --help`).
+If this number is not suitable, during compilation you can define `PZSTD_NUM_THREADS` to the number of threads you prefer.
+
+## Benchmarks
+
+As a reference, PZstandard and Pigz were compared on an Intel Core i7 @ 3.1 GHz, each using 4 threads, with the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia).
+
+Compression Speed vs Ratio with 4 Threads | Decompression Speed with 4 Threads
+------------------------------------------|-----------------------------------
+ | 
+
+The test procedure was to run each of the following commands 2 times for each compression level, and take the minimum time.
+
+ time pzstd -# -p 4 -c silesia.tar > silesia.tar.zst
+ time pzstd -d -p 4 -c silesia.tar.zst > /dev/null
+
+ time pigz -# -p 4 -k -c silesia.tar > silesia.tar.gz
+ time pigz -d -p 4 -k -c silesia.tar.gz > /dev/null
+
+PZstandard was tested using compression levels 1-19, and Pigz was tested using compression levels 1-9.
+Pigz cannot do parallel decompression, it simply does each of reading, decompression, and writing on separate threads.
+
+## Tests
+
+Tests require that you have [gtest](https://github.com/google/googletest) installed.
+Modify `GTEST_INC` and `GTEST_LIB` in `test/Makefile` and `utils/test/Makefile` to work for your install of gtest.
+Then run `make test` in the `contrib/pzstd` directory.
diff --git a/contrib/pzstd/SkippableFrame.cpp b/contrib/pzstd/SkippableFrame.cpp
new file mode 100644
index 000000000..5dc95e5ab
--- /dev/null
+++ b/contrib/pzstd/SkippableFrame.cpp
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+#include "SkippableFrame.h"
+#include "mem.h"
+#include "utils/Range.h"
+
+#include
+
+using namespace pzstd;
+
+SkippableFrame::SkippableFrame(std::uint32_t size) : frameSize_(size) {
+ MEM_writeLE32(data_.data(), kSkippableFrameMagicNumber);
+ MEM_writeLE32(data_.data() + 4, kFrameContentsSize);
+ MEM_writeLE32(data_.data() + 8, frameSize_);
+}
+
+/* static */ std::size_t SkippableFrame::tryRead(ByteRange bytes) {
+ if (bytes.size() < SkippableFrame::kSize ||
+ MEM_readLE32(bytes.begin()) != kSkippableFrameMagicNumber ||
+ MEM_readLE32(bytes.begin() + 4) != kFrameContentsSize) {
+ return 0;
+ }
+ return MEM_readLE32(bytes.begin() + 8);
+}
diff --git a/contrib/pzstd/SkippableFrame.h b/contrib/pzstd/SkippableFrame.h
new file mode 100644
index 000000000..9dc95c1f5
--- /dev/null
+++ b/contrib/pzstd/SkippableFrame.h
@@ -0,0 +1,64 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include "utils/Range.h"
+
+#include
+#include
+#include
+#include
+
+namespace pzstd {
+/**
+ * We put a skippable frame before each frame.
+ * It contains a skippable frame magic number, the size of the skippable frame,
+ * and the size of the next frame.
+ * Each skippable frame is exactly 12 bytes in little endian format.
+ * The first 8 bytes are for compatibility with the ZSTD format.
+ * If we have N threads, the output will look like
+ *
+ * [0x184D2A50|4|size1] [frame1 of size size1]
+ * [0x184D2A50|4|size2] [frame2 of size size2]
+ * ...
+ * [0x184D2A50|4|sizeN] [frameN of size sizeN]
+ *
+ * Each sizeX is 4 bytes.
+ *
+ * These skippable frames should allow us to skip through the compressed file
+ * and only load at most N pages.
+ */
+class SkippableFrame {
+ public:
+ static constexpr std::size_t kSize = 12;
+
+ private:
+ std::uint32_t frameSize_;
+ std::array data_;
+ static constexpr std::uint32_t kSkippableFrameMagicNumber = 0x184D2A50;
+ // Could be improved if the size fits in less bytes
+ static constexpr std::uint32_t kFrameContentsSize = kSize - 8;
+
+ public:
+ // Write the skippable frame to data_ in LE format.
+ explicit SkippableFrame(std::uint32_t size);
+
+ // Read the skippable frame from bytes in LE format.
+ static std::size_t tryRead(ByteRange bytes);
+
+ ByteRange data() const {
+ return {data_.data(), data_.size()};
+ }
+
+ // Size of the next frame.
+ std::size_t frameSize() const {
+ return frameSize_;
+ }
+};
+}
diff --git a/contrib/pzstd/images/Cspeed.png b/contrib/pzstd/images/Cspeed.png
new file mode 100644
index 000000000..aca4f663e
Binary files /dev/null and b/contrib/pzstd/images/Cspeed.png differ
diff --git a/contrib/pzstd/images/Dspeed.png b/contrib/pzstd/images/Dspeed.png
new file mode 100644
index 000000000..e48881bcd
Binary files /dev/null and b/contrib/pzstd/images/Dspeed.png differ
diff --git a/contrib/pzstd/main.cpp b/contrib/pzstd/main.cpp
new file mode 100644
index 000000000..279cbfb5e
--- /dev/null
+++ b/contrib/pzstd/main.cpp
@@ -0,0 +1,32 @@
+/**
+ * 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.
+ */
+#include "ErrorHolder.h"
+#include "Options.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;
+
+int main(int argc, const char** argv) {
+ Options options;
+ switch (options.parse(argc, argv)) {
+ case Options::Status::Failure:
+ return 1;
+ case Options::Status::Message:
+ return 0;
+ default:
+ break;
+ }
+
+ return pzstdMain(options);
+}
diff --git a/contrib/pzstd/test/Makefile b/contrib/pzstd/test/Makefile
new file mode 100644
index 000000000..4f6ba9997
--- /dev/null
+++ b/contrib/pzstd/test/Makefile
@@ -0,0 +1,48 @@
+# ##########################################################################
+# 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.
+# ##########################################################################
+
+# Define *.exe as extension for Windows systems
+ifneq (,$(filter Windows%,$(OS)))
+EXT =.exe
+else
+EXT =
+endif
+
+PZSTDDIR = ..
+PROGDIR = ../../../programs
+ZSTDDIR = ../../../lib
+
+# Set GTEST_INC and GTEST_LIB to work with your install of gtest
+GTEST_INC ?= -isystem $(PZSTDDIR)/googletest/googletest/include
+GTEST_LIB ?= -L $(PZSTDDIR)/googletest/build/googlemock/gtest
+GTEST_FLAGS = $(GTEST_INC) $(GTEST_LIB)
+CPPFLAGS = -I$(PZSTDDIR) -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(PROGDIR) -I.
+
+CXXFLAGS ?= -O3
+CXXFLAGS += -std=c++11 -Wno-deprecated-declarations
+CXXFLAGS += $(MOREFLAGS)
+FLAGS = $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS)
+
+datagen.o: $(PROGDIR)/datagen.*
+ $(CC) $(CPPFLAGS) -O3 $(MOREFLAGS) $(LDFLAGS) -Wno-long-long -Wno-variadic-macros $(PROGDIR)/datagen.c -c -o $@
+
+%: %.cpp *.h datagen.o
+ $(CXX) $(FLAGS) $@.cpp datagen.o $(PZSTDDIR)/Pzstd.o $(PZSTDDIR)/SkippableFrame.o $(PZSTDDIR)/Options.o $(PZSTDDIR)/libzstd.a -o $@$(EXT) $(GTEST_FLAGS) -lgtest -lgtest_main -lpthread
+
+.PHONY: test clean
+
+test: OptionsTest PzstdTest
+ @./OptionsTest$(EXT)
+ @./PzstdTest$(EXT)
+
+roundtrip: RoundTripTest
+ @./RoundTripTest$(EXT)
+
+clean:
+ @rm -f datagen.o OptionsTest PzstdTest RoundTripTest
diff --git a/contrib/pzstd/test/OptionsTest.cpp b/contrib/pzstd/test/OptionsTest.cpp
new file mode 100644
index 000000000..e7d4b2b3e
--- /dev/null
+++ b/contrib/pzstd/test/OptionsTest.cpp
@@ -0,0 +1,542 @@
+/**
+ * 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.
+ */
+#include "Options.h"
+
+#include
+#include
+
+using namespace pzstd;
+
+namespace pzstd {
+bool operator==(const Options &lhs, const Options &rhs) {
+ return lhs.numThreads == rhs.numThreads &&
+ lhs.maxWindowLog == rhs.maxWindowLog &&
+ lhs.compressionLevel == rhs.compressionLevel &&
+ lhs.decompress == rhs.decompress && lhs.inputFiles == rhs.inputFiles &&
+ lhs.outputFile == rhs.outputFile && lhs.overwrite == rhs.overwrite &&
+ lhs.keepSource == rhs.keepSource && lhs.writeMode == rhs.writeMode &&
+ lhs.checksum == rhs.checksum && lhs.verbosity == rhs.verbosity;
+}
+
+std::ostream &operator<<(std::ostream &out, const Options &opt) {
+ out << "{";
+ {
+ out << "\n\t"
+ << "numThreads: " << opt.numThreads;
+ out << ",\n\t"
+ << "maxWindowLog: " << opt.maxWindowLog;
+ out << ",\n\t"
+ << "compressionLevel: " << opt.compressionLevel;
+ out << ",\n\t"
+ << "decompress: " << opt.decompress;
+ out << ",\n\t"
+ << "inputFiles: {";
+ {
+ bool first = true;
+ for (const auto &file : opt.inputFiles) {
+ if (!first) {
+ out << ",";
+ }
+ first = false;
+ out << "\n\t\t" << file;
+ }
+ }
+ out << "\n\t}";
+ out << ",\n\t"
+ << "outputFile: " << opt.outputFile;
+ out << ",\n\t"
+ << "overwrite: " << opt.overwrite;
+ out << ",\n\t"
+ << "keepSource: " << opt.keepSource;
+ out << ",\n\t"
+ << "writeMode: " << static_cast(opt.writeMode);
+ out << ",\n\t"
+ << "checksum: " << opt.checksum;
+ out << ",\n\t"
+ << "verbosity: " << opt.verbosity;
+ }
+ out << "\n}";
+ return out;
+}
+}
+
+namespace {
+#ifdef _WIN32
+const char nullOutput[] = "nul";
+#else
+const char nullOutput[] = "/dev/null";
+#endif
+
+constexpr auto autoMode = Options::WriteMode::Auto;
+} // anonymous namespace
+
+#define EXPECT_SUCCESS(...) EXPECT_EQ(Options::Status::Success, __VA_ARGS__)
+#define EXPECT_FAILURE(...) EXPECT_EQ(Options::Status::Failure, __VA_ARGS__)
+#define EXPECT_MESSAGE(...) EXPECT_EQ(Options::Status::Message, __VA_ARGS__)
+
+template
+std::array makeArray(Args... args) {
+ return {{nullptr, args...}};
+}
+
+TEST(Options, ValidInputs) {
+ {
+ Options options;
+ auto args = makeArray("--processes", "5", "-o", "x", "y", "-f");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected = {5, 23, 3, false, {"y"}, "x",
+ true, true, autoMode, true, 2};
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args = makeArray("-p", "1", "input", "-19");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected = {1, 23, 19, false, {"input"}, "",
+ false, true, autoMode, true, 2};
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args =
+ makeArray("--ultra", "-22", "-p", "1", "-o", "x", "-d", "x.zst", "-f");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected = {1, 0, 22, true, {"x.zst"}, "x",
+ true, true, autoMode, true, 2};
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args = makeArray("--processes", "100", "hello.zst", "--decompress",
+ "--force");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected = {100, 23, 3, true, {"hello.zst"}, "", true,
+ true, autoMode, true, 2};
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-dp", "1", "-c");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected = {1, 23, 3, true, {"x"}, "-",
+ false, true, autoMode, true, 2};
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-dp", "1", "--stdout");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected = {1, 23, 3, true, {"x"}, "-",
+ false, true, autoMode, true, 2};
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args = makeArray("-p", "1", "x", "-5", "-fo", "-", "--ultra", "-d");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected = {1, 0, 5, true, {"x"}, "-",
+ true, true, autoMode, true, 2};
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args = makeArray("silesia.tar", "-o", "silesia.tar.pzstd", "-p", "2");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected = {2,
+ 23,
+ 3,
+ false,
+ {"silesia.tar"},
+ "silesia.tar.pzstd",
+ false,
+ true,
+ autoMode,
+ true,
+ 2};
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-p", "1");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-p", "1");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ }
+}
+
+TEST(Options, GetOutputFile) {
+ {
+ Options options;
+ auto args = makeArray("x");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ("x.zst", options.getOutputFile(options.inputFiles[0]));
+ }
+ {
+ Options options;
+ auto args = makeArray("-o-");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ EXPECT_EQ("-", options.getOutputFile(options.inputFiles[0]));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "y", "-o", nullOutput);
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(nullOutput, options.getOutputFile(options.inputFiles[0]));
+ }
+ {
+ Options options;
+ auto args = makeArray("x.zst", "-do", nullOutput);
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(nullOutput, options.getOutputFile(options.inputFiles[0]));
+ }
+ {
+ Options options;
+ auto args = makeArray("x.zst", "-d");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ("x", options.getOutputFile(options.inputFiles[0]));
+ }
+ {
+ Options options;
+ auto args = makeArray("xzst", "-d");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ("", options.getOutputFile(options.inputFiles[0]));
+ }
+ {
+ Options options;
+ auto args = makeArray("xzst", "-doxx");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ("xx", options.getOutputFile(options.inputFiles[0]));
+ }
+}
+
+TEST(Options, MultipleFiles) {
+ {
+ Options options;
+ auto args = makeArray("x", "y", "z");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected;
+ expected.inputFiles = {"x", "y", "z"};
+ expected.verbosity = 1;
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "y", "z", "-o", nullOutput);
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected;
+ expected.inputFiles = {"x", "y", "z"};
+ expected.outputFile = nullOutput;
+ expected.verbosity = 1;
+ EXPECT_EQ(expected, options);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "y", "-o-");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "y", "-o", "file");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("-qqvd12qp4", "-f", "x", "--", "--rm", "-c");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ Options expected = {4, 23, 12, true, {"x", "--rm", "-c"},
+ "", true, true, autoMode, true,
+ 0};
+ EXPECT_EQ(expected, options);
+ }
+}
+
+TEST(Options, NumThreads) {
+ {
+ Options options;
+ auto args = makeArray("x", "-dfo", "-");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-p", "0", "-fo", "-");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("-f", "-p", "-o", "-");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+}
+
+TEST(Options, BadCompressionLevel) {
+ {
+ Options options;
+ auto args = makeArray("x", "-20");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "--ultra", "-23");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "--1"); // negative 1?
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+}
+
+TEST(Options, InvalidOption) {
+ {
+ Options options;
+ auto args = makeArray("x", "-x");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+}
+
+TEST(Options, BadOutputFile) {
+ {
+ Options options;
+ auto args = makeArray("notzst", "-d", "-p", "1");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ("", options.getOutputFile(options.inputFiles.front()));
+ }
+}
+
+TEST(Options, BadOptionsWithArguments) {
+ {
+ Options options;
+ auto args = makeArray("x", "-pf");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-p", "10f");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-p");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-o");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-o");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+}
+
+TEST(Options, KeepSource) {
+ {
+ Options options;
+ auto args = makeArray("x", "--rm", "-k");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(true, options.keepSource);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "--rm", "--keep");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(true, options.keepSource);
+ }
+ {
+ Options options;
+ auto args = makeArray("x");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(true, options.keepSource);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "--rm");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(false, options.keepSource);
+ }
+}
+
+TEST(Options, Verbosity) {
+ {
+ Options options;
+ auto args = makeArray("x");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(2, options.verbosity);
+ }
+ {
+ Options options;
+ auto args = makeArray("--quiet", "-qq", "x");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(-1, options.verbosity);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "y");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(1, options.verbosity);
+ }
+ {
+ Options options;
+ auto args = makeArray("--", "x", "y");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(1, options.verbosity);
+ }
+ {
+ Options options;
+ auto args = makeArray("-qv", "x", "y");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(1, options.verbosity);
+ }
+ {
+ Options options;
+ auto args = makeArray("-v", "x", "y");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(3, options.verbosity);
+ }
+ {
+ Options options;
+ auto args = makeArray("-v", "x");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(3, options.verbosity);
+ }
+}
+
+TEST(Options, TestMode) {
+ {
+ Options options;
+ auto args = makeArray("x", "-t");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(true, options.keepSource);
+ EXPECT_EQ(true, options.decompress);
+ EXPECT_EQ(nullOutput, options.outputFile);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "--test", "--rm", "-ohello");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(true, options.keepSource);
+ EXPECT_EQ(true, options.decompress);
+ EXPECT_EQ(nullOutput, options.outputFile);
+ }
+}
+
+TEST(Options, Checksum) {
+ {
+ Options options;
+ auto args = makeArray("x.zst", "--no-check", "-Cd");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(true, options.checksum);
+ }
+ {
+ Options options;
+ auto args = makeArray("x");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(true, options.checksum);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "--no-check", "--check");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(true, options.checksum);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "--no-check");
+ EXPECT_SUCCESS(options.parse(args.size(), args.data()));
+ EXPECT_EQ(false, options.checksum);
+ }
+}
+
+TEST(Options, InputFiles) {
+ {
+ Options options;
+ auto args = makeArray("-cd");
+ options.parse(args.size(), args.data());
+ EXPECT_EQ(1, options.inputFiles.size());
+ EXPECT_EQ("-", options.inputFiles[0]);
+ EXPECT_EQ("-", options.outputFile);
+ }
+ {
+ Options options;
+ auto args = makeArray();
+ options.parse(args.size(), args.data());
+ EXPECT_EQ(1, options.inputFiles.size());
+ EXPECT_EQ("-", options.inputFiles[0]);
+ EXPECT_EQ("-", options.outputFile);
+ }
+ {
+ Options options;
+ auto args = makeArray("-d");
+ options.parse(args.size(), args.data());
+ EXPECT_EQ(1, options.inputFiles.size());
+ EXPECT_EQ("-", options.inputFiles[0]);
+ EXPECT_EQ("-", options.outputFile);
+ }
+ {
+ Options options;
+ auto args = makeArray("x", "-");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+}
+
+TEST(Options, InvalidOptions) {
+ {
+ Options options;
+ auto args = makeArray("-ibasdf");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("- ");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("-n15");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("-0", "x");
+ EXPECT_FAILURE(options.parse(args.size(), args.data()));
+ }
+}
+
+TEST(Options, Extras) {
+ {
+ Options options;
+ auto args = makeArray("-h");
+ EXPECT_MESSAGE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("-H");
+ EXPECT_MESSAGE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("-V");
+ EXPECT_MESSAGE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("--help");
+ EXPECT_MESSAGE(options.parse(args.size(), args.data()));
+ }
+ {
+ Options options;
+ auto args = makeArray("--version");
+ EXPECT_MESSAGE(options.parse(args.size(), args.data()));
+ }
+}
diff --git a/contrib/pzstd/test/PzstdTest.cpp b/contrib/pzstd/test/PzstdTest.cpp
new file mode 100644
index 000000000..c85f73a39
--- /dev/null
+++ b/contrib/pzstd/test/PzstdTest.cpp
@@ -0,0 +1,155 @@
+/**
+ * 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.
+ */
+#include "Pzstd.h"
+extern "C" {
+#include "datagen.h"
+}
+#include "test/RoundTrip.h"
+#include "utils/ScopeGuard.h"
+
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+using namespace pzstd;
+
+TEST(Pzstd, SmallSizes) {
+ unsigned seed = std::random_device{}();
+ std::fprintf(stderr, "Pzstd.SmallSizes seed: %u\n", seed);
+ std::mt19937 gen(seed);
+
+ for (unsigned len = 1; len < 256; ++len) {
+ if (len % 16 == 0) {
+ std::fprintf(stderr, "%u / 16\n", len / 16);
+ }
+ std::string inputFile = std::tmpnam(nullptr);
+ auto guard = makeScopeGuard([&] { std::remove(inputFile.c_str()); });
+ {
+ static uint8_t buf[256];
+ RDG_genBuffer(buf, len, 0.5, 0.0, gen());
+ auto fd = std::fopen(inputFile.c_str(), "wb");
+ auto written = std::fwrite(buf, 1, len, fd);
+ std::fclose(fd);
+ ASSERT_EQ(written, len);
+ }
+ for (unsigned headers = 0; headers <= 1; ++headers) {
+ for (unsigned numThreads = 1; numThreads <= 2; ++numThreads) {
+ for (unsigned level = 1; level <= 4; level *= 4) {
+ auto errorGuard = makeScopeGuard([&] {
+ std::fprintf(stderr, "pzstd headers: %u\n", headers);
+ std::fprintf(stderr, "# threads: %u\n", numThreads);
+ std::fprintf(stderr, "compression level: %u\n", level);
+ });
+ Options options;
+ options.overwrite = true;
+ options.inputFiles = {inputFile};
+ options.numThreads = numThreads;
+ options.compressionLevel = level;
+ options.verbosity = 1;
+ ASSERT_TRUE(roundTrip(options));
+ errorGuard.dismiss();
+ }
+ }
+ }
+ }
+}
+
+TEST(Pzstd, LargeSizes) {
+ unsigned seed = std::random_device{}();
+ std::fprintf(stderr, "Pzstd.LargeSizes seed: %u\n", seed);
+ std::mt19937 gen(seed);
+
+ for (unsigned len = 1 << 20; len <= (1 << 24); len *= 2) {
+ std::string inputFile = std::tmpnam(nullptr);
+ auto guard = makeScopeGuard([&] { std::remove(inputFile.c_str()); });
+ {
+ std::unique_ptr buf(new uint8_t[len]);
+ RDG_genBuffer(buf.get(), len, 0.5, 0.0, gen());
+ auto fd = std::fopen(inputFile.c_str(), "wb");
+ auto written = std::fwrite(buf.get(), 1, len, fd);
+ std::fclose(fd);
+ ASSERT_EQ(written, len);
+ }
+ for (unsigned headers = 0; headers <= 1; ++headers) {
+ for (unsigned numThreads = 1; numThreads <= 16; numThreads *= 4) {
+ for (unsigned level = 1; level <= 4; level *= 2) {
+ auto errorGuard = makeScopeGuard([&] {
+ std::fprintf(stderr, "pzstd headers: %u\n", headers);
+ std::fprintf(stderr, "# threads: %u\n", numThreads);
+ std::fprintf(stderr, "compression level: %u\n", level);
+ });
+ Options options;
+ options.overwrite = true;
+ options.inputFiles = {inputFile};
+ options.numThreads = std::min(numThreads, options.numThreads);
+ options.compressionLevel = level;
+ options.verbosity = 1;
+ ASSERT_TRUE(roundTrip(options));
+ errorGuard.dismiss();
+ }
+ }
+ }
+ }
+}
+
+TEST(Pzstd, ExtremelyLargeSize) {
+ unsigned seed = std::random_device{}();
+ std::fprintf(stderr, "Pzstd.ExtremelyLargeSize seed: %u\n", seed);
+ std::mt19937 gen(seed);
+
+ std::string inputFile = std::tmpnam(nullptr);
+ auto guard = makeScopeGuard([&] { std::remove(inputFile.c_str()); });
+
+ {
+ // Write 4GB + 64 MB
+ constexpr size_t kLength = 1 << 26;
+ std::unique_ptr buf(new uint8_t[kLength]);
+ auto fd = std::fopen(inputFile.c_str(), "wb");
+ auto closeGuard = makeScopeGuard([&] { std::fclose(fd); });
+ for (size_t i = 0; i < (1 << 6) + 1; ++i) {
+ RDG_genBuffer(buf.get(), kLength, 0.5, 0.0, gen());
+ auto written = std::fwrite(buf.get(), 1, kLength, fd);
+ if (written != kLength) {
+ std::fprintf(stderr, "Failed to write file, skipping test\n");
+ return;
+ }
+ }
+ }
+
+ Options options;
+ options.overwrite = true;
+ options.inputFiles = {inputFile};
+ options.compressionLevel = 1;
+ if (options.numThreads == 0) {
+ options.numThreads = 1;
+ }
+ ASSERT_TRUE(roundTrip(options));
+}
+
+TEST(Pzstd, ExtremelyCompressible) {
+ std::string inputFile = std::tmpnam(nullptr);
+ auto guard = makeScopeGuard([&] { std::remove(inputFile.c_str()); });
+ {
+ std::unique_ptr buf(new uint8_t[10000]);
+ std::memset(buf.get(), 'a', 10000);
+ auto fd = std::fopen(inputFile.c_str(), "wb");
+ auto written = std::fwrite(buf.get(), 1, 10000, fd);
+ std::fclose(fd);
+ ASSERT_EQ(written, 10000);
+ }
+ Options options;
+ options.overwrite = true;
+ options.inputFiles = {inputFile};
+ options.numThreads = 1;
+ options.compressionLevel = 1;
+ ASSERT_TRUE(roundTrip(options));
+}
diff --git a/contrib/pzstd/test/RoundTrip.h b/contrib/pzstd/test/RoundTrip.h
new file mode 100644
index 000000000..8b9088459
--- /dev/null
+++ b/contrib/pzstd/test/RoundTrip.h
@@ -0,0 +1,86 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include "Options.h"
+#include "Pzstd.h"
+#include "utils/ScopeGuard.h"
+
+#include
+#include
+#include
+#include
+
+namespace pzstd {
+
+inline bool check(std::string source, std::string decompressed) {
+ std::unique_ptr sBuf(new std::uint8_t[1024]);
+ std::unique_ptr dBuf(new std::uint8_t[1024]);
+
+ auto sFd = std::fopen(source.c_str(), "rb");
+ auto dFd = std::fopen(decompressed.c_str(), "rb");
+ auto guard = makeScopeGuard([&] {
+ std::fclose(sFd);
+ std::fclose(dFd);
+ });
+
+ size_t sRead, dRead;
+
+ do {
+ sRead = std::fread(sBuf.get(), 1, 1024, sFd);
+ dRead = std::fread(dBuf.get(), 1, 1024, dFd);
+ if (std::ferror(sFd) || std::ferror(dFd)) {
+ return false;
+ }
+ if (sRead != dRead) {
+ return false;
+ }
+
+ for (size_t i = 0; i < sRead; ++i) {
+ if (sBuf.get()[i] != dBuf.get()[i]) {
+ return false;
+ }
+ }
+ } while (sRead == 1024);
+ if (!std::feof(sFd) || !std::feof(dFd)) {
+ return false;
+ }
+ return true;
+}
+
+inline bool roundTrip(Options& options) {
+ if (options.inputFiles.size() != 1) {
+ return false;
+ }
+ std::string source = options.inputFiles.front();
+ std::string compressedFile = std::tmpnam(nullptr);
+ std::string decompressedFile = std::tmpnam(nullptr);
+ auto guard = makeScopeGuard([&] {
+ std::remove(compressedFile.c_str());
+ std::remove(decompressedFile.c_str());
+ });
+
+ {
+ options.outputFile = compressedFile;
+ options.decompress = false;
+ if (pzstdMain(options) != 0) {
+ return false;
+ }
+ }
+ {
+ options.decompress = true;
+ options.inputFiles.front() = compressedFile;
+ options.outputFile = decompressedFile;
+ if (pzstdMain(options) != 0) {
+ return false;
+ }
+ }
+ return check(source, decompressedFile);
+}
+}
diff --git a/contrib/pzstd/test/RoundTripTest.cpp b/contrib/pzstd/test/RoundTripTest.cpp
new file mode 100644
index 000000000..ed2ea770c
--- /dev/null
+++ b/contrib/pzstd/test/RoundTripTest.cpp
@@ -0,0 +1,86 @@
+/**
+ * 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.
+ */
+extern "C" {
+#include "datagen.h"
+}
+#include "Options.h"
+#include "test/RoundTrip.h"
+#include "utils/ScopeGuard.h"
+
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+using namespace pzstd;
+
+namespace {
+string
+writeData(size_t size, double matchProba, double litProba, unsigned seed) {
+ std::unique_ptr buf(new uint8_t[size]);
+ RDG_genBuffer(buf.get(), size, matchProba, litProba, seed);
+ string file = tmpnam(nullptr);
+ auto fd = std::fopen(file.c_str(), "wb");
+ auto guard = makeScopeGuard([&] { std::fclose(fd); });
+ auto bytesWritten = std::fwrite(buf.get(), 1, size, fd);
+ if (bytesWritten != size) {
+ std::abort();
+ }
+ return file;
+}
+
+template
+string generateInputFile(Generator& gen) {
+ // Use inputs ranging from 1 Byte to 2^16 Bytes
+ std::uniform_int_distribution size{1, 1 << 16};
+ std::uniform_real_distribution<> prob{0, 1};
+ return writeData(size(gen), prob(gen), prob(gen), gen());
+}
+
+template
+Options generateOptions(Generator& gen, const string& inputFile) {
+ Options options;
+ options.inputFiles = {inputFile};
+ options.overwrite = true;
+
+ std::uniform_int_distribution numThreads{1, 32};
+ std::uniform_int_distribution compressionLevel{1, 10};
+
+ options.numThreads = numThreads(gen);
+ options.compressionLevel = compressionLevel(gen);
+
+ return options;
+}
+}
+
+int main() {
+ std::mt19937 gen(std::random_device{}());
+
+ auto newlineGuard = makeScopeGuard([] { std::fprintf(stderr, "\n"); });
+ for (unsigned i = 0; i < 10000; ++i) {
+ if (i % 100 == 0) {
+ std::fprintf(stderr, "Progress: %u%%\r", i / 100);
+ }
+ auto inputFile = generateInputFile(gen);
+ auto inputGuard = makeScopeGuard([&] { std::remove(inputFile.c_str()); });
+ for (unsigned i = 0; i < 10; ++i) {
+ auto options = generateOptions(gen, inputFile);
+ if (!roundTrip(options)) {
+ std::fprintf(stderr, "numThreads: %u\n", options.numThreads);
+ std::fprintf(stderr, "level: %u\n", options.compressionLevel);
+ std::fprintf(stderr, "decompress? %u\n", (unsigned)options.decompress);
+ std::fprintf(stderr, "file: %s\n", inputFile.c_str());
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/contrib/pzstd/utils/Buffer.h b/contrib/pzstd/utils/Buffer.h
new file mode 100644
index 000000000..ab25bac9c
--- /dev/null
+++ b/contrib/pzstd/utils/Buffer.h
@@ -0,0 +1,99 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include "utils/Range.h"
+
+#include
+#include
+#include
+
+namespace pzstd {
+
+/**
+ * A `Buffer` has a pointer to a shared buffer, and a range of the buffer that
+ * it owns.
+ * The idea is that you can allocate one buffer, and write chunks into it
+ * and break off those chunks.
+ * The underlying buffer is reference counted, and will be destroyed when all
+ * `Buffer`s that reference it are destroyed.
+ */
+class Buffer {
+ std::shared_ptr buffer_;
+ MutableByteRange range_;
+
+ static void delete_buffer(unsigned char* buffer) {
+ delete[] buffer;
+ }
+
+ public:
+ /// Construct an empty buffer that owns no data.
+ explicit Buffer() {}
+
+ /// Construct a `Buffer` that owns a new underlying buffer of size `size`.
+ explicit Buffer(std::size_t size)
+ : buffer_(new unsigned char[size], delete_buffer),
+ range_(buffer_.get(), buffer_.get() + size) {}
+
+ explicit Buffer(std::shared_ptr buffer, MutableByteRange data)
+ : buffer_(buffer), range_(data) {}
+
+ Buffer(Buffer&&) = default;
+ Buffer& operator=(Buffer&&) & = default;
+
+ /**
+ * Splits the data into two pieces: [begin, begin + n), [begin + n, end).
+ * Their data both points into the same underlying buffer.
+ * Modifies the original `Buffer` to point to only [begin + n, end).
+ *
+ * @param n The offset to split at.
+ * @returns A buffer that owns the data [begin, begin + n).
+ */
+ Buffer splitAt(std::size_t n) {
+ auto firstPiece = range_.subpiece(0, n);
+ range_.advance(n);
+ return Buffer(buffer_, firstPiece);
+ }
+
+ /// Modifies the buffer to point to the range [begin + n, end).
+ void advance(std::size_t n) {
+ range_.advance(n);
+ }
+
+ /// Modifies the buffer to point to the range [begin, end - n).
+ void subtract(std::size_t n) {
+ range_.subtract(n);
+ }
+
+ /// Returns a read only `Range` pointing to the `Buffer`s data.
+ ByteRange range() const {
+ return range_;
+ }
+ /// Returns a mutable `Range` pointing to the `Buffer`s data.
+ MutableByteRange range() {
+ return range_;
+ }
+
+ const unsigned char* data() const {
+ return range_.data();
+ }
+
+ unsigned char* data() {
+ return range_.data();
+ }
+
+ std::size_t size() const {
+ return range_.size();
+ }
+
+ bool empty() const {
+ return range_.empty();
+ }
+};
+}
diff --git a/contrib/pzstd/utils/FileSystem.h b/contrib/pzstd/utils/FileSystem.h
new file mode 100644
index 000000000..7d597047f
--- /dev/null
+++ b/contrib/pzstd/utils/FileSystem.h
@@ -0,0 +1,94 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include "utils/Range.h"
+
+#include
+#include
+#include
+#include
+
+// A small subset of `std::filesystem`.
+// `std::filesystem` should be a drop in replacement.
+// See http://en.cppreference.com/w/cpp/filesystem for documentation.
+
+namespace pzstd {
+
+// using file_status = ... causes gcc to emit a false positive warning
+#if defined(_MSC_VER)
+typedef struct ::_stat64 file_status;
+#else
+typedef struct ::stat file_status;
+#endif
+
+/// http://en.cppreference.com/w/cpp/filesystem/status
+inline file_status status(StringPiece path, std::error_code& ec) noexcept {
+ file_status status;
+#if defined(_MSC_VER)
+ const auto error = ::_stat64(path.data(), &status);
+#else
+ const auto error = ::stat(path.data(), &status);
+#endif
+ if (error) {
+ ec.assign(errno, std::generic_category());
+ } else {
+ ec.clear();
+ }
+ return status;
+}
+
+/// http://en.cppreference.com/w/cpp/filesystem/is_regular_file
+inline bool is_regular_file(file_status status) noexcept {
+#if defined(S_ISREG)
+ return S_ISREG(status.st_mode);
+#elif !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
+ return (status.st_mode & S_IFMT) == S_IFREG;
+#else
+ static_assert(false, "No POSIX stat() support.");
+#endif
+}
+
+/// http://en.cppreference.com/w/cpp/filesystem/is_regular_file
+inline bool is_regular_file(StringPiece path, std::error_code& ec) noexcept {
+ return is_regular_file(status(path, ec));
+}
+
+/// http://en.cppreference.com/w/cpp/filesystem/is_directory
+inline bool is_directory(file_status status) noexcept {
+#if defined(S_ISDIR)
+ return S_ISDIR(status.st_mode);
+#elif !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
+ return (status.st_mode & S_IFMT) == S_IFDIR;
+#else
+ static_assert(false, "NO POSIX stat() support.");
+#endif
+}
+
+/// http://en.cppreference.com/w/cpp/filesystem/is_directory
+inline bool is_directory(StringPiece path, std::error_code& ec) noexcept {
+ return is_directory(status(path, ec));
+}
+
+/// http://en.cppreference.com/w/cpp/filesystem/file_size
+inline std::uintmax_t file_size(
+ StringPiece path,
+ std::error_code& ec) noexcept {
+ auto stat = status(path, ec);
+ if (ec) {
+ return -1;
+ }
+ if (!is_regular_file(stat)) {
+ ec.assign(ENOTSUP, std::generic_category());
+ return -1;
+ }
+ ec.clear();
+ return stat.st_size;
+}
+}
diff --git a/contrib/pzstd/utils/Likely.h b/contrib/pzstd/utils/Likely.h
new file mode 100644
index 000000000..c8ea102b1
--- /dev/null
+++ b/contrib/pzstd/utils/Likely.h
@@ -0,0 +1,28 @@
+/**
+ * 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.
+ */
+
+/**
+ * Compiler hints to indicate the fast path of an "if" branch: whether
+ * the if condition is likely to be true or false.
+ *
+ * @author Tudor Bosman (tudorb@fb.com)
+ */
+
+#pragma once
+
+#undef LIKELY
+#undef UNLIKELY
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define LIKELY(x) (__builtin_expect((x), 1))
+#define UNLIKELY(x) (__builtin_expect((x), 0))
+#else
+#define LIKELY(x) (x)
+#define UNLIKELY(x) (x)
+#endif
diff --git a/contrib/pzstd/utils/Range.h b/contrib/pzstd/utils/Range.h
new file mode 100644
index 000000000..111e98f58
--- /dev/null
+++ b/contrib/pzstd/utils/Range.h
@@ -0,0 +1,131 @@
+/**
+ * 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.
+ */
+
+/**
+ * A subset of `folly/Range.h`.
+ * All code copied verbatiam modulo formatting
+ */
+#pragma once
+
+#include "utils/Likely.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace pzstd {
+
+namespace detail {
+/*
+ *Use IsCharPointer::type to enable const char* or char*.
+ *Use IsCharPointer::const_type to enable only const char*.
+*/
+template
+struct IsCharPointer {};
+
+template <>
+struct IsCharPointer {
+ typedef int type;
+};
+
+template <>
+struct IsCharPointer {
+ typedef int const_type;
+ typedef int type;
+};
+
+} // namespace detail
+
+template
+class Range {
+ Iter b_;
+ Iter e_;
+
+ public:
+ using size_type = std::size_t;
+ using iterator = Iter;
+ using const_iterator = Iter;
+ using value_type = typename std::remove_reference<
+ typename std::iterator_traits::reference>::type;
+ using reference = typename std::iterator_traits::reference;
+
+ constexpr Range() : b_(), e_() {}
+ constexpr Range(Iter begin, Iter end) : b_(begin), e_(end) {}
+
+ constexpr Range(Iter begin, size_type size) : b_(begin), e_(begin + size) {}
+
+ template ::type = 0>
+ /* implicit */ Range(Iter str) : b_(str), e_(str + std::strlen(str)) {}
+
+ template ::const_type = 0>
+ /* implicit */ Range(const std::string& str)
+ : b_(str.data()), e_(b_ + str.size()) {}
+
+ // Allow implicit conversion from Range to Range if From is
+ // implicitly convertible to To.
+ template <
+ class OtherIter,
+ typename std::enable_if<
+ (!std::is_same::value &&
+ std::is_convertible::value),
+ int>::type = 0>
+ constexpr /* implicit */ Range(const Range& other)
+ : b_(other.begin()), e_(other.end()) {}
+
+ Range(const Range&) = default;
+ Range(Range&&) = default;
+
+ Range& operator=(const Range&) & = default;
+ Range& operator=(Range&&) & = default;
+
+ constexpr size_type size() const {
+ return e_ - b_;
+ }
+ bool empty() const {
+ return b_ == e_;
+ }
+ Iter data() const {
+ return b_;
+ }
+ Iter begin() const {
+ return b_;
+ }
+ Iter end() const {
+ return e_;
+ }
+
+ void advance(size_type n) {
+ if (UNLIKELY(n > size())) {
+ throw std::out_of_range("index out of range");
+ }
+ b_ += n;
+ }
+
+ void subtract(size_type n) {
+ if (UNLIKELY(n > size())) {
+ throw std::out_of_range("index out of range");
+ }
+ e_ -= n;
+ }
+
+ Range subpiece(size_type first, size_type length = std::string::npos) const {
+ if (UNLIKELY(first > size())) {
+ throw std::out_of_range("index out of range");
+ }
+
+ return Range(b_ + first, std::min(length, size() - first));
+ }
+};
+
+using ByteRange = Range;
+using MutableByteRange = Range;
+using StringPiece = Range;
+}
diff --git a/contrib/pzstd/utils/ScopeGuard.h b/contrib/pzstd/utils/ScopeGuard.h
new file mode 100644
index 000000000..5a333e0ab
--- /dev/null
+++ b/contrib/pzstd/utils/ScopeGuard.h
@@ -0,0 +1,50 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include
+
+namespace pzstd {
+
+/**
+ * Dismissable scope guard.
+ * `Function` must be callable and take no parameters.
+ * Unless `dissmiss()` is called, the callable is executed upon destruction of
+ * `ScopeGuard`.
+ *
+ * Example:
+ *
+ * auto guard = makeScopeGuard([&] { cleanup(); });
+ */
+template
+class ScopeGuard {
+ Function function;
+ bool dismissed;
+
+ public:
+ explicit ScopeGuard(Function&& function)
+ : function(std::move(function)), dismissed(false) {}
+
+ void dismiss() {
+ dismissed = true;
+ }
+
+ ~ScopeGuard() noexcept {
+ if (!dismissed) {
+ function();
+ }
+ }
+};
+
+/// Creates a scope guard from `function`.
+template
+ScopeGuard makeScopeGuard(Function&& function) {
+ return ScopeGuard(std::forward(function));
+}
+}
diff --git a/contrib/pzstd/utils/ThreadPool.h b/contrib/pzstd/utils/ThreadPool.h
new file mode 100644
index 000000000..a1d1fc0b9
--- /dev/null
+++ b/contrib/pzstd/utils/ThreadPool.h
@@ -0,0 +1,58 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include "utils/WorkQueue.h"
+
+#include
+#include
+#include
+#include
+
+namespace pzstd {
+/// A simple thread pool that pulls tasks off its queue in FIFO order.
+class ThreadPool {
+ std::vector threads_;
+
+ WorkQueue> tasks_;
+
+ public:
+ /// Constructs a thread pool with `numThreads` threads.
+ explicit ThreadPool(std::size_t numThreads) {
+ threads_.reserve(numThreads);
+ for (std::size_t i = 0; i < numThreads; ++i) {
+ threads_.emplace_back([&] {
+ std::function task;
+ while (tasks_.pop(task)) {
+ task();
+ }
+ });
+ }
+ }
+
+ /// Finishes all tasks currently in the queue.
+ ~ThreadPool() {
+ tasks_.finish();
+ for (auto& thread : threads_) {
+ thread.join();
+ }
+ }
+
+ /**
+ * Adds `task` to the queue of tasks to execute. Since `task` is a
+ * `std::function<>`, it cannot be a move only type. So any lambda passed must
+ * not capture move only types (like `std::unique_ptr`).
+ *
+ * @param task The task to execute.
+ */
+ void add(std::function task) {
+ tasks_.push(std::move(task));
+ }
+};
+}
diff --git a/contrib/pzstd/utils/WorkQueue.h b/contrib/pzstd/utils/WorkQueue.h
new file mode 100644
index 000000000..538213500
--- /dev/null
+++ b/contrib/pzstd/utils/WorkQueue.h
@@ -0,0 +1,184 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include "utils/Buffer.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace pzstd {
+
+/// Unbounded thread-safe work queue.
+template
+class WorkQueue {
+ // Protects all member variable access
+ std::mutex mutex_;
+ std::condition_variable readerCv_;
+ std::condition_variable writerCv_;
+
+ std::queue queue_;
+ bool done_;
+ std::size_t maxSize_;
+
+ // Must have lock to call this function
+ bool full() const {
+ if (maxSize_ == 0) {
+ return false;
+ }
+ return queue_.size() >= maxSize_;
+ }
+
+ public:
+ /**
+ * Constructs an empty work queue with an optional max size.
+ * If `maxSize == 0` the queue size is unbounded.
+ *
+ * @param maxSize The maximum allowed size of the work queue.
+ */
+ WorkQueue(std::size_t maxSize = 0) : done_(false), maxSize_(maxSize) {}
+
+ /**
+ * Push an item onto the work queue. Notify a single thread that work is
+ * available. If `finish()` has been called, do nothing and return false.
+ *
+ * @param item Item to push onto the queue.
+ * @returns True upon success, false if `finish()` has been called. An
+ * item was pushed iff `push()` returns true.
+ */
+ bool push(T item) {
+ {
+ std::unique_lock lock(mutex_);
+ while (full() && !done_) {
+ writerCv_.wait(lock);
+ }
+ if (done_) {
+ return false;
+ }
+ queue_.push(std::move(item));
+ }
+ readerCv_.notify_one();
+ return true;
+ }
+
+ /**
+ * Attempts to pop an item off the work queue. It will block until data is
+ * available or `finish()` has been called.
+ *
+ * @param[out] item If `pop` returns `true`, it contains the popped item.
+ * If `pop` returns `false`, it is unmodified.
+ * @returns True upon success. False if the queue is empty and
+ * `finish()` has been called.
+ */
+ bool pop(T& item) {
+ {
+ std::unique_lock lock(mutex_);
+ while (queue_.empty() && !done_) {
+ readerCv_.wait(lock);
+ }
+ if (queue_.empty()) {
+ assert(done_);
+ return false;
+ }
+ item = std::move(queue_.front());
+ queue_.pop();
+ }
+ writerCv_.notify_one();
+ return true;
+ }
+
+ /**
+ * Sets the maximum queue size. If `maxSize == 0` then it is unbounded.
+ *
+ * @param maxSize The new maximum queue size.
+ */
+ void setMaxSize(std::size_t maxSize) {
+ {
+ std::lock_guard lock(mutex_);
+ maxSize_ = maxSize;
+ }
+ writerCv_.notify_all();
+ }
+
+ /**
+ * Promise that `push()` won't be called again, so once the queue is empty
+ * there will never any more work.
+ */
+ void finish() {
+ {
+ std::lock_guard lock(mutex_);
+ assert(!done_);
+ done_ = true;
+ }
+ readerCv_.notify_all();
+ writerCv_.notify_all();
+ }
+
+ /// Blocks until `finish()` has been called (but the queue may not be empty).
+ void waitUntilFinished() {
+ std::unique_lock lock(mutex_);
+ while (!done_) {
+ readerCv_.wait(lock);
+ // If we were woken by a push, we need to wake a thread waiting on pop().
+ if (!done_) {
+ lock.unlock();
+ readerCv_.notify_one();
+ lock.lock();
+ }
+ }
+ }
+};
+
+/// Work queue for `Buffer`s that knows the total number of bytes in the queue.
+class BufferWorkQueue {
+ WorkQueue queue_;
+ std::atomic size_;
+
+ public:
+ BufferWorkQueue(std::size_t maxSize = 0) : queue_(maxSize), size_(0) {}
+
+ void push(Buffer buffer) {
+ size_.fetch_add(buffer.size());
+ queue_.push(std::move(buffer));
+ }
+
+ bool pop(Buffer& buffer) {
+ bool result = queue_.pop(buffer);
+ if (result) {
+ size_.fetch_sub(buffer.size());
+ }
+ return result;
+ }
+
+ void setMaxSize(std::size_t maxSize) {
+ queue_.setMaxSize(maxSize);
+ }
+
+ void finish() {
+ queue_.finish();
+ }
+
+ /**
+ * Blocks until `finish()` has been called.
+ *
+ * @returns The total number of bytes of all the `Buffer`s currently in the
+ * queue.
+ */
+ std::size_t size() {
+ queue_.waitUntilFinished();
+ return size_.load();
+ }
+};
+}
diff --git a/contrib/pzstd/utils/test/BufferTest.cpp b/contrib/pzstd/utils/test/BufferTest.cpp
new file mode 100644
index 000000000..66ec961e2
--- /dev/null
+++ b/contrib/pzstd/utils/test/BufferTest.cpp
@@ -0,0 +1,89 @@
+/**
+ * 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.
+ */
+#include "utils/Buffer.h"
+#include "utils/Range.h"
+
+#include
+#include
+
+using namespace pzstd;
+
+namespace {
+void deleter(const unsigned char* buf) {
+ delete[] buf;
+}
+}
+
+TEST(Buffer, Constructors) {
+ Buffer empty;
+ EXPECT_TRUE(empty.empty());
+ EXPECT_EQ(0, empty.size());
+
+ Buffer sized(5);
+ EXPECT_FALSE(sized.empty());
+ EXPECT_EQ(5, sized.size());
+
+ Buffer moved(std::move(sized));
+ EXPECT_FALSE(sized.empty());
+ EXPECT_EQ(5, sized.size());
+
+ Buffer assigned;
+ assigned = std::move(moved);
+ EXPECT_FALSE(sized.empty());
+ EXPECT_EQ(5, sized.size());
+}
+
+TEST(Buffer, BufferManagement) {
+ std::shared_ptr buf(new unsigned char[10], deleter);
+ {
+ Buffer acquired(buf, MutableByteRange(buf.get(), buf.get() + 10));
+ EXPECT_EQ(2, buf.use_count());
+ Buffer moved(std::move(acquired));
+ EXPECT_EQ(2, buf.use_count());
+ Buffer assigned;
+ assigned = std::move(moved);
+ EXPECT_EQ(2, buf.use_count());
+
+ Buffer split = assigned.splitAt(5);
+ EXPECT_EQ(3, buf.use_count());
+
+ split.advance(1);
+ assigned.subtract(1);
+ EXPECT_EQ(3, buf.use_count());
+ }
+ EXPECT_EQ(1, buf.use_count());
+}
+
+TEST(Buffer, Modifiers) {
+ Buffer buf(10);
+ {
+ unsigned char i = 0;
+ for (auto& byte : buf.range()) {
+ byte = i++;
+ }
+ }
+
+ auto prefix = buf.splitAt(2);
+
+ ASSERT_EQ(2, prefix.size());
+ EXPECT_EQ(0, *prefix.data());
+
+ ASSERT_EQ(8, buf.size());
+ EXPECT_EQ(2, *buf.data());
+
+ buf.advance(2);
+ EXPECT_EQ(4, *buf.data());
+
+ EXPECT_EQ(9, *(buf.range().end() - 1));
+
+ buf.subtract(2);
+ EXPECT_EQ(7, *(buf.range().end() - 1));
+
+ EXPECT_EQ(4, buf.size());
+}
diff --git a/contrib/pzstd/utils/test/Makefile b/contrib/pzstd/utils/test/Makefile
new file mode 100644
index 000000000..b9ea73e32
--- /dev/null
+++ b/contrib/pzstd/utils/test/Makefile
@@ -0,0 +1,42 @@
+# ##########################################################################
+# 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.
+# ##########################################################################
+
+# Define *.exe as extension for Windows systems
+ifneq (,$(filter Windows%,$(OS)))
+EXT =.exe
+else
+EXT =
+endif
+
+PZSTDDIR = ../..
+
+# Set GTEST_INC and GTEST_LIB to work with your install of gtest
+GTEST_INC ?= -isystem $(PZSTDDIR)/googletest/googletest/include
+GTEST_LIB ?= -L $(PZSTDDIR)/googletest/build/googlemock/gtest
+
+CPPFLAGS = -I$(PZSTDDIR) $(GTEST_INC) $(GTEST_LIB)
+CXXFLAGS ?= -O3
+CXXFLAGS += -std=c++11
+CXXFLAGS += $(MOREFLAGS)
+FLAGS = $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS)
+
+%: %.cpp
+ $(CXX) $(FLAGS) $^ -o $@$(EXT) -lgtest -lgtest_main -lpthread
+
+.PHONY: test clean
+
+test: BufferTest RangeTest ScopeGuardTest ThreadPoolTest WorkQueueTest
+ @./BufferTest$(EXT)
+ @./RangeTest$(EXT)
+ @./ScopeGuardTest$(EXT)
+ @./ThreadPoolTest$(EXT)
+ @./WorkQueueTest$(EXT)
+
+clean:
+ @rm -f BufferTest RangeTest ScopeGuardTest ThreadPoolTest WorkQueueTest
diff --git a/contrib/pzstd/utils/test/RangeTest.cpp b/contrib/pzstd/utils/test/RangeTest.cpp
new file mode 100644
index 000000000..c761c8aff
--- /dev/null
+++ b/contrib/pzstd/utils/test/RangeTest.cpp
@@ -0,0 +1,82 @@
+/**
+ * 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.
+ */
+#include "utils/Range.h"
+
+#include
+#include
+
+using namespace pzstd;
+
+// Range is directly copied from folly.
+// Just some sanity tests to make sure everything seems to work.
+
+TEST(Range, Constructors) {
+ StringPiece empty;
+ EXPECT_TRUE(empty.empty());
+ EXPECT_EQ(0, empty.size());
+
+ std::string str = "hello";
+ {
+ Range piece(str.begin(), str.end());
+ EXPECT_EQ(5, piece.size());
+ EXPECT_EQ('h', *piece.data());
+ EXPECT_EQ('o', *(piece.end() - 1));
+ }
+
+ {
+ StringPiece piece(str.data(), str.size());
+ EXPECT_EQ(5, piece.size());
+ EXPECT_EQ('h', *piece.data());
+ EXPECT_EQ('o', *(piece.end() - 1));
+ }
+
+ {
+ StringPiece piece(str);
+ EXPECT_EQ(5, piece.size());
+ EXPECT_EQ('h', *piece.data());
+ EXPECT_EQ('o', *(piece.end() - 1));
+ }
+
+ {
+ StringPiece piece(str.c_str());
+ EXPECT_EQ(5, piece.size());
+ EXPECT_EQ('h', *piece.data());
+ EXPECT_EQ('o', *(piece.end() - 1));
+ }
+}
+
+TEST(Range, Modifiers) {
+ StringPiece range("hello world");
+ ASSERT_EQ(11, range.size());
+
+ {
+ auto hello = range.subpiece(0, 5);
+ EXPECT_EQ(5, hello.size());
+ EXPECT_EQ('h', *hello.data());
+ EXPECT_EQ('o', *(hello.end() - 1));
+ }
+ {
+ auto hello = range;
+ hello.subtract(6);
+ EXPECT_EQ(5, hello.size());
+ EXPECT_EQ('h', *hello.data());
+ EXPECT_EQ('o', *(hello.end() - 1));
+ }
+ {
+ auto world = range;
+ world.advance(6);
+ EXPECT_EQ(5, world.size());
+ EXPECT_EQ('w', *world.data());
+ EXPECT_EQ('d', *(world.end() - 1));
+ }
+
+ std::string expected = "hello world";
+ EXPECT_EQ(expected, std::string(range.begin(), range.end()));
+ EXPECT_EQ(expected, std::string(range.data(), range.size()));
+}
diff --git a/contrib/pzstd/utils/test/ScopeGuardTest.cpp b/contrib/pzstd/utils/test/ScopeGuardTest.cpp
new file mode 100644
index 000000000..0c4dc0357
--- /dev/null
+++ b/contrib/pzstd/utils/test/ScopeGuardTest.cpp
@@ -0,0 +1,28 @@
+/**
+ * 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.
+ */
+#include "utils/ScopeGuard.h"
+
+#include
+
+using namespace pzstd;
+
+TEST(ScopeGuard, Dismiss) {
+ {
+ auto guard = makeScopeGuard([&] { EXPECT_TRUE(false); });
+ guard.dismiss();
+ }
+}
+
+TEST(ScopeGuard, Executes) {
+ bool executed = false;
+ {
+ auto guard = makeScopeGuard([&] { executed = true; });
+ }
+ EXPECT_TRUE(executed);
+}
diff --git a/contrib/pzstd/utils/test/ThreadPoolTest.cpp b/contrib/pzstd/utils/test/ThreadPoolTest.cpp
new file mode 100644
index 000000000..1d857aae8
--- /dev/null
+++ b/contrib/pzstd/utils/test/ThreadPoolTest.cpp
@@ -0,0 +1,67 @@
+/**
+ * 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.
+ */
+#include "utils/ThreadPool.h"
+
+#include
+#include
+#include
+#include
+
+using namespace pzstd;
+
+TEST(ThreadPool, Ordering) {
+ std::vector results;
+
+ {
+ ThreadPool executor(1);
+ for (int i = 0; i < 10; ++i) {
+ executor.add([ &results, i ] { results.push_back(i); });
+ }
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_EQ(i, results[i]);
+ }
+}
+
+TEST(ThreadPool, AllJobsFinished) {
+ std::atomic numFinished{0};
+ std::atomic start{false};
+ {
+ ThreadPool executor(5);
+ for (int i = 0; i < 10; ++i) {
+ executor.add([ &numFinished, &start ] {
+ while (!start.load()) {
+ // spin
+ }
+ ++numFinished;
+ });
+ }
+ start.store(true);
+ }
+ EXPECT_EQ(10, numFinished.load());
+}
+
+TEST(ThreadPool, AddJobWhileJoining) {
+ std::atomic done{false};
+ {
+ ThreadPool executor(1);
+ executor.add([&executor, &done] {
+ while (!done.load()) {
+ std::this_thread::yield();
+ }
+ // Sleep for a second to be sure that we are joining
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ executor.add([] {
+ EXPECT_TRUE(false);
+ });
+ });
+ done.store(true);
+ }
+}
diff --git a/contrib/pzstd/utils/test/WorkQueueTest.cpp b/contrib/pzstd/utils/test/WorkQueueTest.cpp
new file mode 100644
index 000000000..ebf375a84
--- /dev/null
+++ b/contrib/pzstd/utils/test/WorkQueueTest.cpp
@@ -0,0 +1,262 @@
+/**
+ * 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.
+ */
+#include "utils/Buffer.h"
+#include "utils/WorkQueue.h"
+
+#include
+#include
+#include
+#include
+
+using namespace pzstd;
+
+namespace {
+struct Popper {
+ WorkQueue* queue;
+ int* results;
+ std::mutex* mutex;
+
+ void operator()() {
+ int result;
+ while (queue->pop(result)) {
+ std::lock_guard lock(*mutex);
+ results[result] = result;
+ }
+ }
+};
+}
+
+TEST(WorkQueue, SingleThreaded) {
+ WorkQueue queue;
+ int result;
+
+ queue.push(5);
+ EXPECT_TRUE(queue.pop(result));
+ EXPECT_EQ(5, result);
+
+ queue.push(1);
+ queue.push(2);
+ EXPECT_TRUE(queue.pop(result));
+ EXPECT_EQ(1, result);
+ EXPECT_TRUE(queue.pop(result));
+ EXPECT_EQ(2, result);
+
+ queue.push(1);
+ queue.push(2);
+ queue.finish();
+ EXPECT_TRUE(queue.pop(result));
+ EXPECT_EQ(1, result);
+ EXPECT_TRUE(queue.pop(result));
+ EXPECT_EQ(2, result);
+ EXPECT_FALSE(queue.pop(result));
+
+ queue.waitUntilFinished();
+}
+
+TEST(WorkQueue, SPSC) {
+ WorkQueue queue;
+ const int max = 100;
+
+ for (int i = 0; i < 10; ++i) {
+ queue.push(i);
+ }
+
+ std::thread thread([ &queue, max ] {
+ int result;
+ for (int i = 0;; ++i) {
+ if (!queue.pop(result)) {
+ EXPECT_EQ(i, max);
+ break;
+ }
+ EXPECT_EQ(i, result);
+ }
+ });
+
+ std::this_thread::yield();
+ for (int i = 10; i < max; ++i) {
+ queue.push(i);
+ }
+ queue.finish();
+
+ thread.join();
+}
+
+TEST(WorkQueue, SPMC) {
+ WorkQueue queue;
+ std::vector results(50, -1);
+ std::mutex mutex;
+ std::vector threads;
+ for (int i = 0; i < 5; ++i) {
+ threads.emplace_back(Popper{&queue, results.data(), &mutex});
+ }
+
+ for (int i = 0; i < 50; ++i) {
+ queue.push(i);
+ }
+ queue.finish();
+
+ for (auto& thread : threads) {
+ thread.join();
+ }
+
+ for (int i = 0; i < 50; ++i) {
+ EXPECT_EQ(i, results[i]);
+ }
+}
+
+TEST(WorkQueue, MPMC) {
+ WorkQueue queue;
+ std::vector results(100, -1);
+ std::mutex mutex;
+ std::vector popperThreads;
+ for (int i = 0; i < 4; ++i) {
+ popperThreads.emplace_back(Popper{&queue, results.data(), &mutex});
+ }
+
+ std::vector pusherThreads;
+ for (int i = 0; i < 2; ++i) {
+ auto min = i * 50;
+ auto max = (i + 1) * 50;
+ pusherThreads.emplace_back(
+ [ &queue, min, max ] {
+ for (int i = min; i < max; ++i) {
+ queue.push(i);
+ }
+ });
+ }
+
+ for (auto& thread : pusherThreads) {
+ thread.join();
+ }
+ queue.finish();
+
+ for (auto& thread : popperThreads) {
+ thread.join();
+ }
+
+ for (int i = 0; i < 100; ++i) {
+ EXPECT_EQ(i, results[i]);
+ }
+}
+
+TEST(WorkQueue, BoundedSizeWorks) {
+ WorkQueue queue(1);
+ int result;
+ queue.push(5);
+ queue.pop(result);
+ queue.push(5);
+ queue.pop(result);
+ queue.push(5);
+ queue.finish();
+ queue.pop(result);
+ EXPECT_EQ(5, result);
+}
+
+TEST(WorkQueue, BoundedSizePushAfterFinish) {
+ WorkQueue queue(1);
+ int result;
+ queue.push(5);
+ std::thread pusher([&queue] {
+ queue.push(6);
+ });
+ // Dirtily try and make sure that pusher has run.
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ queue.finish();
+ EXPECT_TRUE(queue.pop(result));
+ EXPECT_EQ(5, result);
+ EXPECT_FALSE(queue.pop(result));
+
+ pusher.join();
+}
+
+TEST(WorkQueue, SetMaxSize) {
+ WorkQueue queue(2);
+ int result;
+ queue.push(5);
+ queue.push(6);
+ queue.setMaxSize(1);
+ std::thread pusher([&queue] {
+ queue.push(7);
+ });
+ // Dirtily try and make sure that pusher has run.
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ queue.finish();
+ EXPECT_TRUE(queue.pop(result));
+ EXPECT_EQ(5, result);
+ EXPECT_TRUE(queue.pop(result));
+ EXPECT_EQ(6, result);
+ EXPECT_FALSE(queue.pop(result));
+
+ pusher.join();
+}
+
+TEST(WorkQueue, BoundedSizeMPMC) {
+ WorkQueue queue(10);
+ std::vector results(200, -1);
+ std::mutex mutex;
+ std::vector popperThreads;
+ for (int i = 0; i < 4; ++i) {
+ popperThreads.emplace_back(Popper{&queue, results.data(), &mutex});
+ }
+
+ std::vector pusherThreads;
+ for (int i = 0; i < 2; ++i) {
+ auto min = i * 100;
+ auto max = (i + 1) * 100;
+ pusherThreads.emplace_back(
+ [ &queue, min, max ] {
+ for (int i = min; i < max; ++i) {
+ queue.push(i);
+ }
+ });
+ }
+
+ for (auto& thread : pusherThreads) {
+ thread.join();
+ }
+ queue.finish();
+
+ for (auto& thread : popperThreads) {
+ thread.join();
+ }
+
+ for (int i = 0; i < 200; ++i) {
+ EXPECT_EQ(i, results[i]);
+ }
+}
+
+TEST(BufferWorkQueue, SizeCalculatedCorrectly) {
+ {
+ BufferWorkQueue queue;
+ queue.finish();
+ EXPECT_EQ(0, queue.size());
+ }
+ {
+ BufferWorkQueue queue;
+ queue.push(Buffer(10));
+ queue.finish();
+ EXPECT_EQ(10, queue.size());
+ }
+ {
+ BufferWorkQueue queue;
+ queue.push(Buffer(10));
+ queue.push(Buffer(5));
+ queue.finish();
+ EXPECT_EQ(15, queue.size());
+ }
+ {
+ BufferWorkQueue queue;
+ queue.push(Buffer(10));
+ queue.push(Buffer(5));
+ queue.finish();
+ Buffer buffer;
+ queue.pop(buffer);
+ EXPECT_EQ(5, queue.size());
+ }
+}
diff --git a/examples/Makefile b/examples/Makefile
index a9d608778..54602dfe0 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -55,20 +55,21 @@ streaming_decompression : streaming_decompression.c
clean:
@rm -f core *.o tmp* result* *.zst \
simple_compression simple_decompression \
- dictionary_compression dictionary_decompression \
- streaming_compression streaming_decompression
+ dictionary_compression dictionary_decompression \
+ streaming_compression streaming_decompression
@echo Cleaning completed
test: all
cp README.md tmp
+ cp Makefile tmp2
@echo starting simple compression
./simple_compression tmp
./simple_decompression tmp.zst
- ./streaming_decompression tmp.zst
+ ./streaming_decompression tmp.zst > /dev/null
@echo starting streaming compression
./streaming_compression tmp
- ./streaming_decompression tmp.zst
+ ./streaming_decompression tmp.zst > /dev/null
@echo starting dictionary compression
- ./dictionary_compression tmp README.md
- ./dictionary_decompression tmp.zst README.md
+ ./dictionary_compression tmp2 tmp README.md
+ ./dictionary_decompression tmp2.zst tmp.zst README.md
@echo tests completed
diff --git a/examples/README.md b/examples/README.md
index 2f4603881..ba132f6c3 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,18 +1,31 @@
Zstandard library : usage examples
==================================
-- [Simple compression](simple_compression.c)
+- [Simple compression](simple_compression.c) :
Compress a single file.
Introduces usage of : `ZSTD_compress()`
-- [Simple decompression](simple_decompression.c)
- Decompress a single file compressed by zstd.
+- [Simple decompression](simple_decompression.c) :
+ Decompress a single file.
+ Only compatible with simple compression.
+ Result remains in memory.
Introduces usage of : `ZSTD_decompress()`
-- [Dictionary compression](dictionary_compression.c)
+- [Streaming compression](streaming_compression.c) :
+ Compress a single file.
+ Introduces usage of : `ZSTD_compressStream()`
+
+- [Streaming decompression](streaming_decompression.c) :
+ Decompress a single file compressed by zstd.
+ Compatible with both simple and streaming compression.
+ Result is sent to stdout.
+ Introduces usage of : `ZSTD_decompressStream()`
+
+- [Dictionary compression](dictionary_compression.c) :
Compress multiple files using the same dictionary.
Introduces usage of : `ZSTD_createCDict()` and `ZSTD_compress_usingCDict()`
-- [Dictionary decompression](dictionary_decompression.c)
+- [Dictionary decompression](dictionary_decompression.c) :
Decompress multiple files using the same dictionary.
+ Result remains in memory.
Introduces usage of : `ZSTD_createDDict()` and `ZSTD_decompress_usingDDict()`
diff --git a/examples/dictionary_compression.c b/examples/dictionary_compression.c
index 08d639c03..adcc3b4d5 100644
--- a/examples/dictionary_compression.c
+++ b/examples/dictionary_compression.c
@@ -73,12 +73,12 @@ static void saveFile_orDie(const char* fileName, const void* buff, size_t buffSi
/* createDict() :
`dictFileName` is supposed to have been created using `zstd --train` */
-static ZSTD_CDict* createCDict_orDie(const char* dictFileName)
+static ZSTD_CDict* createCDict_orDie(const char* dictFileName, int cLevel)
{
size_t dictSize;
printf("loading dictionary %s \n", dictFileName);
void* const dictBuffer = loadFile_orDie(dictFileName, &dictSize);
- ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 3);
+ ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel);
if (!cdict) {
fprintf(stderr, "ZSTD_createCDict error \n");
exit(7);
@@ -96,6 +96,7 @@ static void compress(const char* fname, const char* oname, const ZSTD_CDict* cdi
void* const cBuff = malloc_orDie(cBuffSize);
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
+ if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); }
size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict);
if (ZSTD_isError(cSize)) {
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
@@ -107,7 +108,7 @@ static void compress(const char* fname, const char* oname, const ZSTD_CDict* cdi
/* success */
printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname);
- ZSTD_freeCCtx(cctx);
+ ZSTD_freeCCtx(cctx); /* never fails */
free(fBuff);
free(cBuff);
}
@@ -127,6 +128,7 @@ static char* createOutFilename_orDie(const char* filename)
int main(int argc, const char** argv)
{
const char* const exeName = argv[0];
+ int const cLevel = 3;
if (argc<3) {
fprintf(stderr, "wrong arguments\n");
@@ -137,7 +139,7 @@ int main(int argc, const char** argv)
/* load dictionary only once */
const char* const dictName = argv[argc-1];
- ZSTD_CDict* const dictPtr = createCDict_orDie(dictName);
+ ZSTD_CDict* const dictPtr = createCDict_orDie(dictName, cLevel);
int u;
for (u=1; u buffInSize) toRead = buffInSize; /* Safely handle when `buffInSize` is manually changed to a smaller value */
fwrite_orDie(buffOut, output.pos, fout);
}
}
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
- size_t const remainingToFlush = ZSTD_endStream(cstream, &output);
- if (remainingToFlush) { fprintf(stderr, "not fully flushed"); exit(12); }
+ size_t const remainingToFlush = ZSTD_endStream(cstream, &output); /* close frame */
+ if (remainingToFlush) { fprintf(stderr, "not fully flushed"); exit(13); }
fwrite_orDie(buffOut, output.pos, fout);
+ ZSTD_freeCStream(cstream);
fclose_orDie(fout);
fclose_orDie(fin);
free(buffIn);
diff --git a/examples/streaming_decompression.c b/examples/streaming_decompression.c
index d4dfacb2d..1ba1a3d81 100644
--- a/examples/streaming_decompression.c
+++ b/examples/streaming_decompression.c
@@ -42,6 +42,15 @@ static size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)
exit(4);
}
+static size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)
+{
+ size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);
+ if (writtenSize == sizeToWrite) return sizeToWrite; /* good */
+ /* error */
+ perror("fwrite");
+ exit(5);
+}
+
static size_t fclose_orDie(FILE* file)
{
if (!fclose(file)) return 0;
@@ -54,28 +63,31 @@ static size_t fclose_orDie(FILE* file)
static void decompressFile_orDie(const char* fname)
{
FILE* const fin = fopen_orDie(fname, "rb");
- size_t const buffInSize = ZSTD_DStreamInSize();;
+ size_t const buffInSize = ZSTD_DStreamInSize();
void* const buffIn = malloc_orDie(buffInSize);
- size_t const buffOutSize = ZSTD_DStreamOutSize();;
+ FILE* const fout = stdout;
+ size_t const buffOutSize = ZSTD_DStreamOutSize(); /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */
void* const buffOut = malloc_orDie(buffOutSize);
- size_t read, toRead = buffInSize;
ZSTD_DStream* const dstream = ZSTD_createDStream();
if (dstream==NULL) { fprintf(stderr, "ZSTD_createDStream() error \n"); exit(10); }
size_t const initResult = ZSTD_initDStream(dstream);
- if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initDStream() error \n"); exit(11); }
+ if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initDStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); }
- while( (read = fread_orDie(buffIn, toRead, fin)) ) {
+ size_t read, toRead = initResult;
+ while ( (read = fread_orDie(buffIn, toRead, fin)) ) {
ZSTD_inBuffer input = { buffIn, read, 0 };
while (input.pos < input.size) {
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
- toRead = ZSTD_decompressStream(dstream, &output , &input);
- /* note : data is just "sinked" into buffOut
- a more complete example would write it to disk or stdout */
+ toRead = ZSTD_decompressStream(dstream, &output , &input); /* toRead : size of next compressed block */
+ if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_decompressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); }
+ fwrite_orDie(buffOut, output.pos, fout);
}
}
+ ZSTD_freeDStream(dstream);
fclose_orDie(fin);
+ fclose_orDie(fout);
free(buffIn);
free(buffOut);
}
@@ -87,14 +99,12 @@ int main(int argc, const char** argv)
const char* const inFilename = argv[1];
if (argc!=2) {
- printf("wrong arguments\n");
- printf("usage:\n");
- printf("%s FILE\n", exeName);
+ fprintf(stderr, "wrong arguments\n");
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, "%s FILE\n", exeName);
return 1;
}
decompressFile_orDie(inFilename);
- printf("%s correctly decoded (in memory). \n", inFilename);
-
return 0;
}
diff --git a/lib/Makefile b/lib/Makefile
index 35522da6d..4fb8ed9d2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -78,7 +78,7 @@ clean:
#------------------------------------------------------------------------
#make install is validated only for Linux, OSX, kFreeBSD, Hurd and some BSD targets
-ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU FreeBSD DragonFly))
+ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU FreeBSD DragonFly NetBSD))
libzstd.pc:
libzstd.pc: libzstd.pc.in
@@ -105,11 +105,11 @@ uninstall:
$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)
$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)
$(RM) $(DESTDIR)$(LIBDIR)/pkgconfig/libzstd.pc
- [ -x $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_VER) ] && $(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_VER)
- @[ -f $(DESTDIR)$(LIBDIR)/libzstd.a ] && $(RM) $(DESTDIR)$(LIBDIR)/libzstd.a
- @[ -f $(DESTDIR)$(INCLUDEDIR)/zstd.h ] && $(RM) $(DESTDIR)$(INCLUDEDIR)/zstd.h
- @[ -f $(DESTDIR)$(INCLUDEDIR)/zbuff.h ] && $(RM) $(DESTDIR)$(INCLUDEDIR)/zbuff.h
- @[ -f $(DESTDIR)$(INCLUDEDIR)/zdict.h ] && $(RM) $(DESTDIR)$(INCLUDEDIR)/zdict.h
+ $(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_VER)
+ $(RM) $(DESTDIR)$(LIBDIR)/libzstd.a
+ $(RM) $(DESTDIR)$(INCLUDEDIR)/zstd.h
+ $(RM) $(DESTDIR)$(INCLUDEDIR)/zbuff.h
+ $(RM) $(DESTDIR)$(INCLUDEDIR)/zdict.h
@echo zstd libraries successfully uninstalled
endif
diff --git a/lib/common/fse_decompress.c b/lib/common/fse_decompress.c
index 032e65771..7492a3832 100644
--- a/lib/common/fse_decompress.c
+++ b/lib/common/fse_decompress.c
@@ -42,12 +42,15 @@
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
# else
-# define FORCE_INLINE static inline
-# endif
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
#endif
diff --git a/lib/common/xxhash.c b/lib/common/xxhash.c
index f462c57f8..29e4fa628 100644
--- a/lib/common/xxhash.c
+++ b/lib/common/xxhash.c
@@ -115,7 +115,7 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcp
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# define FORCE_INLINE static __forceinline
#else
-# if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
# ifdef __GNUC__
# define FORCE_INLINE static inline __attribute__((always_inline))
# else
diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h
index 51e7170ec..f40e00aab 100644
--- a/lib/common/zstd_internal.h
+++ b/lib/common/zstd_internal.h
@@ -10,6 +10,28 @@
#ifndef ZSTD_CCOMMON_H_MODULE
#define ZSTD_CCOMMON_H_MODULE
+/*-*******************************************************
+* Compiler specifics
+*********************************************************/
+#ifdef _MSC_VER /* Visual Studio */
+# define FORCE_INLINE static __forceinline
+# include /* For Visual 2005 */
+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
+# pragma warning(disable : 4324) /* disable: C4324: padded structure */
+# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
+#else
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
+# else
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
+#endif
+
+
/*-*************************************
* Dependencies
***************************************/
@@ -20,10 +42,12 @@
/*-*************************************
-* Common macros
+* shared macros
***************************************/
#define MIN(a,b) ((a)<(b) ? (a) : (b))
#define MAX(a,b) ((a)>(b) ? (a) : (b))
+#define CHECK_F(f) { size_t const errcod = f; if (ERR_isError(errcod)) return errcod; } /* check and Forward error code */
+#define CHECK_E(f, e) { size_t const errcod = f; if (ERR_isError(errcod)) return ERROR(e); } /* check and send Error code */
/*-*************************************
@@ -84,7 +108,8 @@ static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
-1,-1,-1,-1 };
-static const U32 LL_defaultNormLog = 6;
+#define LL_DEFAULTNORMLOG 6 /* for static allocation */
+static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -94,11 +119,13 @@ static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,
-1,-1,-1,-1,-1 };
-static const U32 ML_defaultNormLog = 6;
+#define ML_DEFAULTNORMLOG 6 /* for static allocation */
+static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
static const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };
-static const U32 OF_defaultNormLog = 5;
+#define OF_DEFAULTNORMLOG 5 /* for static allocation */
+static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
/*-*******************************************
diff --git a/lib/compress/fse_compress.c b/lib/compress/fse_compress.c
index 386b2c010..679dbdb83 100644
--- a/lib/compress/fse_compress.c
+++ b/lib/compress/fse_compress.c
@@ -41,12 +41,15 @@
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
# else
-# define FORCE_INLINE static inline
-# endif
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
#endif
diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c
index c2dd13c87..b7d3d77a2 100644
--- a/lib/compress/huf_compress.c
+++ b/lib/compress/huf_compress.c
@@ -35,24 +35,8 @@
/* **************************************************************
* Compiler specifics
****************************************************************/
-#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-/* inline is defined */
-#elif defined(_MSC_VER)
-# define inline __inline
-#else
-# define inline /* disable inline */
-#endif
-
-
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#else
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index 0116136c0..94f4b5a25 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -8,30 +8,13 @@
*/
-
-/*-*******************************************************
-* Compiler specifics
-*********************************************************/
-#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
-# include /* For Visual 2005 */
-# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#else
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
-#endif
-
-
/*-*************************************
* Dependencies
***************************************/
#include /* memset */
#include "mem.h"
#define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
-#include "xxhash.h" /* XXH_reset, update, digest */
+#include "xxhash.h" /* XXH_reset, update, digest */
#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
#include "fse.h"
#define HUF_STATIC_LINKING_ONLY
@@ -116,7 +99,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
cctx = (ZSTD_CCtx*) ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
if (!cctx) return NULL;
memset(cctx, 0, sizeof(ZSTD_CCtx));
- memcpy(&(cctx->customMem), &customMem, sizeof(ZSTD_customMem));
+ memcpy(&(cctx->customMem), &customMem, sizeof(customMem));
return cctx;
}
@@ -130,6 +113,7 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
{
+ if (cctx==NULL) return 0; /* support sizeof on NULL */
return sizeof(*cctx) + cctx->workSpaceSize;
}
@@ -139,19 +123,17 @@ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) /* hidden interface *
}
-#define CLAMP(val,min,max) { if (valmax) val=max; }
-#define CLAMPCHECK(val,min,max) { if ((valmax)) return ERROR(compressionParameter_unsupported); }
-
/** ZSTD_checkParams() :
ensure param values remain within authorized range.
@return : 0, or an error code if one value is beyond authorized range */
size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
{
+# define CLAMPCHECK(val,min,max) { if ((valmax)) return ERROR(compressionParameter_unsupported); }
CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
- { U32 const searchLengthMin = (cParams.strategy == ZSTD_fast || cParams.strategy == ZSTD_greedy) ? ZSTD_SEARCHLENGTH_MIN+1 : ZSTD_SEARCHLENGTH_MIN;
+ { U32 const searchLengthMin = ((cParams.strategy == ZSTD_fast) | (cParams.strategy == ZSTD_greedy)) ? ZSTD_SEARCHLENGTH_MIN+1 : ZSTD_SEARCHLENGTH_MIN;
U32 const searchLengthMax = (cParams.strategy == ZSTD_fast) ? ZSTD_SEARCHLENGTH_MAX : ZSTD_SEARCHLENGTH_MAX-1;
CLAMPCHECK(cParams.searchLength, searchLengthMin, searchLengthMax); }
CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
@@ -160,21 +142,8 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
}
-/** ZSTD_checkCParams_advanced() :
- temporary work-around, while the compressor compatibility remains limited regarding windowLog < 18 */
-size_t ZSTD_checkCParams_advanced(ZSTD_compressionParameters cParams, U64 srcSize)
-{
- if (srcSize > (1ULL << ZSTD_WINDOWLOG_MIN)) return ZSTD_checkCParams(cParams);
- if (cParams.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) return ERROR(compressionParameter_unsupported);
- if (srcSize <= (1ULL << cParams.windowLog)) cParams.windowLog = ZSTD_WINDOWLOG_MIN; /* fake value - temporary work around */
- if (srcSize <= (1ULL << cParams.chainLog)) cParams.chainLog = ZSTD_CHAINLOG_MIN; /* fake value - temporary work around */
- if ((srcSize <= (1ULL << cParams.hashLog)) && ((U32)cParams.strategy < (U32)ZSTD_btlazy2)) cParams.hashLog = ZSTD_HASHLOG_MIN; /* fake value - temporary work around */
- return ZSTD_checkCParams(cParams);
-}
-
-
/** ZSTD_adjustCParams() :
- optimize cPar for a given input (`srcSize` and `dictSize`).
+ optimize `cPar` for a given input (`srcSize` and `dictSize`).
mostly downsizing to reduce memory consumption and initialization.
Both `srcSize` and `dictSize` are optional (use 0 if unknown),
but if both are 0, no optimization can be done.
@@ -187,16 +156,15 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u
{ U32 const minSrcSize = (srcSize==0) ? 500 : 0;
U64 const rSize = srcSize + dictSize + minSrcSize;
if (rSize < ((U64)1< srcLog) cPar.windowLog = srcLog;
} }
if (cPar.hashLog > cPar.windowLog) cPar.hashLog = cPar.windowLog;
- { U32 const btPlus = (cPar.strategy == ZSTD_btlazy2) || (cPar.strategy == ZSTD_btopt);
+ { U32 const btPlus = (cPar.strategy == ZSTD_btlazy2) | (cPar.strategy == ZSTD_btopt);
U32 const maxChainLog = cPar.windowLog+btPlus;
if (cPar.chainLog > maxChainLog) cPar.chainLog = maxChainLog; } /* <= ZSTD_CHAINLOG_MAX */
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
- if ((cPar.hashLog < ZSTD_HASHLOG_MIN) && ( (U32)cPar.strategy >= (U32)ZSTD_btlazy2)) cPar.hashLog = ZSTD_HASHLOG_MIN; /* required to ensure collision resistance in bt */
return cPar;
}
@@ -223,81 +191,116 @@ size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams)
return sizeof(ZSTD_CCtx) + neededSpace;
}
+
+static U32 ZSTD_equivalentParams(ZSTD_parameters param1, ZSTD_parameters param2)
+{
+ return (param1.cParams.hashLog == param2.cParams.hashLog)
+ & (param1.cParams.chainLog == param2.cParams.chainLog)
+ & (param1.cParams.strategy == param2.cParams.strategy)
+ & ((param1.cParams.searchLength==3) == (param2.cParams.searchLength==3));
+}
+
+/*! ZSTD_continueCCtx() :
+ reuse CCtx without reset (note : requires no dictionary) */
+static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 frameContentSize)
+{
+ U32 const end = (U32)(cctx->nextSrc - cctx->base);
+ cctx->params = params;
+ cctx->frameContentSize = frameContentSize;
+ cctx->lowLimit = end;
+ cctx->dictLimit = end;
+ cctx->nextToUpdate = end+1;
+ cctx->stage = ZSTDcs_init;
+ cctx->dictID = 0;
+ cctx->loadedDictEnd = 0;
+ { int i; for (i=0; irep[i] = repStartValue[i]; }
+ cctx->seqStore.litLengthSum = 0; /* force reset of btopt stats */
+ XXH64_reset(&cctx->xxhState, 0);
+ return 0;
+}
+
+typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset, ZSTDcrp_fullReset } ZSTD_compResetPolicy_e;
+
/*! ZSTD_resetCCtx_advanced() :
- note : 'params' is expected to be validated */
+ note : 'params' must be validated */
static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
ZSTD_parameters params, U64 frameContentSize,
- U32 reset)
-{ /* note : params considered validated here */
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog);
- U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
- size_t const maxNbSeq = blockSize / divider;
- size_t const tokenSpace = blockSize + 11*maxNbSeq;
- size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog);
- size_t const hSize = ((size_t)1) << params.cParams.hashLog;
- U32 const hashLog3 = (params.cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
- size_t const h3Size = ((size_t)1) << hashLog3;
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
- void* ptr;
+ ZSTD_compResetPolicy_e const crp)
+{
+ if (crp == ZSTDcrp_continue)
+ if (ZSTD_equivalentParams(params, zc->params))
+ return ZSTD_continueCCtx(zc, params, frameContentSize);
- /* Check if workSpace is large enough, alloc a new one if needed */
- { size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<workSpaceSize < neededSpace) {
- ZSTD_free(zc->workSpace, zc->customMem);
- zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
- if (zc->workSpace == NULL) return ERROR(memory_allocation);
- zc->workSpaceSize = neededSpace;
- } }
+ { size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog);
+ U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
+ size_t const maxNbSeq = blockSize / divider;
+ size_t const tokenSpace = blockSize + 11*maxNbSeq;
+ size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog);
+ size_t const hSize = ((size_t)1) << params.cParams.hashLog;
+ U32 const hashLog3 = (params.cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
+ size_t const h3Size = ((size_t)1) << hashLog3;
+ size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
+ void* ptr;
- if (reset) memset(zc->workSpace, 0, tableSpace ); /* reset only tables */
- XXH64_reset(&zc->xxhState, 0);
- zc->hashLog3 = hashLog3;
- zc->hashTable = (U32*)(zc->workSpace);
- zc->chainTable = zc->hashTable + hSize;
- zc->hashTable3 = zc->chainTable + chainSize;
- ptr = zc->hashTable3 + h3Size;
- zc->hufTable = (HUF_CElt*)ptr;
- zc->flagStaticTables = 0;
- ptr = ((U32*)ptr) + 256; /* note : HUF_CElt* is incomplete type, size is simulated using U32 */
+ /* Check if workSpace is large enough, alloc a new one if needed */
+ { size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<workSpaceSize < neededSpace) {
+ ZSTD_free(zc->workSpace, zc->customMem);
+ zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
+ if (zc->workSpace == NULL) return ERROR(memory_allocation);
+ zc->workSpaceSize = neededSpace;
+ } }
- zc->nextToUpdate = 1;
- zc->nextSrc = NULL;
- zc->base = NULL;
- zc->dictBase = NULL;
- zc->dictLimit = 0;
- zc->lowLimit = 0;
- zc->params = params;
- zc->blockSize = blockSize;
- zc->frameContentSize = frameContentSize;
- { int i; for (i=0; irep[i] = repStartValue[i]; }
+ if (crp!=ZSTDcrp_noMemset) memset(zc->workSpace, 0, tableSpace); /* reset tables only */
+ XXH64_reset(&zc->xxhState, 0);
+ zc->hashLog3 = hashLog3;
+ zc->hashTable = (U32*)(zc->workSpace);
+ zc->chainTable = zc->hashTable + hSize;
+ zc->hashTable3 = zc->chainTable + chainSize;
+ ptr = zc->hashTable3 + h3Size;
+ zc->hufTable = (HUF_CElt*)ptr;
+ zc->flagStaticTables = 0;
+ ptr = ((U32*)ptr) + 256; /* note : HUF_CElt* is incomplete type, size is simulated using U32 */
- if (params.cParams.strategy == ZSTD_btopt) {
- zc->seqStore.litFreq = (U32*)ptr;
- zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL+1);
- zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (MaxML+1);
- ptr = zc->seqStore.offCodeFreq + (MaxOff+1);
- zc->seqStore.matchTable = (ZSTD_match_t*)ptr;
- ptr = zc->seqStore.matchTable + ZSTD_OPT_NUM+1;
- zc->seqStore.priceTable = (ZSTD_optimal_t*)ptr;
- ptr = zc->seqStore.priceTable + ZSTD_OPT_NUM+1;
- zc->seqStore.litLengthSum = 0;
+ zc->nextToUpdate = 1;
+ zc->nextSrc = NULL;
+ zc->base = NULL;
+ zc->dictBase = NULL;
+ zc->dictLimit = 0;
+ zc->lowLimit = 0;
+ zc->params = params;
+ zc->blockSize = blockSize;
+ zc->frameContentSize = frameContentSize;
+ { int i; for (i=0; irep[i] = repStartValue[i]; }
+
+ if (params.cParams.strategy == ZSTD_btopt) {
+ zc->seqStore.litFreq = (U32*)ptr;
+ zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL+1);
+ zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (MaxML+1);
+ ptr = zc->seqStore.offCodeFreq + (MaxOff+1);
+ zc->seqStore.matchTable = (ZSTD_match_t*)ptr;
+ ptr = zc->seqStore.matchTable + ZSTD_OPT_NUM+1;
+ zc->seqStore.priceTable = (ZSTD_optimal_t*)ptr;
+ ptr = zc->seqStore.priceTable + ZSTD_OPT_NUM+1;
+ zc->seqStore.litLengthSum = 0;
+ }
+ zc->seqStore.sequencesStart = (seqDef*)ptr;
+ ptr = zc->seqStore.sequencesStart + maxNbSeq;
+ zc->seqStore.llCode = (BYTE*) ptr;
+ zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
+ zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
+ zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
+
+ zc->stage = ZSTDcs_init;
+ zc->dictID = 0;
+ zc->loadedDictEnd = 0;
+
+ return 0;
}
- zc->seqStore.sequencesStart = (seqDef*)ptr;
- ptr = zc->seqStore.sequencesStart + maxNbSeq;
- zc->seqStore.llCode = (BYTE*) ptr;
- zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
- zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
- zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
-
- zc->stage = ZSTDcs_init;
- zc->dictID = 0;
- zc->loadedDictEnd = 0;
-
- return 0;
}
@@ -305,13 +308,12 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
* Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
* Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
* @return : 0, or an error code */
-size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
+size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)
{
if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
- ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params, srcCCtx->frameContentSize, 0);
- dstCCtx->params.fParams.contentSizeFlag = 0; /* content size different from the one set during srcCCtx init */
+ ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params, pledgedSrcSize, ZSTDcrp_noMemset);
/* copy tables */
{ size_t const chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog);
@@ -665,8 +667,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
FSE_CState_t stateOffsetBits;
FSE_CState_t stateLitLength;
- { size_t const errorCode = BIT_initCStream(&blockStream, op, oend-op);
- if (ERR_isError(errorCode)) return ERROR(dstSize_tooSmall); } /* not enough space remaining */
+ CHECK_E(BIT_initCStream(&blockStream, op, oend-op), dstSize_tooSmall); /* not enough space remaining */
/* first symbols */
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
@@ -1080,7 +1081,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
if (ip <= ilimit) {
/* Fill Table */
- hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
+ hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
/* check immediate repcode */
while (ip <= ilimit) {
@@ -2473,8 +2474,7 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
unsigned offcodeMaxValue = MaxOff, offcodeLog = OffFSELog;
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
- { size_t const errorCode = FSE_buildCTable(cctx->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog);
- if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
+ CHECK_E (FSE_buildCTable(cctx->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted);
dictPtr += offcodeHeaderSize;
}
@@ -2482,8 +2482,7 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
- { size_t const errorCode = FSE_buildCTable(cctx->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
- if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
+ CHECK_E (FSE_buildCTable(cctx->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted);
dictPtr += matchlengthHeaderSize;
}
@@ -2491,8 +2490,7 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
- { size_t const errorCode = FSE_buildCTable(cctx->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog);
- if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
+ CHECK_E(FSE_buildCTable(cctx->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted);
dictPtr += litlengthHeaderSize;
}
@@ -2517,9 +2515,9 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, si
zc->dictID = zc->params.fParams.noDictIDFlag ? 0 : MEM_readLE32((const char*)dict+4);
/* known magic number : dict is parsed for entropy stats and content */
- { size_t const eSize_8 = ZSTD_loadDictEntropyStats(zc, (const char*)dict+8 /* skip dictHeader */, dictSize-8);
- size_t const eSize = eSize_8 + 8;
- if (ZSTD_isError(eSize_8)) return eSize_8;
+ { size_t const loadError = ZSTD_loadDictEntropyStats(zc, (const char*)dict+8 /* skip dictHeader */, dictSize-8);
+ size_t const eSize = loadError + 8;
+ if (ZSTD_isError(loadError)) return loadError;
return ZSTD_loadDictionaryContent(zc, (const char*)dict+eSize, dictSize-eSize);
}
}
@@ -2527,14 +2525,13 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, si
/*! ZSTD_compressBegin_internal() :
* @return : 0, or an error code */
-static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* zc,
+static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
ZSTD_parameters params, U64 pledgedSrcSize)
{
- size_t const resetError = ZSTD_resetCCtx_advanced(zc, params, pledgedSrcSize, 1);
- if (ZSTD_isError(resetError)) return resetError;
-
- return ZSTD_compress_insertDictionary(zc, dict, dictSize);
+ ZSTD_compResetPolicy_e const crp = dictSize ? ZSTDcrp_fullReset : ZSTDcrp_continue;
+ CHECK_F(ZSTD_resetCCtx_advanced(cctx, params, pledgedSrcSize, crp));
+ return ZSTD_compress_insertDictionary(cctx, dict, dictSize);
}
@@ -2545,9 +2542,7 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
ZSTD_parameters params, unsigned long long pledgedSrcSize)
{
/* compression parameters verification and optimization */
- { size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, pledgedSrcSize);
- if (ZSTD_isError(errorCode)) return errorCode; }
-
+ CHECK_F(ZSTD_checkCParams(params.cParams));
return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, pledgedSrcSize);
}
@@ -2625,9 +2620,7 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
const void* dict,size_t dictSize,
ZSTD_parameters params)
{
- size_t const errorCode = ZSTD_compressBegin_internal(cctx, dict, dictSize, params, srcSize);
- if(ZSTD_isError(errorCode)) return errorCode;
-
+ CHECK_F(ZSTD_compressBegin_internal(cctx, dict, dictSize, params, srcSize));
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
}
@@ -2637,8 +2630,7 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
const void* dict,size_t dictSize,
ZSTD_parameters params)
{
- size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, srcSize);
- if (ZSTD_isError(errorCode)) return errorCode;
+ CHECK_F(ZSTD_checkCParams(params.cParams));
return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
}
@@ -2674,6 +2666,12 @@ struct ZSTD_CDict_s {
ZSTD_CCtx* refContext;
}; /* typedef'd tp ZSTD_CDict within "zstd.h" */
+size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
+{
+ if (cdict==NULL) return 0; /* support sizeof on NULL */
+ return ZSTD_sizeof_CCtx(cdict->refContext) + cdict->dictContentSize;
+}
+
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, ZSTD_parameters params, ZSTD_customMem customMem)
{
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
@@ -2717,7 +2715,7 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL
size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
{
if (cdict==NULL) return 0; /* support free on NULL */
- { ZSTD_customMem cMem = cdict->refContext->customMem;
+ { ZSTD_customMem const cMem = cdict->refContext->customMem;
ZSTD_freeCCtx(cdict->refContext);
ZSTD_free(cdict->dictContent, cMem);
ZSTD_free(cdict, cMem);
@@ -2725,17 +2723,23 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
}
}
+size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, U64 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));
+ return 0;
+}
+
/*! ZSTD_compress_usingCDict() :
* Compression using a digested Dictionary.
* Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times.
* Note that compression level is decided during dictionary creation */
-ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_CDict* cdict)
+size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict)
{
- size_t const errorCode = ZSTD_copyCCtx(cctx, cdict->refContext);
- if (ZSTD_isError(errorCode)) return errorCode;
+ CHECK_F(ZSTD_compressBegin_usingCDict(cctx, cdict, srcSize));
if (cdict->refContext->params.fParams.contentSizeFlag==1) {
cctx->params.fParams.contentSizeFlag = 1;
@@ -2754,7 +2758,8 @@ ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
typedef enum { zcss_init, zcss_load, zcss_flush, zcss_final } ZSTD_cStreamStage;
struct ZSTD_CStream_s {
- ZSTD_CCtx* zc;
+ ZSTD_CCtx* cctx;
+ ZSTD_CDict* cdict;
char* inBuff;
size_t inBuffSize;
size_t inToCompress;
@@ -2787,8 +2792,8 @@ ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)
if (zcs==NULL) return NULL;
memset(zcs, 0, sizeof(ZSTD_CStream));
memcpy(&zcs->customMem, &customMem, sizeof(ZSTD_customMem));
- zcs->zc = ZSTD_createCCtx_advanced(customMem);
- if (zcs->zc == NULL) { ZSTD_freeCStream(zcs); return NULL; }
+ zcs->cctx = ZSTD_createCCtx_advanced(customMem);
+ if (zcs->cctx == NULL) { ZSTD_freeCStream(zcs); return NULL; }
return zcs;
}
@@ -2796,7 +2801,8 @@ size_t ZSTD_freeCStream(ZSTD_CStream* zcs)
{
if (zcs==NULL) return 0; /* support free on NULL */
{ ZSTD_customMem const cMem = zcs->customMem;
- ZSTD_freeCCtx(zcs->zc);
+ ZSTD_freeCCtx(zcs->cctx);
+ ZSTD_freeCDict(zcs->cdict);
ZSTD_free(zcs->inBuff, cMem);
ZSTD_free(zcs->outBuff, cMem);
ZSTD_free(zcs, cMem);
@@ -2810,6 +2816,19 @@ size_t ZSTD_freeCStream(ZSTD_CStream* zcs)
size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
size_t ZSTD_CStreamOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ; }
+size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
+{
+ CHECK_F(ZSTD_compressBegin_usingCDict(zcs->cctx, zcs->cdict, pledgedSrcSize));
+
+ zcs->inToCompress = 0;
+ zcs->inBuffPos = 0;
+ zcs->inBuffTarget = zcs->blockSize;
+ zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
+ zcs->stage = zcss_load;
+ zcs->frameEnded = 0;
+ return 0; /* ready to go */
+}
+
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
const void* dict, size_t dictSize,
ZSTD_parameters params, unsigned long long pledgedSrcSize)
@@ -2818,7 +2837,7 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
{ size_t const neededInBuffSize = (size_t)1 << params.cParams.windowLog;
if (zcs->inBuffSize < neededInBuffSize) {
zcs->inBuffSize = neededInBuffSize;
- ZSTD_free(zcs->inBuff, zcs->customMem); /* should not be necessary */
+ ZSTD_free(zcs->inBuff, zcs->customMem);
zcs->inBuff = (char*) ZSTD_malloc(neededInBuffSize, zcs->customMem);
if (zcs->inBuff == NULL) return ERROR(memory_allocation);
}
@@ -2826,22 +2845,18 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
}
if (zcs->outBuffSize < ZSTD_compressBound(zcs->blockSize)+1) {
zcs->outBuffSize = ZSTD_compressBound(zcs->blockSize)+1;
- ZSTD_free(zcs->outBuff, zcs->customMem); /* should not be necessary */
+ ZSTD_free(zcs->outBuff, zcs->customMem);
zcs->outBuff = (char*) ZSTD_malloc(zcs->outBuffSize, zcs->customMem);
if (zcs->outBuff == NULL) return ERROR(memory_allocation);
}
- { size_t const errorCode = ZSTD_compressBegin_advanced(zcs->zc, dict, dictSize, params, pledgedSrcSize);
- if (ZSTD_isError(errorCode)) return errorCode; }
+ ZSTD_freeCDict(zcs->cdict);
+ zcs->cdict = ZSTD_createCDict_advanced(dict, dictSize, params, zcs->customMem);
+ if (zcs->cdict == NULL) return ERROR(memory_allocation);
- zcs->inToCompress = 0;
- zcs->inBuffPos = 0;
- zcs->inBuffTarget = zcs->blockSize;
- zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
- zcs->stage = zcss_load;
zcs->checksum = params.fParams.checksumFlag > 0;
- zcs->frameEnded = 0;
- return 0; /* ready to go */
+
+ return ZSTD_resetCStream(zcs, pledgedSrcSize);
}
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
@@ -2857,7 +2872,8 @@ size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
{
- return sizeof(zcs) + ZSTD_sizeof_CCtx(zcs->zc) + zcs->outBuffSize + zcs->inBuffSize;
+ if (zcs==NULL) return 0; /* support sizeof on NULL */
+ return sizeof(zcs) + ZSTD_sizeof_CCtx(zcs->cctx) + ZSTD_sizeof_CDict(zcs->cdict) + zcs->outBuffSize + zcs->inBuffSize;
}
/*====== Compression ======*/
@@ -2908,8 +2924,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
else
cDst = zcs->outBuff, oSize = zcs->outBuffSize;
cSize = (flush == zsf_end) ?
- ZSTD_compressEnd(zcs->zc, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize) :
- ZSTD_compressContinue(zcs->zc, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize);
+ ZSTD_compressEnd(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize) :
+ ZSTD_compressContinue(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize);
if (ZSTD_isError(cSize)) return cSize;
if (flush == zsf_end) zcs->frameEnded = 1;
/* prepare next block */
@@ -2974,8 +2990,8 @@ size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
size_t srcSize = 0;
size_t sizeWritten = output->size - output->pos;
size_t const result = ZSTD_compressStream_generic(zcs,
- (char*)(output->dst) + output->pos, &sizeWritten,
- &srcSize, &srcSize, /* use a valid src address instead of NULL */
+ (char*)(output->dst) + output->pos, &sizeWritten,
+ &srcSize, &srcSize, /* use a valid src address instead of NULL */
zsf_flush);
output->pos += sizeWritten;
if (ZSTD_isError(result)) return result;
@@ -3003,7 +3019,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
/* create epilogue */
zcs->stage = zcss_final;
zcs->outBuffContentSize = !notEnded ? 0 :
- ZSTD_compressEnd(zcs->zc, zcs->outBuff, zcs->outBuffSize, NULL, 0); /* write epilogue, including final empty block, into outBuff */
+ ZSTD_compressEnd(zcs->cctx, zcs->outBuff, zcs->outBuffSize, NULL, 0); /* write epilogue, including final empty block, into outBuff */
}
/* flush epilogue */
diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c
index a5521bd36..e94fa83cc 100644
--- a/lib/decompress/huf_decompress.c
+++ b/lib/decompress/huf_decompress.c
@@ -43,16 +43,8 @@
# define inline /* disable inline */
#endif
-
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#else
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c
index fb1ee35a0..47b5f42c7 100644
--- a/lib/decompress/zstd_decompress.c
+++ b/lib/decompress/zstd_decompress.c
@@ -28,7 +28,6 @@
# define ZSTD_LEGACY_SUPPORT 0
#endif
-
/*!
* MAXWINDOWSIZE_DEFAULT :
* maximum window size accepted by DStream, by default.
@@ -57,24 +56,6 @@
#endif
-/*-*******************************************************
-* Compiler specifics
-*********************************************************/
-#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
-# include /* For Visual 2005 */
-# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-# pragma warning(disable : 4324) /* disable: C4324: padded structure */
-# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
-#else
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
-#endif
-
-
/*-*************************************
* Macros
***************************************/
@@ -99,8 +80,12 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
struct ZSTD_DCtx_s
{
+ const FSE_DTable* LLTptr;
+ const FSE_DTable* MLTptr;
+ const FSE_DTable* OFTptr;
+ const HUF_DTable* HUFptr;
FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
- FSE_DTable OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
+ FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
const void* previousDstEnd;
@@ -126,23 +111,27 @@ struct ZSTD_DCtx_s
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
-size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx) { return sizeof(*dctx); }
+size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx) { if (dctx==NULL) return 0; return sizeof(ZSTD_DCtx); } /* support sizeof on NULL */
size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
{
- dctx->expected = ZSTD_frameHeaderSize_min;
+ dctx->expected = ZSTD_frameHeaderSize_prefix;
dctx->stage = ZSTDds_getFrameHeaderSize;
dctx->previousDstEnd = NULL;
dctx->base = NULL;
dctx->vBase = NULL;
dctx->dictEnd = NULL;
- dctx->hufTable[0] = (HUF_DTable)((HufLog)*0x1000001);
+ dctx->hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
dctx->litEntropy = dctx->fseEntropy = 0;
dctx->dictID = 0;
- MEM_STATIC_ASSERT(sizeof(dctx->rep)==sizeof(repStartValue));
- memcpy(dctx->rep, repStartValue, sizeof(repStartValue));
+ MEM_STATIC_ASSERT(sizeof(dctx->rep) == sizeof(repStartValue));
+ memcpy(dctx->rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
+ dctx->LLTptr = dctx->LLTable;
+ dctx->MLTptr = dctx->MLTable;
+ dctx->OFTptr = dctx->OFTable;
+ dctx->HUFptr = dctx->hufTable;
return 0;
}
@@ -153,7 +142,7 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
if (!customMem.customAlloc || !customMem.customFree) return NULL;
- dctx = (ZSTD_DCtx*) ZSTD_malloc(sizeof(ZSTD_DCtx), customMem);
+ dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(ZSTD_DCtx), customMem);
if (!dctx) return NULL;
memcpy(&dctx->customMem, &customMem, sizeof(customMem));
ZSTD_decompressBegin(dctx);
@@ -178,6 +167,25 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */
}
+static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
+{
+ ZSTD_decompressBegin(dstDCtx); /* init */
+ dstDCtx->dictEnd = srcDCtx->dictEnd;
+ dstDCtx->vBase = srcDCtx->vBase;
+ dstDCtx->base = srcDCtx->base;
+ dstDCtx->previousDstEnd = srcDCtx->previousDstEnd;
+ dstDCtx->dictID = srcDCtx->dictID;
+ dstDCtx->litEntropy = srcDCtx->litEntropy;
+ dstDCtx->fseEntropy = srcDCtx->fseEntropy;
+ dstDCtx->LLTptr = srcDCtx->LLTable;
+ dstDCtx->MLTptr = srcDCtx->MLTable;
+ dstDCtx->OFTptr = srcDCtx->OFTable;
+ dstDCtx->HUFptr = srcDCtx->hufTable;
+ dstDCtx->rep[0] = srcDCtx->rep[0];
+ dstDCtx->rep[1] = srcDCtx->rep[1];
+ dstDCtx->rep[2] = srcDCtx->rep[2];
+}
+
/*-*************************************************************
* Decompression section
@@ -186,16 +194,16 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
/* See compression format details in : zstd_compression_format.md */
/** ZSTD_frameHeaderSize() :
-* srcSize must be >= ZSTD_frameHeaderSize_min.
+* srcSize must be >= ZSTD_frameHeaderSize_prefix.
* @return : size of the Frame Header */
static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
{
- if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);
+ if (srcSize < ZSTD_frameHeaderSize_prefix) return ERROR(srcSize_wrong);
{ BYTE const fhd = ((const BYTE*)src)[4];
U32 const dictID= fhd & 3;
U32 const singleSegment = (fhd >> 5) & 1;
U32 const fcsId = fhd >> 6;
- return ZSTD_frameHeaderSize_min + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
+ return ZSTD_frameHeaderSize_prefix + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
+ (singleSegment && !fcsId);
}
}
@@ -210,7 +218,7 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
{
const BYTE* ip = (const BYTE*)src;
- if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_min;
+ if (srcSize < ZSTD_frameHeaderSize_prefix) return ZSTD_frameHeaderSize_prefix;
if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) {
if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
if (srcSize < ZSTD_skippableHeaderSize) return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */
@@ -369,34 +377,31 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
{
case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */
/* 2 - 2 - 10 - 10 */
- { singleStream = !lhlCode;
- lhSize = 3;
- litSize = (lhc >> 4) & 0x3FF;
- litCSize = (lhc >> 14) & 0x3FF;
- break;
- }
+ singleStream = !lhlCode;
+ lhSize = 3;
+ litSize = (lhc >> 4) & 0x3FF;
+ litCSize = (lhc >> 14) & 0x3FF;
+ break;
case 2:
/* 2 - 2 - 14 - 14 */
- { lhSize = 4;
- litSize = (lhc >> 4) & 0x3FFF;
- litCSize = lhc >> 18;
- break;
- }
+ lhSize = 4;
+ litSize = (lhc >> 4) & 0x3FFF;
+ litCSize = lhc >> 18;
+ break;
case 3:
/* 2 - 2 - 18 - 18 */
- { lhSize = 5;
- litSize = (lhc >> 4) & 0x3FFFF;
- litCSize = (lhc >> 22) + (istart[4] << 10);
- break;
- }
+ lhSize = 5;
+ litSize = (lhc >> 4) & 0x3FFFF;
+ litCSize = (lhc >> 22) + (istart[4] << 10);
+ break;
}
if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
if (HUF_isError((litEncType==set_repeat) ?
( singleStream ?
- HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable) :
- HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable) ) :
+ HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) :
+ HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) ) :
( singleStream ?
HUF_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :
HUF_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize)) ))
@@ -406,6 +411,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
dctx->litBufSize = ZSTD_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH;
dctx->litSize = litSize;
dctx->litEntropy = 1;
+ if (litEncType==set_compressed) dctx->HUFptr = dctx->hufTable;
return litCSize + lhSize;
}
@@ -472,28 +478,207 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
default:
return ERROR(corruption_detected); /* impossible */
}
-
}
}
+typedef union {
+ FSE_decode_t realData;
+ U32 alignedBy4;
+} FSE_decode_t4;
+
+static const FSE_decode_t4 LL_defaultDTable[(1< max) return ERROR(corruption_detected);
- FSE_buildDTable_rle(DTable, *(const BYTE*)src); /* if *src > max, data is corrupted */
+ FSE_buildDTable_rle(DTableSpace, *(const BYTE*)src);
+ *DTablePtr = DTableSpace;
return 1;
case set_basic :
- FSE_buildDTable(DTable, defaultNorm, max, defaultLog);
+ *DTablePtr = (const FSE_DTable*)tmpPtr;
return 0;
case set_repeat:
if (!flagRepeatTable) return ERROR(corruption_detected);
@@ -505,14 +690,13 @@ FORCE_INLINE size_t ZSTD_buildSeqTable(FSE_DTable* DTable, symbolEncodingType_e
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
if (FSE_isError(headerSize)) return ERROR(corruption_detected);
if (tableLog > maxLog) return ERROR(corruption_detected);
- FSE_buildDTable(DTable, norm, max, tableLog);
+ FSE_buildDTable(DTableSpace, norm, max, tableLog);
+ *DTablePtr = DTableSpace;
return headerSize;
} }
}
-
-size_t ZSTD_decodeSeqHeaders(int* nbSeqPtr,
- FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb, U32 flagRepeatTable,
+size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
const void* src, size_t srcSize)
{
const BYTE* const istart = (const BYTE* const)src;
@@ -542,18 +726,25 @@ size_t ZSTD_decodeSeqHeaders(int* nbSeqPtr,
ip++;
/* Build DTables */
- { size_t const llhSize = ZSTD_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);
+ { size_t const llhSize = ZSTD_buildSeqTable(dctx->LLTable, &dctx->LLTptr,
+ LLtype, MaxLL, LLFSELog,
+ ip, iend-ip, LL_defaultDTable, dctx->fseEntropy);
if (ZSTD_isError(llhSize)) return ERROR(corruption_detected);
ip += llhSize;
}
- { size_t const ofhSize = ZSTD_buildSeqTable(DTableOffb, OFtype, MaxOff, OffFSELog, ip, iend-ip, OF_defaultNorm, OF_defaultNormLog, flagRepeatTable);
+ { size_t const ofhSize = ZSTD_buildSeqTable(dctx->OFTable, &dctx->OFTptr,
+ OFtype, MaxOff, OffFSELog,
+ ip, iend-ip, OF_defaultDTable, dctx->fseEntropy);
if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected);
ip += ofhSize;
}
- { size_t const mlhSize = ZSTD_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog, flagRepeatTable);
+ { size_t const mlhSize = ZSTD_buildSeqTable(dctx->MLTable, &dctx->MLTptr,
+ MLtype, MaxML, MLFSELog,
+ ip, iend-ip, ML_defaultDTable, dctx->fseEntropy);
if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected);
ip += mlhSize;
- } }
+ }
+ }
return ip-istart;
}
@@ -734,16 +925,13 @@ static size_t ZSTD_decompressSequences(
const BYTE* litPtr = dctx->litPtr;
const BYTE* const litLimit_w = litPtr + dctx->litBufSize - WILDCOPY_OVERLENGTH;
const BYTE* const litEnd = litPtr + dctx->litSize;
- FSE_DTable* DTableLL = dctx->LLTable;
- FSE_DTable* DTableML = dctx->MLTable;
- FSE_DTable* DTableOffb = dctx->OffTable;
const BYTE* const base = (const BYTE*) (dctx->base);
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
int nbSeq;
/* Build Decoding Tables */
- { size_t const seqHSize = ZSTD_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, dctx->fseEntropy, ip, seqSize);
+ { size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
if (ZSTD_isError(seqHSize)) return seqHSize;
ip += seqHSize;
}
@@ -753,11 +941,10 @@ static size_t ZSTD_decompressSequences(
seqState_t seqState;
dctx->fseEntropy = 1;
{ U32 i; for (i=0; irep[i]; }
- { size_t const errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);
- if (ERR_isError(errorCode)) return ERROR(corruption_detected); }
- FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
- FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
- FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
+ CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
+ FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
nbSeq--;
@@ -859,12 +1046,10 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
/* Frame Header */
- { size_t const frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
- size_t result;
+ { size_t const frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix);
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
- result = ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize);
- if (ZSTD_isError(result)) return result;
+ CHECK_F(ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize));
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
}
@@ -917,25 +1102,10 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
}
-/*! ZSTD_decompress_usingPreparedDCtx() :
-* Same as ZSTD_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.
-* It avoids reloading the dictionary each time.
-* `preparedDCtx` must have been properly initialized using ZSTD_decompressBegin_usingDict().
-* Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */
-size_t ZSTD_decompress_usingPreparedDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* refDCtx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize)
-{
- ZSTD_copyDCtx(dctx, refDCtx);
- ZSTD_checkContinuity(dctx, dst);
- return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
-}
-
-
size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const void* dict, size_t dictSize)
+ const void* src, size_t srcSize,
+ const void* dict, size_t dictSize)
{
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, dict, dictSize);
@@ -1009,32 +1179,30 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
switch (dctx->stage)
{
case ZSTDds_getFrameHeaderSize :
- if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
- if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
- memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min);
- dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_min; /* magic number + skippable frame length */
+ if (srcSize != ZSTD_frameHeaderSize_prefix) return ERROR(srcSize_wrong); /* impossible */
+ if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
+ memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
+ dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix; /* magic number + skippable frame length */
dctx->stage = ZSTDds_decodeSkippableHeader;
return 0;
}
- dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
+ dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix);
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
- memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min);
- if (dctx->headerSize > ZSTD_frameHeaderSize_min) {
- dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_min;
+ memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
+ if (dctx->headerSize > ZSTD_frameHeaderSize_prefix) {
+ dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_prefix;
dctx->stage = ZSTDds_decodeFrameHeader;
return 0;
}
dctx->expected = 0; /* not necessary to copy more */
case ZSTDds_decodeFrameHeader:
- { size_t result;
- memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected);
- result = ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);
- if (ZSTD_isError(result)) return result;
- dctx->expected = ZSTD_blockHeaderSize;
- dctx->stage = ZSTDds_decodeBlockHeader;
- return 0;
- }
+ memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
+ CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
+ dctx->expected = ZSTD_blockHeaderSize;
+ dctx->stage = ZSTDds_decodeBlockHeader;
+ return 0;
+
case ZSTDds_decodeBlockHeader:
{ blockProperties_t bp;
size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
@@ -1106,7 +1274,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
return 0;
}
case ZSTDds_decodeSkippableHeader:
- { memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected);
+ { memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
dctx->expected = MEM_readLE32(dctx->headerBuffer + 4);
dctx->stage = ZSTDds_skipFrame;
return 0;
@@ -1145,8 +1313,7 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
U32 offcodeMaxValue=MaxOff, offcodeLog=OffFSELog;
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
- { size_t const errorCode = FSE_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
- if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
+ CHECK_E(FSE_buildDTable(dctx->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted);
dictPtr += offcodeHeaderSize;
}
@@ -1154,8 +1321,7 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
- { size_t const errorCode = FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
- if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
+ CHECK_E(FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted);
dictPtr += matchlengthHeaderSize;
}
@@ -1163,8 +1329,7 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
- { size_t const errorCode = FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
- if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
+ CHECK_E(FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted);
dictPtr += litlengthHeaderSize;
}
@@ -1200,21 +1365,16 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
return ZSTD_refDictContent(dctx, dict, dictSize);
}
-
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
{
- { size_t const errorCode = ZSTD_decompressBegin(dctx);
- if (ZSTD_isError(errorCode)) return errorCode; }
-
- if (dict && dictSize) {
- size_t const errorCode = ZSTD_decompress_insertDictionary(dctx, dict, dictSize);
- if (ZSTD_isError(errorCode)) return ERROR(dictionary_corrupted);
- }
-
+ CHECK_F(ZSTD_decompressBegin(dctx));
+ if (dict && dictSize) CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
return 0;
}
+/* ====== ZSTD_DDict ====== */
+
struct ZSTD_DDict_s {
void* dict;
size_t dictSize;
@@ -1273,20 +1433,27 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
}
}
+size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
+{
+ if (ddict==NULL) return 0; /* support sizeof on NULL */
+ return sizeof(*ddict) + sizeof(ddict->refContext) + ddict->dictSize;
+}
+
+
/*! ZSTD_decompress_usingDDict() :
* Decompression using a pre-digested Dictionary
* Use dictionary without significant overhead. */
-ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_DDict* ddict)
+size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_DDict* ddict)
{
#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);
#endif
- return ZSTD_decompress_usingPreparedDCtx(dctx, ddict->refContext,
- dst, dstCapacity,
- src, srcSize);
+ ZSTD_refDCtx(dctx, ddict->refContext);
+ ZSTD_checkContinuity(dctx, dst);
+ return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
}
@@ -1299,7 +1466,8 @@ typedef enum { zdss_init, zdss_loadHeader,
/* *** Resource management *** */
struct ZSTD_DStream_s {
- ZSTD_DCtx* zd;
+ ZSTD_DCtx* dctx;
+ ZSTD_DDict* ddict;
ZSTD_frameParams fParams;
ZSTD_dStreamStage stage;
char* inBuff;
@@ -1311,15 +1479,13 @@ struct ZSTD_DStream_s {
size_t outStart;
size_t outEnd;
size_t blockSize;
- BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
+ BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */
size_t lhSize;
ZSTD_customMem customMem;
- void* dictContent;
- size_t dictSize;
- const void* dictSource;
void* legacyContext;
U32 previousLegacyVersion;
U32 legacyVersion;
+ U32 hostageByte;
}; /* typedef'd to ZSTD_DStream within "zstd.h" */
@@ -1339,8 +1505,8 @@ ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
if (zds==NULL) return NULL;
memset(zds, 0, sizeof(ZSTD_DStream));
memcpy(&zds->customMem, &customMem, sizeof(ZSTD_customMem));
- zds->zd = ZSTD_createDCtx_advanced(customMem);
- if (zds->zd == NULL) { ZSTD_freeDStream(zds); return NULL; }
+ zds->dctx = ZSTD_createDCtx_advanced(customMem);
+ if (zds->dctx == NULL) { ZSTD_freeDStream(zds); return NULL; }
zds->stage = zdss_init;
zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
return zds;
@@ -1350,10 +1516,10 @@ size_t ZSTD_freeDStream(ZSTD_DStream* zds)
{
if (zds==NULL) return 0; /* support free on null */
{ ZSTD_customMem const cMem = zds->customMem;
- ZSTD_freeDCtx(zds->zd);
+ ZSTD_freeDCtx(zds->dctx);
+ ZSTD_freeDDict(zds->ddict);
ZSTD_free(zds->inBuff, cMem);
ZSTD_free(zds->outBuff, cMem);
- ZSTD_free(zds->dictContent, cMem);
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
if (zds->legacyContext)
ZSTD_freeLegacyStreamContext(zds->legacyContext, zds->previousLegacyVersion);
@@ -1373,17 +1539,12 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
{
zds->stage = zdss_loadHeader;
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
- if ((dict != zds->dictSource) | (dictSize != zds->dictSize)) { /* new dictionary */
- if (dictSize > zds->dictSize) {
- ZSTD_free(zds->dictContent, zds->customMem);
- zds->dictContent = ZSTD_malloc(dictSize, zds->customMem);
- if (zds->dictContent == NULL) return ERROR(memory_allocation);
- }
- memcpy(zds->dictContent, dict, dictSize);
- zds->dictSize = dictSize;
- }
+ ZSTD_freeDDict(zds->ddict);
+ zds->ddict = ZSTD_createDDict(dict, dictSize);
+ if (zds->ddict == NULL) return ERROR(memory_allocation);
zds->legacyVersion = 0;
- return 0;
+ zds->hostageByte = 0;
+ return ZSTD_frameHeaderSize_prefix;
}
size_t ZSTD_initDStream(ZSTD_DStream* zds)
@@ -1391,6 +1552,16 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
return ZSTD_initDStream_usingDict(zds, NULL, 0);
}
+size_t ZSTD_resetDStream(ZSTD_DStream* zds)
+{
+ if (zds->ddict == NULL) return ERROR(stage_wrong); /* must be init at least once */
+ zds->stage = zdss_loadHeader;
+ zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
+ zds->legacyVersion = 0;
+ zds->hostageByte = 0;
+ return ZSTD_frameHeaderSize_prefix;
+}
+
size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
ZSTD_DStreamParameter_e paramType, unsigned paramValue)
{
@@ -1405,11 +1576,12 @@ size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds)
{
- return sizeof(*zds) + ZSTD_sizeof_DCtx(zds->zd) + zds->inBuffSize + zds->outBuffSize;
+ if (zds==NULL) return 0; /* support sizeof on NULL */
+ return sizeof(*zds) + ZSTD_sizeof_DCtx(zds->dctx) + ZSTD_sizeof_DDict(zds->ddict) + zds->inBuffSize + zds->outBuffSize;
}
-/* *** Decompression *** */
+/* ***** Decompression ***** */
MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{
@@ -1446,10 +1618,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
{ U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
if (legacyVersion) {
- size_t initResult;
- initResult = ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion,
- zds->dictContent, zds->dictSize);
- if (ZSTD_isError(initResult)) return initResult;
+ CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion,
+ zds->ddict->dict, zds->ddict->dictSize));
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
} else {
@@ -1464,27 +1634,24 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
memcpy(zds->headerBuffer + zds->lhSize, ip, iend-ip);
zds->lhSize += iend-ip;
input->pos = input->size;
- return (hSize - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
+ return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
}
memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
break;
} }
/* Consume header */
- ZSTD_decompressBegin_usingDict(zds->zd, zds->dictContent, zds->dictSize);
- { size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->zd); /* == ZSTD_frameHeaderSize_min */
- size_t const h1Result = ZSTD_decompressContinue(zds->zd, NULL, 0, zds->headerBuffer, h1Size);
- if (ZSTD_isError(h1Result)) return h1Result; /* should not happen : already checked */
- if (h1Size < zds->lhSize) { /* long header */
- size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->zd);
- size_t const h2Result = ZSTD_decompressContinue(zds->zd, NULL, 0, zds->headerBuffer+h1Size, h2Size);
- if (ZSTD_isError(h2Result)) return h2Result;
+ ZSTD_refDCtx(zds->dctx, zds->ddict->refContext);
+ { size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
+ CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
+ { size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+ CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer+h1Size, h2Size));
} }
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_unsupported);
- /* Frame header instruct buffer sizes */
+ /* Adapt buffer sizes to frame header instructions */
{ size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
size_t const neededOutSize = zds->fParams.windowSize + blockSize;
zds->blockSize = blockSize;
@@ -1504,21 +1671,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
/* pass-through */
case zdss_read:
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->zd);
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
if (neededInSize==0) { /* end of frame */
zds->stage = zdss_init;
someMoreWork = 0;
break;
}
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
- const int isSkipFrame = ZSTD_isSkipFrame(zds->zd);
- size_t const decodedSize = ZSTD_decompressContinue(zds->zd,
+ const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
+ size_t const decodedSize = ZSTD_decompressContinue(zds->dctx,
zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
ip, neededInSize);
if (ZSTD_isError(decodedSize)) return decodedSize;
ip += neededInSize;
if (!decodedSize && !isSkipFrame) break; /* this was just a header */
- zds->outEnd = zds->outStart + decodedSize;
+ zds->outEnd = zds->outStart + decodedSize;
zds->stage = zdss_flush;
break;
}
@@ -1528,7 +1695,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
}
case zdss_load:
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->zd);
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
size_t const toLoad = neededInSize - zds->inPos; /* should always be <= remaining space within inBuff */
size_t loadedSize;
if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */
@@ -1538,8 +1705,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
/* decode loaded input */
- { const int isSkipFrame = ZSTD_isSkipFrame(zds->zd);
- size_t const decodedSize = ZSTD_decompressContinue(zds->zd,
+ { const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
+ size_t const decodedSize = ZSTD_decompressContinue(zds->dctx,
zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
zds->inBuff, neededInSize);
if (ZSTD_isError(decodedSize)) return decodedSize;
@@ -1561,7 +1728,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
zds->outStart = zds->outEnd = 0;
break;
}
- /* cannot flush everything */
+ /* cannot complete flush */
someMoreWork = 0;
break;
}
@@ -1571,9 +1738,22 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
/* result */
input->pos += (size_t)(ip-istart);
output->pos += (size_t)(op-ostart);
- { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->zd);
- if (!nextSrcSizeHint) return (zds->outEnd != zds->outStart); /* return 0 only if fully flushed too */
- nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->zd) == ZSTDnit_block);
+ { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+ if (!nextSrcSizeHint) { /* frame fully decoded */
+ if (zds->outEnd == zds->outStart) { /* output fully flushed */
+ if (zds->hostageByte) {
+ if (input->pos >= input->size) { zds->stage = zdss_read; return 1; } /* can't release hostage (not present) */
+ input->pos++; /* release hostage */
+ }
+ return 0;
+ }
+ if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
+ input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
+ zds->hostageByte=1;
+ }
+ return 1;
+ }
+ nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->dctx) == ZSTDnit_block); /* preload header of next block */
if (zds->inPos > nextSrcSizeHint) return ERROR(GENERIC); /* should never happen */
nextSrcSizeHint -= zds->inPos; /* already loaded*/
return nextSrcSizeHint;
diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c
index adfe55cf7..47a82af14 100644
--- a/lib/dictBuilder/zdict.c
+++ b/lib/dictBuilder/zdict.c
@@ -71,26 +71,18 @@ static const size_t g_min_fast_dictContent = 192;
* Console display
***************************************/
#define DISPLAY(...) { fprintf(stderr, __VA_ARGS__); fflush( stderr ); }
-#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
-static unsigned g_displayLevel = 0; /* 0 : no display; 1: errors; 2: default; 4: full information */
-
-#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
- if (ZDICT_clockSpan(g_time) > refreshRate) \
- { g_time = clock(); DISPLAY(__VA_ARGS__); \
- if (g_displayLevel>=4) fflush(stdout); } }
-static const clock_t refreshRate = CLOCKS_PER_SEC * 3 / 10;
-static clock_t g_time = 0;
+#define DISPLAYLEVEL(l, ...) if (notificationLevel>=l) { DISPLAY(__VA_ARGS__); } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */
static clock_t ZDICT_clockSpan(clock_t nPrevious) { return clock() - nPrevious; }
-static void ZDICT_printHex(U32 dlevel, const void* ptr, size_t length)
+static void ZDICT_printHex(const void* ptr, size_t length)
{
const BYTE* const b = (const BYTE*)ptr;
size_t u;
for (u=0; u126) c = '.'; /* non-printable char */
- DISPLAYLEVEL(dlevel, "%c", c);
+ DISPLAY("%c", c);
}
}
@@ -211,7 +203,7 @@ static void ZDICT_initDictItem(dictItem* d)
static dictItem ZDICT_analyzePos(
BYTE* doneMarks,
const int* suffix, U32 start,
- const void* buffer, U32 minRatio)
+ const void* buffer, U32 minRatio, U32 notificationLevel)
{
U32 lengthList[LLIMIT] = {0};
U32 cumulLength[LLIMIT] = {0};
@@ -473,7 +465,7 @@ static U32 ZDICT_dictSize(const dictItem* dictList)
static size_t ZDICT_trainBuffer(dictItem* dictList, U32 dictListSize,
const void* const buffer, size_t bufferSize, /* buffer must end with noisy guard band */
const size_t* fileSizes, unsigned nbFiles,
- U32 minRatio)
+ U32 minRatio, U32 notificationLevel)
{
int* const suffix0 = (int*)malloc((bufferSize+2)*sizeof(*suffix0));
int* const suffix = suffix0+1;
@@ -481,6 +473,13 @@ static size_t ZDICT_trainBuffer(dictItem* dictList, U32 dictListSize,
BYTE* doneMarks = (BYTE*)malloc((bufferSize+16)*sizeof(*doneMarks)); /* +16 for overflow security */
U32* filePos = (U32*)malloc(nbFiles * sizeof(*filePos));
size_t result = 0;
+ clock_t displayClock = 0;
+ clock_t const refreshRate = CLOCKS_PER_SEC * 3 / 10;
+
+# define DISPLAYUPDATE(l, ...) if (notificationLevel>=l) { \
+ if (ZDICT_clockSpan(displayClock) > refreshRate) \
+ { displayClock = clock(); DISPLAY(__VA_ARGS__); \
+ if (notificationLevel>=4) fflush(stdout); } }
/* init */
DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */
@@ -506,7 +505,8 @@ static size_t ZDICT_trainBuffer(dictItem* dictList, U32 dictListSize,
{ size_t pos;
for (pos=0; pos < bufferSize; pos++)
reverseSuffix[suffix[pos]] = (U32)pos;
- /* build file pos */
+ /* note filePos tracks borders between samples.
+ It's not used at this stage, but planned to become useful in a later update */
filePos[0] = 0;
for (pos=1; pos blockSizeMax) srcSize = blockSizeMax; /* protection vs large samples */
- { size_t const errorCode = ZSTD_copyCCtx(esr.zc, esr.ref);
- if (ZSTD_isError(errorCode)) { DISPLAYLEVEL(1, "warning : ZSTD_copyCCtx failed \n"); return; }
- }
+ { size_t const errorCode = ZSTD_copyCCtx(esr.zc, esr.ref, 0);
+ if (ZSTD_isError(errorCode)) { DISPLAYLEVEL(1, "warning : ZSTD_copyCCtx failed \n"); return; }
+ }
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; }
@@ -647,9 +647,10 @@ static void ZDICT_insertSortCount(offsetCount_t table[ZSTD_REP_NUM+1], U32 val,
#define OFFCODE_MAX 30 /* only applicable to first block */
static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
- unsigned compressionLevel,
- const void* srcBuffer, const size_t* fileSizes, unsigned nbFiles,
- const void* dictBuffer, size_t dictBufferSize)
+ unsigned compressionLevel,
+ const void* srcBuffer, const size_t* fileSizes, unsigned nbFiles,
+ const void* dictBuffer, size_t dictBufferSize,
+ unsigned notificationLevel)
{
U32 countLit[256];
HUF_CREATE_STATIC_CTABLE(hufTable, 255);
@@ -690,18 +691,19 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
memset(bestRepOffset, 0, sizeof(bestRepOffset));
if (compressionLevel==0) compressionLevel=g_compressionLevel_default;
params = ZSTD_getParams(compressionLevel, averageSampleSize, dictBufferSize);
- { size_t const beginResult = ZSTD_compressBegin_advanced(esr.ref, dictBuffer, dictBufferSize, params, 0);
- if (ZSTD_isError(beginResult)) {
- eSize = ERROR(GENERIC);
- DISPLAYLEVEL(1, "error : ZSTD_compressBegin_advanced failed \n");
- goto _cleanup;
- } }
+ { size_t const beginResult = ZSTD_compressBegin_advanced(esr.ref, dictBuffer, dictBufferSize, params, 0);
+ if (ZSTD_isError(beginResult)) {
+ eSize = ERROR(GENERIC);
+ DISPLAYLEVEL(1, "error : ZSTD_compressBegin_advanced failed \n");
+ goto _cleanup;
+ } }
/* collect stats on all files */
for (u=0; u= 3) {
+ if (params.notificationLevel>= 3) {
U32 const nb = MIN(25, dictList[0].pos);
U32 const dictContentSize = ZDICT_dictSize(dictList);
U32 u;
@@ -901,14 +904,14 @@ size_t ZDICT_trainFromBuffer_unsafe(
U32 printedLength = MIN(40, length);
DISPLAYLEVEL(3, "%3u:%3u bytes at pos %8u, savings %7u bytes |",
u, length, pos, dictList[u].savings);
- ZDICT_printHex(3, (const char*)samplesBuffer+pos, printedLength);
+ ZDICT_printHex((const char*)samplesBuffer+pos, printedLength);
DISPLAYLEVEL(3, "| \n");
} }
/* create dictionary */
{ U32 dictContentSize = ZDICT_dictSize(dictList);
- if (dictContentSize < targetDictSize/2) {
+ if (dictContentSize < targetDictSize/3) {
DISPLAYLEVEL(2, "! warning : selected content significantly smaller than requested (%u < %u) \n", dictContentSize, (U32)maxDictSize);
if (minRep > MINRATIO) {
DISPLAYLEVEL(2, "! consider increasing selectivity to produce larger dictionary (-s%u) \n", selectivity+1);
@@ -918,12 +921,12 @@ size_t ZDICT_trainFromBuffer_unsafe(
DISPLAYLEVEL(2, "! consider increasing the number of samples (total size : %u MB)\n", (U32)(samplesBuffSize>>20));
}
- if ((dictContentSize > targetDictSize*2) && (nbSamples > 2*MINRATIO) && (selectivity>1)) {
+ if ((dictContentSize > targetDictSize*3) && (nbSamples > 2*MINRATIO) && (selectivity>1)) {
U32 proposedSelectivity = selectivity-1;
while ((nbSamples >> proposedSelectivity) <= MINRATIO) { proposedSelectivity--; }
DISPLAYLEVEL(2, "! note : calculated dictionary significantly larger than requested (%u > %u) \n", dictContentSize, (U32)maxDictSize);
- DISPLAYLEVEL(2, "! you may consider decreasing selectivity to produce denser dictionary (-s%u) \n", proposedSelectivity);
- DISPLAYLEVEL(2, "! but test its efficiency on samples \n");
+ DISPLAYLEVEL(2, "! consider increasing dictionary size, or produce denser dictionary (-s%u) \n", proposedSelectivity);
+ DISPLAYLEVEL(2, "! always test dictionary efficiency on samples \n");
}
/* limit dictionary size */
diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h
index c84aedd1f..642a43516 100644
--- a/lib/dictBuilder/zdict.h
+++ b/lib/dictBuilder/zdict.h
@@ -68,7 +68,7 @@ typedef struct {
int compressionLevel; /* 0 means default; target a specific zstd compression level */
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 */
- unsigned reserved[2]; /* space for future parameters */
+ unsigned reserved[2]; /* reserved space for future parameters */
} ZDICT_params_t;
diff --git a/lib/legacy/zstd_v01.c b/lib/legacy/zstd_v01.c
index 94847d5c8..fe9c5ccdd 100644
--- a/lib/legacy/zstd_v01.c
+++ b/lib/legacy/zstd_v01.c
@@ -13,6 +13,7 @@
******************************************/
#include /* size_t, ptrdiff_t */
#include "zstd_v01.h"
+#include "error_private.h"
/******************************************
@@ -139,11 +140,15 @@ typedef struct
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
#else
# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
# else
-# define FORCE_INLINE static inline
-# endif
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
#endif
@@ -1171,57 +1176,6 @@ static size_t HUF_decompress (void* dst, size_t maxDstSize, const void* cSrc, si
#endif /* FSE_COMMONDEFS_ONLY */
-/*
- zstd - standard compression library
- Header File for static linking only
- Copyright (C) 2014-2015, Yann Collet.
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- 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
- OWNER 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 :
- - zstd source repository : https://github.com/Cyan4973/zstd
- - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c
-*/
-
-/* The objects defined into this file should be considered experimental.
- * They are not labelled stable, as their prototype may change in the future.
- * You can use them for tests, provide feedback, or if you can endure risk of future changes.
- */
-
-/**************************************
-* Error management
-**************************************/
-#define ZSTD_LIST_ERRORS(ITEM) \
- ITEM(ZSTD_OK_NoError) ITEM(ZSTD_ERROR_GENERIC) \
- ITEM(ZSTD_ERROR_MagicNumber) \
- ITEM(ZSTD_ERROR_SrcSize) ITEM(ZSTD_ERROR_maxDstSize_tooSmall) \
- ITEM(ZSTD_ERROR_corruption) \
- ITEM(ZSTD_ERROR_maxCode)
-
-#define ZSTD_GENERATE_ENUM(ENUM) ENUM,
-typedef enum { ZSTD_LIST_ERRORS(ZSTD_GENERATE_ENUM) } ZSTD_errorCodes; /* exposed list of errors; static linking only */
-
/*
zstd - standard compression library
Copyright (C) 2014-2015, Yann Collet.
@@ -1300,17 +1254,9 @@ typedef enum { ZSTD_LIST_ERRORS(ZSTD_GENERATE_ENUM) } ZSTD_errorCodes; /* expo
#endif
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# include /* For Visual 2005 */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
-#else
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
@@ -1491,11 +1437,8 @@ typedef struct ZSTD_Cctx_s
/**************************************
* Error Management
**************************************/
-/* tells if a return value is an error code */
-static unsigned ZSTD_isError(size_t code) { return (code > (size_t)(-ZSTD_ERROR_maxCode)); }
-
/* published entry point */
-unsigned ZSTDv01_isError(size_t code) { return ZSTD_isError(code); }
+unsigned ZSTDv01_isError(size_t code) { return ERR_isError(code); }
/**************************************
@@ -1510,13 +1453,13 @@ unsigned ZSTDv01_isError(size_t code) { return ZSTD_isError(code); }
* Decompression code
**************************************************************/
-static size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
+size_t ZSTDv01_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
{
const BYTE* const in = (const BYTE* const)src;
BYTE headerFlags;
U32 cSize;
- if (srcSize < 3) return (size_t)-ZSTD_ERROR_SrcSize;
+ if (srcSize < 3) return ERROR(srcSize_wrong);
headerFlags = *in;
cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
@@ -1532,7 +1475,7 @@ static size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockPropertie
static size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{
- if (srcSize > maxDstSize) return (size_t)-ZSTD_ERROR_maxDstSize_tooSmall;
+ if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);
memcpy(dst, src, srcSize);
return srcSize;
}
@@ -1549,21 +1492,21 @@ static size_t ZSTD_decompressLiterals(void* ctx,
size_t litSize;
/* check : minimum 2, for litSize, +1, for content */
- if (srcSize <= 3) return (size_t)-ZSTD_ERROR_corruption;
+ if (srcSize <= 3) return ERROR(corruption_detected);
litSize = ip[1] + (ip[0]<<8);
litSize += ((ip[-3] >> 3) & 7) << 16; // mmmmh....
op = oend - litSize;
(void)ctx;
- if (litSize > maxDstSize) return (size_t)-ZSTD_ERROR_maxDstSize_tooSmall;
+ if (litSize > maxDstSize) return ERROR(dstSize_tooSmall);
errorCode = HUF_decompress(op, litSize, ip+2, srcSize-2);
- if (FSE_isError(errorCode)) return (size_t)-ZSTD_ERROR_GENERIC;
+ if (FSE_isError(errorCode)) return ERROR(GENERIC);
return litSize;
}
-static size_t ZSTD_decodeLiteralsBlock(void* ctx,
+size_t ZSTDv01_decodeLiteralsBlock(void* ctx,
void* dst, size_t maxDstSize,
const BYTE** litStart, size_t* litSize,
const void* src, size_t srcSize)
@@ -1574,9 +1517,9 @@ static size_t ZSTD_decodeLiteralsBlock(void* ctx,
BYTE* const oend = ostart + maxDstSize;
blockProperties_t litbp;
- size_t litcSize = ZSTD_getcBlockSize(src, srcSize, &litbp);
- if (ZSTD_isError(litcSize)) return litcSize;
- if (litcSize > srcSize - ZSTD_blockHeaderSize) return (size_t)-ZSTD_ERROR_SrcSize;
+ size_t litcSize = ZSTDv01_getcBlockSize(src, srcSize, &litbp);
+ if (ZSTDv01_isError(litcSize)) return litcSize;
+ if (litcSize > srcSize - ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
ip += ZSTD_blockHeaderSize;
switch(litbp.blockType)
@@ -1589,7 +1532,7 @@ static size_t ZSTD_decodeLiteralsBlock(void* ctx,
case bt_rle:
{
size_t rleSize = litbp.origSize;
- if (rleSize>maxDstSize) return (size_t)-ZSTD_ERROR_maxDstSize_tooSmall;
+ if (rleSize>maxDstSize) return ERROR(dstSize_tooSmall);
memset(oend - rleSize, *ip, rleSize);
*litStart = oend - rleSize;
*litSize = rleSize;
@@ -1599,7 +1542,7 @@ static size_t ZSTD_decodeLiteralsBlock(void* ctx,
case bt_compressed:
{
size_t decodedLitSize = ZSTD_decompressLiterals(ctx, dst, maxDstSize, ip, litcSize);
- if (ZSTD_isError(decodedLitSize)) return decodedLitSize;
+ if (ZSTDv01_isError(decodedLitSize)) return decodedLitSize;
*litStart = oend - decodedLitSize;
*litSize = decodedLitSize;
ip += litcSize;
@@ -1607,14 +1550,14 @@ static size_t ZSTD_decodeLiteralsBlock(void* ctx,
}
case bt_end:
default:
- return (size_t)-ZSTD_ERROR_GENERIC;
+ return ERROR(GENERIC);
}
return ip-istart;
}
-static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,
+size_t ZSTDv01_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,
FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,
const void* src, size_t srcSize)
{
@@ -1626,7 +1569,7 @@ static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* d
size_t dumpsLength;
/* check */
- if (srcSize < 5) return (size_t)-ZSTD_ERROR_SrcSize;
+ if (srcSize < 5) return ERROR(srcSize_wrong);
/* SeqHead */
*nbSeq = ZSTD_readLE16(ip); ip+=2;
@@ -1650,7 +1593,7 @@ static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* d
*dumpsLengthPtr = dumpsLength;
/* check */
- if (ip > iend-3) return (size_t)-ZSTD_ERROR_SrcSize; /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
+ if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
/* sequences */
{
@@ -1669,8 +1612,8 @@ static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* d
default :
{ U32 max = MaxLL;
headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);
- if (FSE_isError(headerSize)) return (size_t)-ZSTD_ERROR_GENERIC;
- if (LLlog > LLFSELog) return (size_t)-ZSTD_ERROR_corruption;
+ if (FSE_isError(headerSize)) return ERROR(GENERIC);
+ if (LLlog > LLFSELog) return ERROR(corruption_detected);
ip += headerSize;
FSE_buildDTable(DTableLL, norm, max, LLlog);
} }
@@ -1679,7 +1622,7 @@ static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* d
{
case bt_rle :
Offlog = 0;
- if (ip > iend-2) return (size_t)-ZSTD_ERROR_SrcSize; /* min : "raw", hence no header, but at least xxLog bits */
+ if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
FSE_buildDTable_rle(DTableOffb, *ip++); break;
case bt_raw :
Offlog = Offbits;
@@ -1687,8 +1630,8 @@ static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* d
default :
{ U32 max = MaxOff;
headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);
- if (FSE_isError(headerSize)) return (size_t)-ZSTD_ERROR_GENERIC;
- if (Offlog > OffFSELog) return (size_t)-ZSTD_ERROR_corruption;
+ if (FSE_isError(headerSize)) return ERROR(GENERIC);
+ if (Offlog > OffFSELog) return ERROR(corruption_detected);
ip += headerSize;
FSE_buildDTable(DTableOffb, norm, max, Offlog);
} }
@@ -1697,7 +1640,7 @@ static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* d
{
case bt_rle :
MLlog = 0;
- if (ip > iend-2) return (size_t)-ZSTD_ERROR_SrcSize; /* min : "raw", hence no header, but at least xxLog bits */
+ if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
FSE_buildDTable_rle(DTableML, *ip++); break;
case bt_raw :
MLlog = MLbits;
@@ -1705,8 +1648,8 @@ static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* d
default :
{ U32 max = MaxML;
headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);
- if (FSE_isError(headerSize)) return (size_t)-ZSTD_ERROR_GENERIC;
- if (MLlog > MLFSELog) return (size_t)-ZSTD_ERROR_corruption;
+ if (FSE_isError(headerSize)) return ERROR(GENERIC);
+ if (MLlog > MLFSELog) return ERROR(corruption_detected);
ip += headerSize;
FSE_buildDTable(DTableML, norm, max, MLlog);
} } }
@@ -1809,9 +1752,9 @@ static size_t ZSTD_execSequence(BYTE* op,
const BYTE* const litEnd = *litPtr + litLength;
/* check */
- if (endMatch > oend) return (size_t)-ZSTD_ERROR_maxDstSize_tooSmall; /* overwrite beyond dst buffer */
- if (litEnd > litLimit) return (size_t)-ZSTD_ERROR_corruption;
- if (sequence.matchLength > (size_t)(*litPtr-op)) return (size_t)-ZSTD_ERROR_maxDstSize_tooSmall; /* overwrite literal segment */
+ if (endMatch > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
+ if (litEnd > litLimit) return ERROR(corruption_detected);
+ if (sequence.matchLength > (size_t)(*litPtr-op)) return ERROR(dstSize_tooSmall); /* overwrite literal segment */
/* copy Literals */
if (((size_t)(*litPtr - op) < 8) || ((size_t)(oend-litEnd) < 8) || (op+litLength > oend-8))
@@ -1822,7 +1765,7 @@ static size_t ZSTD_execSequence(BYTE* op,
*litPtr = litEnd; /* update for next sequence */
/* check : last match must be at a minimum distance of 8 from end of dest buffer */
- if (oend-op < 8) return (size_t)-ZSTD_ERROR_maxDstSize_tooSmall;
+ if (oend-op < 8) return ERROR(dstSize_tooSmall);
/* copy Match */
{
@@ -1832,8 +1775,8 @@ static size_t ZSTD_execSequence(BYTE* op,
U64 saved[2];
/* check */
- if (match < base) return (size_t)-ZSTD_ERROR_corruption;
- if (sequence.offset > (size_t)base) return (size_t)-ZSTD_ERROR_corruption;
+ if (match < base) return ERROR(corruption_detected);
+ if (sequence.offset > (size_t)base) return ERROR(corruption_detected);
/* save beginning of literal sequence, in case of write overlap */
if (overlapRisk)
@@ -1911,10 +1854,10 @@ static size_t ZSTD_decompressSequences(
BYTE* const base = (BYTE*) (dctx->base);
/* Build Decoding Tables */
- errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
+ errorCode = ZSTDv01_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
DTableLL, DTableML, DTableOffb,
ip, iend-ip);
- if (ZSTD_isError(errorCode)) return errorCode;
+ if (ZSTDv01_isError(errorCode)) return errorCode;
ip += errorCode;
/* Regen sequences */
@@ -1927,7 +1870,7 @@ static size_t ZSTD_decompressSequences(
seqState.dumpsEnd = dumps + dumpsLength;
seqState.prevOffset = 1;
errorCode = FSE_initDStream(&(seqState.DStream), ip, iend-ip);
- if (FSE_isError(errorCode)) return (size_t)-ZSTD_ERROR_corruption;
+ if (FSE_isError(errorCode)) return ERROR(corruption_detected);
FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
@@ -1938,18 +1881,18 @@ static size_t ZSTD_decompressSequences(
nbSeq--;
ZSTD_decodeSequence(&sequence, &seqState);
oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend);
- if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+ if (ZSTDv01_isError(oneSeqSize)) return oneSeqSize;
op += oneSeqSize;
}
/* check if reached exact end */
- if ( !FSE_endOfDStream(&(seqState.DStream)) ) return (size_t)-ZSTD_ERROR_corruption; /* requested too much : data is corrupted */
- if (nbSeq<0) return (size_t)-ZSTD_ERROR_corruption; /* requested too many sequences : data is corrupted */
+ if ( !FSE_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected); /* requested too much : data is corrupted */
+ if (nbSeq<0) return ERROR(corruption_detected); /* requested too many sequences : data is corrupted */
/* last literal segment */
{
size_t lastLLSize = litEnd - litPtr;
- if (op+lastLLSize > oend) return (size_t)-ZSTD_ERROR_maxDstSize_tooSmall;
+ if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
if (op != litPtr) memmove(op, litPtr, lastLLSize);
op += lastLLSize;
}
@@ -1971,8 +1914,8 @@ static size_t ZSTD_decompressBlock(
size_t errorCode;
/* Decode literals sub-block */
- errorCode = ZSTD_decodeLiteralsBlock(ctx, dst, maxDstSize, &litPtr, &litSize, src, srcSize);
- if (ZSTD_isError(errorCode)) return errorCode;
+ errorCode = ZSTDv01_decodeLiteralsBlock(ctx, dst, maxDstSize, &litPtr, &litSize, src, srcSize);
+ if (ZSTDv01_isError(errorCode)) return errorCode;
ip += errorCode;
srcSize -= errorCode;
@@ -1993,20 +1936,20 @@ size_t ZSTDv01_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const voi
blockProperties_t blockProperties;
/* Frame Header */
- if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return (size_t)-ZSTD_ERROR_SrcSize;
+ if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
magicNumber = ZSTD_readBE32(src);
- if (magicNumber != ZSTD_magicNumber) return (size_t)-ZSTD_ERROR_MagicNumber;
+ if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
/* Loop on each block */
while (1)
{
- size_t blockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);
- if (ZSTD_isError(blockSize)) return blockSize;
+ size_t blockSize = ZSTDv01_getcBlockSize(ip, iend-ip, &blockProperties);
+ if (ZSTDv01_isError(blockSize)) return blockSize;
ip += ZSTD_blockHeaderSize;
remainingSize -= ZSTD_blockHeaderSize;
- if (blockSize > remainingSize) return (size_t)-ZSTD_ERROR_SrcSize;
+ if (blockSize > remainingSize) return ERROR(srcSize_wrong);
switch(blockProperties.blockType)
{
@@ -2017,18 +1960,18 @@ size_t ZSTDv01_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const voi
errorCode = ZSTD_copyUncompressedBlock(op, oend-op, ip, blockSize);
break;
case bt_rle :
- return (size_t)-ZSTD_ERROR_GENERIC; /* not yet supported */
+ return ERROR(GENERIC); /* not yet supported */
break;
case bt_end :
/* end of frame */
- if (remainingSize) return (size_t)-ZSTD_ERROR_SrcSize;
+ if (remainingSize) return ERROR(srcSize_wrong);
break;
default:
- return (size_t)-ZSTD_ERROR_GENERIC;
+ return ERROR(GENERIC);
}
if (blockSize == 0) break; /* bt_end */
- if (ZSTD_isError(errorCode)) return errorCode;
+ if (ZSTDv01_isError(errorCode)) return errorCode;
op += errorCode;
ip += blockSize;
remainingSize -= blockSize;
@@ -2082,7 +2025,7 @@ size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSi
dctx_t* ctx = (dctx_t*)dctx;
/* Sanity check */
- if (srcSize != ctx->expected) return (size_t)-ZSTD_ERROR_SrcSize;
+ if (srcSize != ctx->expected) return ERROR(srcSize_wrong);
if (dst != ctx->previousDstEnd) /* not contiguous */
ctx->base = dst;
@@ -2091,7 +2034,7 @@ size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSi
{
/* Check frame magic header */
U32 magicNumber = ZSTD_readBE32(src);
- if (magicNumber != ZSTD_magicNumber) return (size_t)-ZSTD_ERROR_MagicNumber;
+ if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
ctx->phase = 1;
ctx->expected = ZSTD_blockHeaderSize;
return 0;
@@ -2101,8 +2044,8 @@ size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSi
if (ctx->phase == 1)
{
blockProperties_t bp;
- size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
- if (ZSTD_isError(blockSize)) return blockSize;
+ size_t blockSize = ZSTDv01_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
+ if (ZSTDv01_isError(blockSize)) return blockSize;
if (bp.blockType == bt_end)
{
ctx->expected = 0;
@@ -2130,13 +2073,13 @@ size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSi
rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);
break;
case bt_rle :
- return (size_t)-ZSTD_ERROR_GENERIC; /* not yet handled */
+ return ERROR(GENERIC); /* not yet handled */
break;
case bt_end : /* should never happen (filtered at phase 1) */
rSize = 0;
break;
default:
- return (size_t)-ZSTD_ERROR_GENERIC;
+ return ERROR(GENERIC);
}
ctx->phase = 1;
ctx->expected = ZSTD_blockHeaderSize;
diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c
index af1366208..de1592e18 100644
--- a/lib/legacy/zstd_v02.c
+++ b/lib/legacy/zstd_v02.c
@@ -7,15 +7,11 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-#ifndef ERROR_H_MODULE
-#define ERROR_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
#include /* size_t, ptrdiff_t */
#include "zstd_v02.h"
+#include "error_private.h"
+
/******************************************
* Compiler-specific
@@ -24,46 +20,6 @@ extern "C" {
# include /* _byteswap_ulong */
# include /* _byteswap_* */
#endif
-#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-# define ERR_STATIC static inline
-#elif defined(_MSC_VER)
-# define ERR_STATIC static __inline
-#elif defined(__GNUC__)
-# define ERR_STATIC static __attribute__((unused))
-#else
-# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
-#endif
-
-
-/******************************************
-* Error Management
-******************************************/
-#define PREFIX(name) ZSTD_error_##name
-
-#define ERROR(name) (size_t)-PREFIX(name)
-
-#define ERROR_LIST(ITEM) \
- ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \
- ITEM(PREFIX(memory_allocation)) \
- ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \
- ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \
- ITEM(PREFIX(tableLog_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooSmall)) \
- ITEM(PREFIX(maxCode))
-
-#define ERROR_GENERATE_ENUM(ENUM) ENUM,
-typedef enum { ERROR_LIST(ERROR_GENERATE_ENUM) } ERR_codes; /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */
-
-#define ERROR_CONVERTTOSTRING(STRING) #STRING,
-#define ERROR_GENERATE_STRING(EXPR) ERROR_CONVERTTOSTRING(EXPR)
-
-ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_H_MODULE */
/* ******************************************************************
@@ -1122,12 +1078,15 @@ typedef struct ZSTD_DCtx_s ZSTD_DCtx;
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
# else
-# define FORCE_INLINE static inline
-# endif
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
#endif
@@ -1595,15 +1554,7 @@ static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, siz
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
@@ -2790,17 +2741,9 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
#endif
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# include /* For Visual 2005 */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
-#else
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c
index 637204deb..caad331d3 100644
--- a/lib/legacy/zstd_v03.c
+++ b/lib/legacy/zstd_v03.c
@@ -7,15 +7,11 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-#ifndef ERROR_H_MODULE
-#define ERROR_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
#include /* size_t, ptrdiff_t */
#include "zstd_v03.h"
+#include "error_private.h"
+
/******************************************
* Compiler-specific
@@ -24,47 +20,8 @@ extern "C" {
# include /* _byteswap_ulong */
# include /* _byteswap_* */
#endif
-#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-# define ERR_STATIC static inline
-#elif defined(_MSC_VER)
-# define ERR_STATIC static __inline
-#elif defined(__GNUC__)
-# define ERR_STATIC static __attribute__((unused))
-#else
-# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
-#endif
-/******************************************
-* Error Management
-******************************************/
-#define PREFIX(name) ZSTD_error_##name
-
-#define ERROR(name) (size_t)-PREFIX(name)
-
-#define ERROR_LIST(ITEM) \
- ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \
- ITEM(PREFIX(memory_allocation)) \
- ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \
- ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \
- ITEM(PREFIX(tableLog_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooSmall)) \
- ITEM(PREFIX(maxCode))
-
-#define ERROR_GENERATE_ENUM(ENUM) ENUM,
-typedef enum { ERROR_LIST(ERROR_GENERATE_ENUM) } ERR_codes; /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */
-
-#define ERROR_CONVERTTOSTRING(STRING) #STRING,
-#define ERROR_GENERATE_STRING(EXPR) ERROR_CONVERTTOSTRING(EXPR)
-
-ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_H_MODULE */
-
/* ******************************************************************
mem.h
@@ -1122,12 +1079,15 @@ typedef struct ZSTD_DCtx_s ZSTD_DCtx;
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
# else
-# define FORCE_INLINE static inline
-# endif
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
#endif
@@ -1588,25 +1548,13 @@ static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, siz
#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
/* inline is defined */
#elif defined(_MSC_VER)
+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# define inline __inline
#else
# define inline /* disable inline */
#endif
-#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
-# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
-#endif
-
-
/****************************************************************
* Includes
****************************************************************/
@@ -2432,17 +2380,11 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
#endif
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# include /* For Visual 2005 */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
#else
# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
diff --git a/lib/legacy/zstd_v04.c b/lib/legacy/zstd_v04.c
index 1239bdb3a..c9dcb94e0 100644
--- a/lib/legacy/zstd_v04.c
+++ b/lib/legacy/zstd_v04.c
@@ -10,6 +10,7 @@
/*- Dependencies -*/
#include "zstd_v04.h"
+#include "error_private.h"
/* ******************************************************************
@@ -250,79 +251,6 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
#endif /* MEM_H_MODULE */
-/* ******************************************************************
- Error codes list
- Copyright (C) 2016, Yann Collet
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- 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
- OWNER 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 :
- - Source repository : https://github.com/Cyan4973/zstd
-****************************************************************** */
-#ifndef ERROR_PUBLIC_H_MODULE
-#define ERROR_PUBLIC_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-
-/* ****************************************
-* error list
-******************************************/
-enum {
- ZSTD_error_No_Error,
- ZSTD_error_GENERIC,
- ZSTD_error_prefix_unknown,
- ZSTD_error_frameParameter_unsupported,
- ZSTD_error_frameParameter_unsupportedBy32bitsImplementation,
- ZSTD_error_init_missing,
- ZSTD_error_memory_allocation,
- ZSTD_error_stage_wrong,
- ZSTD_error_dstSize_tooSmall,
- ZSTD_error_srcSize_wrong,
- ZSTD_error_corruption_detected,
- ZSTD_error_tableLog_tooLarge,
- ZSTD_error_maxSymbolValue_tooLarge,
- ZSTD_error_maxSymbolValue_tooSmall,
- ZSTD_error_maxCode
-};
-
-/* note : functions provide error codes in reverse negative order,
- so compare with (size_t)(0-enum) */
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_PUBLIC_H_MODULE */
-
-
-
/*
zstd - standard compression library
Header File for static linking only
@@ -456,115 +384,6 @@ static size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstS
}
#endif
-/* ******************************************************************
- Error codes and messages
- Copyright (C) 2013-2016, Yann Collet
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- 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
- OWNER 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 :
- - Source repository : https://github.com/Cyan4973/zstd
-****************************************************************** */
-/* Note : this module is expected to remain private, do not expose it */
-
-#ifndef ERROR_H_MODULE
-#define ERROR_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-
-/* *****************************************
-* Includes
-******************************************/
-#include /* size_t, ptrdiff_t */
-
-
-/* *****************************************
-* Compiler-specific
-******************************************/
-#if defined(__GNUC__)
-# define ERR_STATIC static __attribute__((unused))
-#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-# define ERR_STATIC static inline
-#elif defined(_MSC_VER)
-# define ERR_STATIC static __inline
-#else
-# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
-#endif
-
-
-/* *****************************************
-* Error Codes
-******************************************/
-#define PREFIX(name) ZSTD_error_##name
-
-#ifdef ERROR
-# undef ERROR /* reported already defined on VS 2015 by Rich Geldreich */
-#endif
-#define ERROR(name) (size_t)-PREFIX(name)
-
-ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
-
-
-/* *****************************************
-* Error Strings
-******************************************/
-
-ERR_STATIC const char* ERR_getErrorName(size_t code)
-{
- static const char* codeError = "Unspecified error code";
- switch( (size_t)(0-code) )
- {
- case ZSTD_error_No_Error: return "No error detected";
- case ZSTD_error_GENERIC: return "Error (generic)";
- case ZSTD_error_prefix_unknown: return "Unknown frame descriptor";
- case ZSTD_error_frameParameter_unsupported: return "Unsupported frame parameter";
- case ZSTD_error_frameParameter_unsupportedBy32bitsImplementation: return "Frame parameter unsupported in 32-bits mode";
- case ZSTD_error_init_missing: return "Context should be init first";
- case ZSTD_error_memory_allocation: return "Allocation error : not enough memory";
- case ZSTD_error_dstSize_tooSmall: return "Destination buffer is too small";
- case ZSTD_error_srcSize_wrong: return "Src size incorrect";
- case ZSTD_error_corruption_detected: return "Corrupted block detected";
- case ZSTD_error_tableLog_tooLarge: return "tableLog requires too much memory";
- case ZSTD_error_maxSymbolValue_tooLarge: return "Unsupported max possible Symbol Value : too large";
- case ZSTD_error_maxSymbolValue_tooSmall: return "Specified maxSymbolValue is too small";
- case ZSTD_error_maxCode:
- default: return codeError;
- }
-}
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_H_MODULE */
-
#endif /* ZSTD_STATIC_H */
@@ -1380,12 +1199,15 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
# else
-# define FORCE_INLINE static inline
-# endif
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
#endif
@@ -2021,15 +1843,7 @@ static size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
@@ -2837,17 +2651,9 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
* Compiler specifics
*********************************************************/
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# include /* For Visual 2005 */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
-#else
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
@@ -2968,7 +2774,7 @@ static size_t ZSTD_decodeFrameHeader_Part2(ZSTD_DCtx* zc, const void* src, size_
size_t result;
if (srcSize != zc->headerSize) return ERROR(srcSize_wrong);
result = ZSTD_getFrameParams(&(zc->params), src, srcSize);
- if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bitsImplementation);
+ if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bits);
return result;
}
diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c
index 96fdf35e9..5027e2b8b 100644
--- a/lib/legacy/zstd_v05.c
+++ b/lib/legacy/zstd_v05.c
@@ -10,6 +10,7 @@
/*- Dependencies -*/
#include "zstd_v05.h"
+#include "error_private.h"
/* ******************************************************************
@@ -254,79 +255,6 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
#endif /* MEM_H_MODULE */
-/* ******************************************************************
- Error codes list
- Copyright (C) 2016, Yann Collet
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- 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
- OWNER 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 :
- - Source repository : https://github.com/Cyan4973/zstd
-****************************************************************** */
-#ifndef ERROR_PUBLIC_H_MODULE
-#define ERROR_PUBLIC_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-
-/* ****************************************
-* error codes list
-******************************************/
-typedef enum {
- ZSTDv05_error_no_error,
- ZSTDv05_error_GENERIC,
- ZSTDv05_error_prefix_unknown,
- ZSTDv05_error_frameParameter_unsupported,
- ZSTDv05_error_frameParameter_unsupportedBy32bits,
- ZSTDv05_error_init_missing,
- ZSTDv05_error_memory_allocation,
- ZSTDv05_error_stage_wrong,
- ZSTDv05_error_dstSize_tooSmall,
- ZSTDv05_error_srcSize_wrong,
- ZSTDv05_error_corruption_detected,
- ZSTDv05_error_tableLog_tooLarge,
- ZSTDv05_error_maxSymbolValue_tooLarge,
- ZSTDv05_error_maxSymbolValue_tooSmall,
- ZSTDv05_error_dictionary_corrupted,
- ZSTDv05_error_maxCode
-} ZSTDv05_ErrorCode;
-
-/* note : functions provide error codes in reverse negative order,
- so compare with (size_t)(0-enum) */
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_PUBLIC_H_MODULE */
-
-
/*
zstd - standard compression library
Header File for static linking only
@@ -470,119 +398,6 @@ size_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx, void* dst, size_t dstCapacity
#endif /* ZSTDv05_STATIC_H */
-
-/* ******************************************************************
- Error codes and messages
- Copyright (C) 2013-2016, Yann Collet
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- 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
- OWNER 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 :
- - Source repository : https://github.com/Cyan4973/zstd
-****************************************************************** */
-/* Note : this module is expected to remain private, do not expose it */
-
-#ifndef ERROR_H_MODULE
-#define ERROR_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-
-
-/* ****************************************
-* Compiler-specific
-******************************************/
-#if defined(__GNUC__)
-# define ERR_STATIC static __attribute__((unused))
-#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-# define ERR_STATIC static inline
-#elif defined(_MSC_VER)
-# define ERR_STATIC static __inline
-#else
-# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
-#endif
-
-
-/*-****************************************
-* Customization
-******************************************/
-typedef ZSTDv05_ErrorCode ERR_enum;
-#define PREFIX(name) ZSTDv05_error_##name
-
-
-/*-****************************************
-* Error codes handling
-******************************************/
-#ifdef ERROR
-# undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
-#endif
-#define ERROR(name) (size_t)-PREFIX(name)
-
-ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
-
-ERR_STATIC ERR_enum ERR_getError(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
-
-
-/*-****************************************
-* Error Strings
-******************************************/
-
-ERR_STATIC const char* ERR_getErrorName(size_t code)
-{
- static const char* notErrorCode = "Unspecified error code";
- switch( ERR_getError(code) )
- {
- case PREFIX(no_error): return "No error detected";
- case PREFIX(GENERIC): return "Error (generic)";
- case PREFIX(prefix_unknown): return "Unknown frame descriptor";
- case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
- case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode";
- case PREFIX(init_missing): return "Context should be init first";
- case PREFIX(memory_allocation): return "Allocation error : not enough memory";
- case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
- case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
- case PREFIX(srcSize_wrong): return "Src size incorrect";
- case PREFIX(corruption_detected): return "Corrupted block detected";
- case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory";
- case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max possible Symbol Value : too large";
- case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
- case PREFIX(dictionary_corrupted): return "Dictionary is corrupted";
- case PREFIX(maxCode):
- default: return notErrorCode; /* should be impossible, due to ERR_getError() */
- }
-}
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_H_MODULE */
/*
zstd_internal - common functions to include
Header File for include
@@ -1380,12 +1195,15 @@ MEM_STATIC unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr)
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
# else
-# define FORCE_INLINE static inline
-# endif
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
#endif
@@ -2002,14 +1820,7 @@ size_t HUFv05_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#else
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
@@ -2858,17 +2669,9 @@ size_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cS
* Compiler specifics
*********************************************************/
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# include /* For Visual 2005 */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
-#else
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
@@ -2895,9 +2698,6 @@ static void ZSTDv05_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
* tells if a return value is an error code */
unsigned ZSTDv05_isError(size_t code) { return ERR_isError(code); }
-/*! ZSTDv05_getError() :
-* convert a `size_t` function result into a proper ZSTDv05_errorCode enum */
-ZSTDv05_ErrorCode ZSTDv05_getError(size_t code) { return ERR_getError(code); }
/*! ZSTDv05_getErrorName() :
* provides error code string (useful for debugging) */
diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c
index 6bd463b6e..d9e89f806 100644
--- a/lib/legacy/zstd_v06.c
+++ b/lib/legacy/zstd_v06.c
@@ -13,6 +13,7 @@
#include /* size_t, ptrdiff_t */
#include /* memcpy */
#include /* malloc, free, qsort */
+#include "error_private.h"
@@ -273,77 +274,6 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
#endif /* MEM_H_MODULE */
-/* ******************************************************************
- Error codes list
- Copyright (C) 2016, Yann Collet
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- 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
- OWNER 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 :
- - Homepage : http://www.zstd.net
-****************************************************************** */
-#ifndef ERROR_PUBLIC_H_MODULE
-#define ERROR_PUBLIC_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-
-/* ****************************************
-* error codes list
-******************************************/
-typedef enum {
- ZSTDv06_error_no_error,
- ZSTDv06_error_GENERIC,
- ZSTDv06_error_prefix_unknown,
- ZSTDv06_error_frameParameter_unsupported,
- ZSTDv06_error_frameParameter_unsupportedBy32bits,
- ZSTDv06_error_compressionParameter_unsupported,
- ZSTDv06_error_init_missing,
- ZSTDv06_error_memory_allocation,
- ZSTDv06_error_stage_wrong,
- ZSTDv06_error_dstSize_tooSmall,
- ZSTDv06_error_srcSize_wrong,
- ZSTDv06_error_corruption_detected,
- ZSTDv06_error_tableLog_tooLarge,
- ZSTDv06_error_maxSymbolValue_tooLarge,
- ZSTDv06_error_maxSymbolValue_tooSmall,
- ZSTDv06_error_dictionary_corrupted,
- ZSTDv06_error_maxCode
-} ZSTDv06_ErrorCode;
-
-/* note : compare with size_t function results using ZSTDv06_getError() */
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_PUBLIC_H_MODULE */
/*
zstd - standard compression library
Header File for static linking only
@@ -396,7 +326,7 @@ extern "C" {
* It avoids reloading the dictionary each time.
* `preparedDCtx` must have been properly initialized using ZSTDv06_decompressBegin_usingDict().
* Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */
-ZSTDLIB_API size_t ZSTDv06_decompress_usingPreparedDCtx(
+ZSTDLIBv06_API size_t ZSTDv06_decompress_usingPreparedDCtx(
ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
@@ -407,7 +337,7 @@ ZSTDLIB_API size_t ZSTDv06_decompress_usingPreparedDCtx(
static const size_t ZSTDv06_frameHeaderSize_min = 5;
static const size_t ZSTDv06_frameHeaderSize_max = ZSTDv06_FRAMEHEADERSIZE_MAX;
-ZSTDLIB_API size_t ZSTDv06_decompressBegin(ZSTDv06_DCtx* dctx);
+ZSTDLIBv06_API size_t ZSTDv06_decompressBegin(ZSTDv06_DCtx* dctx);
/*
Streaming decompression, direct mode (bufferless)
@@ -466,140 +396,15 @@ ZSTDLIB_API size_t ZSTDv06_decompressBegin(ZSTDv06_DCtx* dctx);
*/
#define ZSTDv06_BLOCKSIZE_MAX (128 * 1024) /* define, for static allocation */
-ZSTDLIB_API size_t ZSTDv06_decompressBlock(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIBv06_API size_t ZSTDv06_decompressBlock(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-/*-*************************************
-* Error management
-***************************************/
-/*! ZSTDv06_getErrorCode() :
- convert a `size_t` function result into a `ZSTDv06_ErrorCode` enum type,
- which can be used to compare directly with enum list published into "error_public.h" */
-ZSTDLIB_API ZSTDv06_ErrorCode ZSTDv06_getErrorCode(size_t functionResult);
-ZSTDLIB_API const char* ZSTDv06_getErrorString(ZSTDv06_ErrorCode code);
-
#if defined (__cplusplus)
}
#endif
#endif /* ZSTDv06_STATIC_H */
-/* ******************************************************************
- Error codes and messages
- Copyright (C) 2013-2016, Yann Collet
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- 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
- OWNER 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 :
- - Homepage : http://www.zstd.net
-****************************************************************** */
-/* Note : this module is expected to remain private, do not expose it */
-
-#ifndef ERROR_H_MODULE
-#define ERROR_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-
-/* ****************************************
-* Compiler-specific
-******************************************/
-#if defined(__GNUC__)
-# define ERR_STATIC static __attribute__((unused))
-#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-# define ERR_STATIC static inline
-#elif defined(_MSC_VER)
-# define ERR_STATIC static __inline
-#else
-# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
-#endif
-
-
-/*-****************************************
-* Customization (error_public.h)
-******************************************/
-typedef ZSTDv06_ErrorCode ERR_enum;
-#define PREFIX(name) ZSTDv06_error_##name
-
-
-/*-****************************************
-* Error codes handling
-******************************************/
-#ifdef ERROR
-# undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
-#endif
-#define ERROR(name) ((size_t)-PREFIX(name))
-
-ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
-
-ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
-
-
-/*-****************************************
-* Error Strings
-******************************************/
-
-ERR_STATIC const char* ERR_getErrorString(ERR_enum code)
-{
- static const char* notErrorCode = "Unspecified error code";
- switch( code )
- {
- case PREFIX(no_error): return "No error detected";
- case PREFIX(GENERIC): return "Error (generic)";
- case PREFIX(prefix_unknown): return "Unknown frame descriptor";
- case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
- case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode";
- case PREFIX(compressionParameter_unsupported): return "Compression parameter is out of bound";
- case PREFIX(init_missing): return "Context should be init first";
- case PREFIX(memory_allocation): return "Allocation error : not enough memory";
- case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
- case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
- case PREFIX(srcSize_wrong): return "Src size incorrect";
- case PREFIX(corruption_detected): return "Corrupted block detected";
- case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
- case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
- case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
- case PREFIX(dictionary_corrupted): return "Dictionary is corrupted";
- case PREFIX(maxCode):
- default: return notErrorCode;
- }
-}
-
-ERR_STATIC const char* ERR_getErrorName(size_t code)
-{
- return ERR_getErrorString(ERR_getErrorCode(code));
-}
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_H_MODULE */
/*
zstd_internal - common functions to include
Header File for include
@@ -1665,12 +1470,15 @@ size_t FSEv06_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
# else
-# define FORCE_INLINE static inline
-# endif
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
#endif
@@ -2238,14 +2046,7 @@ MEM_STATIC size_t HUFv06_readStats(BYTE* huffWeight, size_t hwSize, U32* rankSta
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#else
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
@@ -2990,14 +2791,6 @@ unsigned ZSTDv06_isError(size_t code) { return ERR_isError(code); }
* provides error code string from function result (useful for debugging) */
const char* ZSTDv06_getErrorName(size_t code) { return ERR_getErrorName(code); }
-/*! ZSTDv06_getError() :
-* convert a `size_t` function result into a proper ZSTDv06_errorCode enum */
-ZSTDv06_ErrorCode ZSTDv06_getErrorCode(size_t code) { return ERR_getErrorCode(code); }
-
-/*! ZSTDv06_getErrorString() :
-* provides error code string from enum */
-const char* ZSTDv06_getErrorString(ZSTDv06_ErrorCode code) { return ERR_getErrorName(code); }
-
/* **************************************************************
* ZBUFF Error Management
@@ -3054,16 +2847,9 @@ const char* ZBUFFv06_getErrorName(size_t errorCode) { return ERR_getErrorName(er
* Compiler specifics
*********************************************************/
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# include /* For Visual 2005 */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
-#else
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
diff --git a/lib/legacy/zstd_v06.h b/lib/legacy/zstd_v06.h
index bcc6efbc3..14040abdd 100644
--- a/lib/legacy/zstd_v06.h
+++ b/lib/legacy/zstd_v06.h
@@ -14,23 +14,19 @@
extern "C" {
#endif
-/*-*************************************
-* Dependencies
-***************************************/
+/*====== Dependency ======*/
#include /* size_t */
-/*-***************************************************************
-* Export parameters
-*****************************************************************/
+/*====== Export for Windows ======*/
/*!
* ZSTDv06_DLL_EXPORT :
* Enable exporting of functions when building a Windows DLL
*/
#if defined(_WIN32) && defined(ZSTDv06_DLL_EXPORT) && (ZSTDv06_DLL_EXPORT==1)
-# define ZSTDLIB_API __declspec(dllexport)
+# define ZSTDLIBv06_API __declspec(dllexport)
#else
-# define ZSTDLIB_API
+# define ZSTDLIBv06_API
#endif
@@ -42,18 +38,18 @@ extern "C" {
`dstCapacity` must be large enough, equal or larger than originalSize.
@return : the number of bytes decompressed into `dst` (<= `dstCapacity`),
or an errorCode if it fails (which can be tested using ZSTDv06_isError()) */
-ZSTDLIB_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity,
- const void* src, size_t compressedSize);
+ZSTDLIBv06_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity,
+ const void* src, size_t compressedSize);
/* *************************************
* Helper functions
***************************************/
-ZSTDLIB_API size_t ZSTDv06_compressBound(size_t srcSize); /*!< maximum compressed size (worst case scenario) */
+ZSTDLIBv06_API size_t ZSTDv06_compressBound(size_t srcSize); /*!< maximum compressed size (worst case scenario) */
/* Error Management */
-ZSTDLIB_API unsigned ZSTDv06_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
-ZSTDLIB_API const char* ZSTDv06_getErrorName(size_t code); /*!< provides readable string for an error code */
+ZSTDLIBv06_API unsigned ZSTDv06_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
+ZSTDLIBv06_API const char* ZSTDv06_getErrorName(size_t code); /*!< provides readable string for an error code */
/* *************************************
@@ -61,12 +57,12 @@ ZSTDLIB_API const char* ZSTDv06_getErrorName(size_t code); /*!< provides rea
***************************************/
/** Decompression context */
typedef struct ZSTDv06_DCtx_s ZSTDv06_DCtx;
-ZSTDLIB_API ZSTDv06_DCtx* ZSTDv06_createDCtx(void);
-ZSTDLIB_API size_t ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx); /*!< @return : errorCode */
+ZSTDLIBv06_API ZSTDv06_DCtx* ZSTDv06_createDCtx(void);
+ZSTDLIBv06_API size_t ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx); /*!< @return : errorCode */
/** ZSTDv06_decompressDCtx() :
* Same as ZSTDv06_decompress(), but requires an already allocated ZSTDv06_DCtx (see ZSTDv06_createDCtx()) */
-ZSTDLIB_API size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIBv06_API size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
/*-***********************
@@ -76,10 +72,10 @@ ZSTDLIB_API size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* ctx, void* dst, size_t d
* Decompression using a pre-defined Dictionary content (see dictBuilder).
* Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted.
* Note : dict can be NULL, in which case, it's equivalent to ZSTDv06_decompressDCtx() */
-ZSTDLIB_API size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const void* dict,size_t dictSize);
+ZSTDLIBv06_API size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize);
/*-************************
@@ -88,12 +84,12 @@ ZSTDLIB_API size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,
struct ZSTDv06_frameParams_s { unsigned long long frameContentSize; unsigned windowLog; };
typedef struct ZSTDv06_frameParams_s ZSTDv06_frameParams;
-ZSTDLIB_API size_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input */
-ZSTDLIB_API size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize);
-ZSTDLIB_API void ZSTDv06_copyDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx);
+ZSTDLIBv06_API size_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input */
+ZSTDLIBv06_API size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize);
+ZSTDLIBv06_API void ZSTDv06_copyDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx);
-ZSTDLIB_API size_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx);
-ZSTDLIB_API size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIBv06_API size_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx);
+ZSTDLIBv06_API size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
@@ -102,15 +98,15 @@ ZSTDLIB_API size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, siz
***************************************/
typedef struct ZBUFFv06_DCtx_s ZBUFFv06_DCtx;
-ZSTDLIB_API ZBUFFv06_DCtx* ZBUFFv06_createDCtx(void);
-ZSTDLIB_API size_t ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* dctx);
+ZSTDLIBv06_API ZBUFFv06_DCtx* ZBUFFv06_createDCtx(void);
+ZSTDLIBv06_API size_t ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* dctx);
-ZSTDLIB_API size_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* dctx);
-ZSTDLIB_API size_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* dctx, const void* dict, size_t dictSize);
+ZSTDLIBv06_API size_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* dctx);
+ZSTDLIBv06_API size_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* dctx, const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* dctx,
- void* dst, size_t* dstCapacityPtr,
- const void* src, size_t* srcSizePtr);
+ZSTDLIBv06_API size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* dctx,
+ void* dst, size_t* dstCapacityPtr,
+ const void* src, size_t* srcSizePtr);
/*-***************************************************************************
* Streaming decompression howto
@@ -140,13 +136,13 @@ ZSTDLIB_API size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* dctx,
/* *************************************
* Tool functions
***************************************/
-ZSTDLIB_API unsigned ZBUFFv06_isError(size_t errorCode);
-ZSTDLIB_API const char* ZBUFFv06_getErrorName(size_t errorCode);
+ZSTDLIBv06_API unsigned ZBUFFv06_isError(size_t errorCode);
+ZSTDLIBv06_API const char* ZBUFFv06_getErrorName(size_t errorCode);
/** Functions below provide recommended buffer sizes for Compression or Decompression operations.
* These sizes are just hints, they tend to offer better latency */
-ZSTDLIB_API size_t ZBUFFv06_recommendedDInSize(void);
-ZSTDLIB_API size_t ZBUFFv06_recommendedDOutSize(void);
+ZSTDLIBv06_API size_t ZBUFFv06_recommendedDInSize(void);
+ZSTDLIBv06_API size_t ZBUFFv06_recommendedDOutSize(void);
/*-*************************************
diff --git a/lib/legacy/zstd_v07.c b/lib/legacy/zstd_v07.c
index f948069e0..f4c8073f9 100644
--- a/lib/legacy/zstd_v07.c
+++ b/lib/legacy/zstd_v07.c
@@ -21,6 +21,8 @@
#define HUFv07_STATIC_LINKING_ONLY /* HUFv07_TABLELOG_ABSOLUTEMAX */
#define ZSTDv07_STATIC_LINKING_ONLY
+#include "error_private.h"
+
#ifdef ZSTDv07_STATIC_LINKING_ONLY
@@ -66,27 +68,27 @@ typedef struct { ZSTDv07_allocFunction customAlloc; ZSTDv07_freeFunction customF
/*! ZSTDv07_estimateDCtxSize() :
* Gives the potential amount of memory allocated to create a ZSTDv07_DCtx */
-ZSTDLIB_API size_t ZSTDv07_estimateDCtxSize(void);
+ZSTDLIBv07_API size_t ZSTDv07_estimateDCtxSize(void);
/*! ZSTDv07_createDCtx_advanced() :
* Create a ZSTD decompression context using external alloc and free functions */
-ZSTDLIB_API ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem);
+ZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem);
/*! ZSTDv07_sizeofDCtx() :
* Gives the amount of memory used by a given ZSTDv07_DCtx */
-ZSTDLIB_API size_t ZSTDv07_sizeofDCtx(const ZSTDv07_DCtx* dctx);
+ZSTDLIBv07_API size_t ZSTDv07_sizeofDCtx(const ZSTDv07_DCtx* dctx);
/* ******************************************************************
* Buffer-less streaming functions (synchronous mode)
********************************************************************/
-ZSTDLIB_API size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx);
-ZSTDLIB_API size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize);
-ZSTDLIB_API void ZSTDv07_copyDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* preparedDCtx);
+ZSTDLIBv07_API size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx);
+ZSTDLIBv07_API size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize);
+ZSTDLIBv07_API void ZSTDv07_copyDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* preparedDCtx);
-ZSTDLIB_API size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx);
-ZSTDLIB_API size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIBv07_API size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx);
+ZSTDLIBv07_API size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
/*
Buffer-less streaming decompression (synchronous mode)
@@ -167,8 +169,8 @@ ZSTDLIB_API size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, siz
*/
#define ZSTDv07_BLOCKSIZE_ABSOLUTEMAX (128 * 1024) /* define, for static allocation */
-ZSTDLIB_API size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-ZSTDLIB_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful for uncompressed blocks */
+ZSTDLIBv07_API size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful for uncompressed blocks */
#endif /* ZSTDv07_STATIC_LINKING_ONLY */
@@ -427,203 +429,6 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
#endif
#endif /* MEM_H_MODULE */
-
-/* ******************************************************************
- Error codes list
- Copyright (C) 2016, Yann Collet
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- 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
- OWNER 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 :
- - Homepage : http://www.zstd.net
-****************************************************************** */
-#ifndef ERROR_PUBLIC_H_MODULE
-#define ERROR_PUBLIC_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-
-/* ****************************************
-* error codes list
-******************************************/
-typedef enum {
- ZSTDv07_error_no_error,
- ZSTDv07_error_GENERIC,
- ZSTDv07_error_prefix_unknown,
- ZSTDv07_error_frameParameter_unsupported,
- ZSTDv07_error_frameParameter_unsupportedBy32bits,
- ZSTDv07_error_compressionParameter_unsupported,
- ZSTDv07_error_init_missing,
- ZSTDv07_error_memory_allocation,
- ZSTDv07_error_stage_wrong,
- ZSTDv07_error_dstSize_tooSmall,
- ZSTDv07_error_srcSize_wrong,
- ZSTDv07_error_corruption_detected,
- ZSTDv07_error_checksum_wrong,
- ZSTDv07_error_tableLog_tooLarge,
- ZSTDv07_error_maxSymbolValue_tooLarge,
- ZSTDv07_error_maxSymbolValue_tooSmall,
- ZSTDv07_error_dictionary_corrupted,
- ZSTDv07_error_dictionary_wrong,
- ZSTDv07_error_maxCode
-} ZSTDv07_ErrorCode;
-
-/*! ZSTDv07_getErrorCode() :
- convert a `size_t` function result into a `ZSTDv07_ErrorCode` enum type,
- which can be used to compare directly with enum list published into "error_public.h" */
-ZSTDv07_ErrorCode ZSTDv07_getErrorCode(size_t functionResult);
-const char* ZSTDv07_getErrorString(ZSTDv07_ErrorCode code);
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_PUBLIC_H_MODULE */
-/* ******************************************************************
- Error codes and messages
- Copyright (C) 2013-2016, Yann Collet
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- 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
- OWNER 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 :
- - Homepage : http://www.zstd.net
-****************************************************************** */
-/* Note : this module is expected to remain private, do not expose it */
-
-#ifndef ERROR_H_MODULE
-#define ERROR_H_MODULE
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-
-
-/* ****************************************
-* Compiler-specific
-******************************************/
-#if defined(__GNUC__)
-# define ERR_STATIC static __attribute__((unused))
-#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-# define ERR_STATIC static inline
-#elif defined(_MSC_VER)
-# define ERR_STATIC static __inline
-#else
-# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
-#endif
-
-
-/*-****************************************
-* Customization (error_public.h)
-******************************************/
-typedef ZSTDv07_ErrorCode ERR_enum;
-#define PREFIX(name) ZSTDv07_error_##name
-
-
-/*-****************************************
-* Error codes handling
-******************************************/
-#ifdef ERROR
-# undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
-#endif
-#define ERROR(name) ((size_t)-PREFIX(name))
-
-ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
-
-ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
-
-
-/*-****************************************
-* Error Strings
-******************************************/
-
-ERR_STATIC const char* ERR_getErrorString(ERR_enum code)
-{
- static const char* notErrorCode = "Unspecified error code";
- switch( code )
- {
- case PREFIX(no_error): return "No error detected";
- case PREFIX(GENERIC): return "Error (generic)";
- case PREFIX(prefix_unknown): return "Unknown frame descriptor";
- case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
- case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode";
- case PREFIX(compressionParameter_unsupported): return "Compression parameter is out of bound";
- case PREFIX(init_missing): return "Context should be init first";
- case PREFIX(memory_allocation): return "Allocation error : not enough memory";
- case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
- case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
- case PREFIX(srcSize_wrong): return "Src size incorrect";
- case PREFIX(corruption_detected): return "Corrupted block detected";
- case PREFIX(checksum_wrong): return "Restored data doesn't match checksum";
- case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
- case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
- case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
- case PREFIX(dictionary_corrupted): return "Dictionary is corrupted";
- case PREFIX(dictionary_wrong): return "Dictionary mismatch";
- case PREFIX(maxCode):
- default: return notErrorCode;
- }
-}
-
-ERR_STATIC const char* ERR_getErrorName(size_t code)
-{
- return ERR_getErrorString(ERR_getErrorCode(code));
-}
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* ERROR_H_MODULE */
/* ******************************************************************
bitstream
Part of FSE library
@@ -845,8 +650,8 @@ MEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, U32 nbBits)
if status == unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
MEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD)
{
- if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should not happen => corruption detected */
- return BITv07_DStream_overflow;
+ if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should not happen => corruption detected */
+ return BITv07_DStream_overflow;
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
bitD->ptr -= bitD->bitsConsumed >> 3;
@@ -1680,17 +1485,18 @@ size_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
#else
-# ifdef __GNUC__
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
# else
-# define FORCE_INLINE static inline
-# endif
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
#endif
-
-
/* **************************************************************
* Error Management
****************************************************************/
@@ -2006,14 +1812,7 @@ size_t FSEv07_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#else
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
@@ -2888,13 +2687,6 @@ unsigned ZSTDv07_isError(size_t code) { return ERR_isError(code); }
* provides error code string from function result (useful for debugging) */
const char* ZSTDv07_getErrorName(size_t code) { return ERR_getErrorName(code); }
-/*! ZSTDv07_getError() :
-* convert a `size_t` function result into a proper ZSTDv07_errorCode enum */
-ZSTDv07_ErrorCode ZSTDv07_getErrorCode(size_t code) { return ERR_getErrorCode(code); }
-
-/*! ZSTDv07_getErrorString() :
-* provides error code string from enum */
-const char* ZSTDv07_getErrorString(ZSTDv07_ErrorCode code) { return ERR_getErrorName(code); }
/* **************************************************************
@@ -3176,17 +2968,10 @@ static const ZSTDv07_customMem defaultCustomMem = { ZSTDv07_defaultAllocFunction
* Compiler specifics
*********************************************************/
#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
# include /* For Visual 2005 */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
-#else
-# ifdef __GNUC__
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
#endif
@@ -4046,7 +3831,7 @@ size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx,
/** ZSTDv07_insertBlock() :
insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
-ZSTDLIB_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize)
+ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize)
{
ZSTDv07_checkContinuity(dctx, blockStart);
dctx->previousDstEnd = (const char*)blockStart + blockSize;
@@ -4448,7 +4233,7 @@ size_t ZSTDv07_freeDDict(ZSTDv07_DDict* ddict)
/*! ZSTDv07_decompress_usingDDict() :
* Decompression using a pre-digested Dictionary
* Use dictionary without significant overhead. */
-ZSTDLIB_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,
+ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTDv07_DDict* ddict)
@@ -4535,7 +4320,7 @@ struct ZBUFFv07_DCtx_s {
ZSTDv07_customMem customMem;
}; /* typedef'd to ZBUFFv07_DCtx within "zstd_buffered.h" */
-ZSTDLIB_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem);
+ZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem);
ZBUFFv07_DCtx* ZBUFFv07_createDCtx(void)
{
diff --git a/lib/legacy/zstd_v07.h b/lib/legacy/zstd_v07.h
index d1fbc0830..30725dcf7 100644
--- a/lib/legacy/zstd_v07.h
+++ b/lib/legacy/zstd_v07.h
@@ -24,13 +24,12 @@ extern "C" {
* Enable exporting of functions when building a Windows DLL
*/
#if defined(_WIN32) && defined(ZSTDv07_DLL_EXPORT) && (ZSTDv07_DLL_EXPORT==1)
-# define ZSTDLIB_API __declspec(dllexport)
+# define ZSTDLIBv07_API __declspec(dllexport)
#else
-# define ZSTDLIB_API
+# define ZSTDLIBv07_API
#endif
-
/* *************************************
* Simple API
***************************************/
@@ -46,12 +45,12 @@ unsigned long long ZSTDv07_getDecompressedSize(const void* src, size_t srcSize);
`dstCapacity` must be equal or larger than originalSize.
@return : the number of bytes decompressed into `dst` (<= `dstCapacity`),
or an errorCode if it fails (which can be tested using ZSTDv07_isError()) */
-ZSTDLIB_API size_t ZSTDv07_decompress( void* dst, size_t dstCapacity,
- const void* src, size_t compressedSize);
+ZSTDLIBv07_API size_t ZSTDv07_decompress( void* dst, size_t dstCapacity,
+ const void* src, size_t compressedSize);
/*====== Helper functions ======*/
-ZSTDLIB_API unsigned ZSTDv07_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
-ZSTDLIB_API const char* ZSTDv07_getErrorName(size_t code); /*!< provides readable string from an error code */
+ZSTDLIBv07_API unsigned ZSTDv07_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
+ZSTDLIBv07_API const char* ZSTDv07_getErrorName(size_t code); /*!< provides readable string from an error code */
/*-*************************************
@@ -59,12 +58,12 @@ ZSTDLIB_API const char* ZSTDv07_getErrorName(size_t code); /*!< provides rea
***************************************/
/** Decompression context */
typedef struct ZSTDv07_DCtx_s ZSTDv07_DCtx;
-ZSTDLIB_API ZSTDv07_DCtx* ZSTDv07_createDCtx(void);
-ZSTDLIB_API size_t ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx); /*!< @return : errorCode */
+ZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx(void);
+ZSTDLIBv07_API size_t ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx); /*!< @return : errorCode */
/** ZSTDv07_decompressDCtx() :
* Same as ZSTDv07_decompress(), requires an allocated ZSTDv07_DCtx (see ZSTDv07_createDCtx()) */
-ZSTDLIB_API size_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIBv07_API size_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
/*-************************
@@ -74,10 +73,10 @@ ZSTDLIB_API size_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* ctx, void* dst, size_t d
* Decompression using a pre-defined Dictionary content (see dictBuilder).
* Dictionary must be identical to the one used during compression.
* Note : This function load the dictionary, resulting in a significant startup time */
-ZSTDLIB_API size_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const void* dict,size_t dictSize);
+ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize);
/*-**************************
@@ -87,16 +86,16 @@ ZSTDLIB_API size_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,
* Create a digested dictionary, ready to start decompression operation without startup delay.
* `dict` can be released after creation */
typedef struct ZSTDv07_DDict_s ZSTDv07_DDict;
-ZSTDLIB_API ZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZSTDv07_freeDDict(ZSTDv07_DDict* ddict);
+ZSTDLIBv07_API ZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize);
+ZSTDLIBv07_API size_t ZSTDv07_freeDDict(ZSTDv07_DDict* ddict);
/*! ZSTDv07_decompress_usingDDict() :
* Decompression using a pre-digested Dictionary
* Faster startup than ZSTDv07_decompress_usingDict(), recommended when same dictionary is used multiple times. */
-ZSTDLIB_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTDv07_DDict* ddict);
+ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTDv07_DDict* ddict);
typedef struct {
unsigned long long frameContentSize;
@@ -105,7 +104,7 @@ typedef struct {
unsigned checksumFlag;
} ZSTDv07_frameParams;
-ZSTDLIB_API size_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input */
+ZSTDLIBv07_API size_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input */
@@ -114,13 +113,13 @@ ZSTDLIB_API size_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const
* Streaming functions
***************************************/
typedef struct ZBUFFv07_DCtx_s ZBUFFv07_DCtx;
-ZSTDLIB_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx(void);
-ZSTDLIB_API size_t ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* dctx);
+ZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx(void);
+ZSTDLIBv07_API size_t ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* dctx);
-ZSTDLIB_API size_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* dctx);
-ZSTDLIB_API size_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* dctx, const void* dict, size_t dictSize);
+ZSTDLIBv07_API size_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* dctx);
+ZSTDLIBv07_API size_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* dctx, const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* dctx,
+ZSTDLIBv07_API size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* dctx,
void* dst, size_t* dstCapacityPtr,
const void* src, size_t* srcSizePtr);
@@ -152,13 +151,13 @@ ZSTDLIB_API size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* dctx,
/* *************************************
* Tool functions
***************************************/
-ZSTDLIB_API unsigned ZBUFFv07_isError(size_t errorCode);
-ZSTDLIB_API const char* ZBUFFv07_getErrorName(size_t errorCode);
+ZSTDLIBv07_API unsigned ZBUFFv07_isError(size_t errorCode);
+ZSTDLIBv07_API const char* ZBUFFv07_getErrorName(size_t errorCode);
/** Functions below provide recommended buffer sizes for Compression or Decompression operations.
* These sizes are just hints, they tend to offer better latency */
-ZSTDLIB_API size_t ZBUFFv07_recommendedDInSize(void);
-ZSTDLIB_API size_t ZBUFFv07_recommendedDOutSize(void);
+ZSTDLIBv07_API size_t ZBUFFv07_recommendedDInSize(void);
+ZSTDLIBv07_API size_t ZBUFFv07_recommendedDOutSize(void);
/*-*************************************
diff --git a/lib/libzstd.pc.in b/lib/libzstd.pc.in
index 28afc3add..9399363dd 100644
--- a/lib/libzstd.pc.in
+++ b/lib/libzstd.pc.in
@@ -8,7 +8,7 @@ includedir=@INCLUDEDIR@
Name: zstd
Description: lossless compression algorithm library
-URL: https://github.com/Cyan4973/zstd
+URL: https://github.com/facebook/zstd
Version: @VERSION@
Libs: -L@LIBDIR@ -lzstd
Cflags: -I@INCLUDEDIR@
diff --git a/lib/zstd.h b/lib/zstd.h
index d768ded35..dd3f5df4c 100644
--- a/lib/zstd.h
+++ b/lib/zstd.h
@@ -32,7 +32,7 @@ extern "C" {
/*======= Version =======*/
#define ZSTD_VERSION_MAJOR 1
-#define ZSTD_VERSION_MINOR 0
+#define ZSTD_VERSION_MINOR 1
#define ZSTD_VERSION_RELEASE 0
#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
@@ -48,40 +48,41 @@ ZSTDLIB_API unsigned ZSTD_versionNumber (void);
* Simple API
***************************************/
/*! ZSTD_compress() :
- Compresses `src` buffer into already allocated `dst`.
+ Compresses `src` content as a single zstd compressed frame into already allocated `dst`.
Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
- @return : the number of bytes written into `dst` (<= `dstCapacity),
+ @return : compressed size written into `dst` (<= `dstCapacity),
or an error code if it fails (which can be tested using ZSTD_isError()) */
ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel);
-/*! ZSTD_getDecompressedSize() :
-* @return : decompressed size as a 64-bits value _if known_, 0 otherwise.
-* note 1 : decompressed size can be very large (64-bits value),
-* potentially larger than what local system can handle as a single memory segment.
-* In which case, it's necessary to use streaming mode to decompress data.
-* note 2 : decompressed size is an optional field, that may not be present.
-* When `return==0`, data to decompress can have any size.
-* In which case, it's necessary to use streaming mode to decompress data.
-* Optionally, application may rely on its own implied limits.
-* (For example, application data could be necessarily cut into blocks <= 16 KB).
-* note 3 : decompressed size could be wrong or intentionally modified !
-* Always ensure result fits within application's authorized limits !
-* Each application can set its own limits.
-* note 4 : when `return==0`, if precise failure cause is needed, use ZSTD_getFrameParams() to know more. */
-ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
-
/*! ZSTD_decompress() :
- `compressedSize` : must be the _exact_ size of compressed input, otherwise decompression will fail.
- `dstCapacity` must be equal or larger than originalSize (see ZSTD_getDecompressedSize() ).
- If originalSize is unknown, and if there is no implied application-specific limitations,
- it's preferable to use streaming mode to decompress data.
+ `compressedSize` : must be the _exact_ size of a single compressed frame.
+ `dstCapacity` is an upper bound of originalSize.
+ If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data.
@return : the number of bytes decompressed into `dst` (<= `dstCapacity`),
or an errorCode if it fails (which can be tested using ZSTD_isError()) */
ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
const void* src, size_t compressedSize);
+/*! ZSTD_getDecompressedSize() :
+* 'src' is the start of a zstd compressed frame.
+* @return : content size to be decompressed, as a 64-bits value _if known_, 0 otherwise.
+* note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode.
+* When `return==0`, data to decompress could be any size.
+* In which case, it's necessary to use streaming mode to decompress data.
+* Optionally, application can still use ZSTD_decompress() while relying on implied limits.
+* (For example, data may be necessarily cut into blocks <= 16 KB).
+* note 2 : decompressed size is always present when compression is done with ZSTD_compress()
+* note 3 : decompressed size can be very large (64-bits value),
+* potentially larger than what local system can handle as a single memory segment.
+* In which case, it's necessary to use streaming mode to decompress data.
+* note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified.
+* Always ensure result fits within application's authorized limits.
+* Each application can set its own limits.
+* note 5 : when `return==0`, if precise failure cause is needed, use ZSTD_getFrameParams() to know more. */
+ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
+
/*====== Helper functions ======*/
ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
@@ -200,7 +201,7 @@ typedef struct ZSTD_outBuffer_s {
* Use ZSTD_initCStream_usingDict() for a compression which requires a dictionary.
*
* Use ZSTD_compressStream() repetitively to consume input stream.
-* The function will automatically update both `pos`.
+* The function will automatically update both `pos` fields.
* Note that it may not consume the entire input, in which case `pos < size`,
* and it's up to the caller to present again remaining data.
* @return : a size hint, preferred nb of bytes to use as input for next function call
@@ -229,7 +230,7 @@ ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */
-ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer */
+ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */
ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
@@ -248,16 +249,17 @@ ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
*
* Use ZSTD_initDStream() to start a new decompression operation,
* or ZSTD_initDStream_usingDict() if decompression requires a dictionary.
+* @return : recommended first input size
*
* Use ZSTD_decompressStream() repetitively to consume your input.
-* The function will update both `pos`.
-* Note that it may not consume the entire input (pos < size),
-* in which case it's up to the caller to present remaining input again.
+* The function will update both `pos` fields.
+* If `input.pos < input.size`, some input has not been consumed.
+* It's up to the caller to present again remaining data.
+* If `output.pos < output.size`, decoder has flushed everything it could.
* @return : 0 when a frame is completely decoded and fully flushed,
-* 1 when there is still some data left within internal buffer to flush,
-* >1 when more data is expected, with value being a suggested next input size (it's just a hint, which helps latency, any size is accepted),
-* or an error code, which can be tested using ZSTD_isError().
-*
+* an error code, which can be tested using ZSTD_isError(),
+* any other value > 0, which means there is still some work to do to complete the frame.
+* The return value is a suggested next input size (just an hint, to help latency).
* *******************************************************************************/
typedef struct ZSTD_DStream_s ZSTD_DStream;
@@ -265,7 +267,7 @@ ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */
-ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer */
+ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
@@ -288,21 +290,22 @@ ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* outp
#define ZSTD_WINDOWLOG_MAX_32 25
#define ZSTD_WINDOWLOG_MAX_64 27
#define ZSTD_WINDOWLOG_MAX ((U32)(MEM_32bits() ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))
-#define ZSTD_WINDOWLOG_MIN 18
-#define ZSTD_CHAINLOG_MAX (ZSTD_WINDOWLOG_MAX+1)
-#define ZSTD_CHAINLOG_MIN 4
+#define ZSTD_WINDOWLOG_MIN 10
#define ZSTD_HASHLOG_MAX ZSTD_WINDOWLOG_MAX
-#define ZSTD_HASHLOG_MIN 12
+#define ZSTD_HASHLOG_MIN 6
+#define ZSTD_CHAINLOG_MAX (ZSTD_WINDOWLOG_MAX+1)
+#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN
#define ZSTD_HASHLOG3_MAX 17
#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
#define ZSTD_SEARCHLOG_MIN 1
-#define ZSTD_SEARCHLENGTH_MAX 7
-#define ZSTD_SEARCHLENGTH_MIN 3
+#define ZSTD_SEARCHLENGTH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */
+#define ZSTD_SEARCHLENGTH_MIN 3 /* only for ZSTD_btopt, other strategies are limited to 4 */
#define ZSTD_TARGETLENGTH_MIN 4
#define ZSTD_TARGETLENGTH_MAX 999
#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* for static allocation */
-static const size_t ZSTD_frameHeaderSize_min = 5;
+static const size_t ZSTD_frameHeaderSize_prefix = 5;
+static const size_t ZSTD_frameHeaderSize_min = 6;
static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX;
static const size_t ZSTD_skippableHeaderSize = 8; /* magic number + skippable frame length */
@@ -349,14 +352,18 @@ ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams);
* Create a ZSTD compression context using external alloc and free functions */
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
+/*! ZSTD_sizeofCCtx() :
+ * Gives the amount of memory used by a given ZSTD_CCtx */
+ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
+
/*! ZSTD_createCDict_advanced() :
* 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,
ZSTD_parameters params, ZSTD_customMem customMem);
-/*! ZSTD_sizeofCCtx() :
- * Gives the amount of memory used by a given ZSTD_CCtx */
-ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
+/*! ZSTD_sizeof_CDict() :
+ * Gives the amount of memory used by a given ZSTD_sizeof_CDict */
+ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
/*! ZSTD_getParams() :
* same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of a `ZSTD_compressionParameters`.
@@ -396,10 +403,14 @@ ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
* Create a ZSTD decompression context using external alloc and free functions */
ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
-/*! ZSTD_sizeofDCtx() :
+/*! ZSTD_sizeof_DCtx() :
* Gives the amount of memory used by a given ZSTD_DCtx */
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
+/*! ZSTD_sizeof_DDict() :
+ * Gives the amount of memory used by a given ZSTD_DDict */
+ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
+
/* ******************************************************************
* Advanced Streaming functions
@@ -410,7 +421,8 @@ ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel);
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
- ZSTD_parameters params, unsigned long long pledgedSrcSize);
+ ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be zero == unknown */
+ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); /**< re-use compression parameters from previous init; saves dictionary loading */
ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
@@ -421,6 +433,7 @@ typedef enum { ZSTDdsp_maxWindowSize } ZSTD_DStreamParameter_e;
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_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue);
+ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */
ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
@@ -434,7 +447,7 @@ ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
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_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);
+ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, 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_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
diff --git a/programs/.gitignore b/programs/.gitignore
index 5875fc792..24f96cf4b 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -7,6 +7,7 @@ zstd-decompress
# Object files
*.o
*.ko
+default.profraw
# Executables
*.exe
diff --git a/programs/Makefile b/programs/Makefile
index fc634b60e..6e78d0ea9 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -57,6 +57,13 @@ endif
ifneq (,$(filter Windows%,$(OS)))
EXT =.exe
VOID = nul
+RES64_FILE = ..\build\VS2010\zstd\generate_res\zstd64.res
+RES32_FILE = ..\build\VS2010\zstd\generate_res\zstd32.res
+ifneq (,$(filter x86_64%,$(shell $(CC) -dumpmachine)))
+ RES_FILE = $(RES64_FILE)
+else
+ RES_FILE = $(RES32_FILE)
+endif
else
EXT =
VOID = /dev/null
@@ -78,11 +85,11 @@ $(ZSTDDECOMP32_O): $(ZSTDDIR)/decompress/zstd_decompress.c
zstd : $(ZSTDDECOMP_O) $(ZSTD_FILES) $(ZSTDLEGACY_FILES) $(ZDICT_FILES) \
zstdcli.c fileio.c bench.c datagen.c dibio.c
- $(CC) $(FLAGS) -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) $^ -o $@$(EXT)
+ $(CC) $(FLAGS) -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) $^ $(RES_FILE) -o $@$(EXT)
zstd32 : $(ZSTDDECOMP32_O) $(ZSTD_FILES) $(ZSTDLEGACY_FILES) $(ZDICT_FILES) \
zstdcli.c fileio.c bench.c datagen.c dibio.c
- $(CC) -m32 $(FLAGS) -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) $^ -o $@$(EXT)
+ $(CC) -m32 $(FLAGS) -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) $^ $(RES32_FILE) -o $@$(EXT)
zstd_nolegacy :
@@ -97,6 +104,7 @@ zstd-pgo : clean zstd
./zstd -b7i2 $(PROFILE_WITH)
./zstd -b5 $(PROFILE_WITH)
$(RM) zstd
+ $(RM) $(ZSTDDIR)/decompress/zstd_decompress.o
$(MAKE) zstd MOREFLAGS=-fprofile-use
zstd-frugal: $(ZSTDDECOMP_O) $(ZSTD_FILES) zstdcli.c fileio.c
@@ -116,16 +124,17 @@ zstd-small: clean
clean:
$(MAKE) -C ../lib clean
- @$(RM) ../lib/decompress/*.o
+ @$(RM) $(ZSTDDIR)/decompress/*.o $(ZSTDDIR)/decompress/zstd_decompress.gcda
@$(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
@echo Cleaning completed
#----------------------------------------------------------------------------------
#make install is validated only for Linux, OSX, kFreeBSD, Hurd and some BSD targets
#----------------------------------------------------------------------------------
-ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD DragonFly))
+ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD DragonFly NetBSD))
install: zstd
@echo Installing binaries
@install -d -m 755 $(DESTDIR)$(BINDIR)/ $(DESTDIR)$(MANDIR)/
@@ -141,9 +150,9 @@ install: zstd
uninstall:
$(RM) $(DESTDIR)$(BINDIR)/zstdcat
$(RM) $(DESTDIR)$(BINDIR)/unzstd
- [ -x $(DESTDIR)$(BINDIR)/zstd$(EXT) ] && $(RM) $(DESTDIR)$(BINDIR)/zstd$(EXT)
+ $(RM) $(DESTDIR)$(BINDIR)/zstd$(EXT)
$(RM) $(DESTDIR)$(MANDIR)/zstdcat.1
$(RM) $(DESTDIR)$(MANDIR)/unzstd.1
- [ -f $(DESTDIR)$(MANDIR)/zstd.1 ] && $(RM) $(DESTDIR)$(MANDIR)/zstd.1
+ $(RM) $(DESTDIR)$(MANDIR)/zstd.1
@echo zstd programs successfully uninstalled
endif
diff --git a/programs/bench.c b/programs/bench.c
index 3a290cc9a..c477b2682 100644
--- a/programs/bench.c
+++ b/programs/bench.c
@@ -15,7 +15,7 @@
#include /* malloc, free */
#include /* memset */
#include /* fprintf, fopen, ftello64 */
-#include /* clock_t, clock, CLOCKS_PER_SEC */
+#include /* clock_t, clock, CLOCKS_PER_SEC */
#include "mem.h"
#define ZSTD_STATIC_LINKING_ONLY
@@ -24,7 +24,6 @@
#include "xxhash.h"
-
/* *************************************
* Constants
***************************************/
diff --git a/programs/datagen.c b/programs/datagen.c
index 109b8e3d8..1af5a38a5 100644
--- a/programs/datagen.c
+++ b/programs/datagen.c
@@ -20,10 +20,9 @@
/*-************************************
* Dependencies
**************************************/
-#include /* malloc */
+#include /* malloc, free */
#include /* FILE, fwrite, fprintf */
#include /* memcpy */
-#include /* errno */
#include "mem.h" /* U32 */
@@ -176,7 +175,7 @@ void RDG_genStdout(unsigned long long size, double matchProba, double litProba,
BYTE ldt[LTSIZE]; /* literals distribution table */
/* init */
- if (buff==NULL) { fprintf(stderr, "datagen: error: %s \n", strerror(errno)); exit(1); }
+ if (buff==NULL) { perror("datagen"); exit(1); }
if (litProba<=0.0) litProba = matchProba / 4.5;
memset(ldt, '0', sizeof(ldt)); /* yes, character '0', this is intentional */
RDG_fillLiteralDistrib(ldt, litProba);
diff --git a/programs/datagen.h b/programs/datagen.h
index 55f9d8283..094056b69 100644
--- a/programs/datagen.h
+++ b/programs/datagen.h
@@ -6,7 +6,8 @@
* 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 DATAGEN_H
+#define DATAGEN_H
#include /* size_t */
@@ -22,3 +23,5 @@ void RDG_genBuffer(void* buffer, size_t size, double matchProba, double litProba
RDG_genStdout
Same as RDG_genBuffer, but generates data into stdout
*/
+
+#endif
diff --git a/programs/fileio.c b/programs/fileio.c
index b7b201e02..56f22fe75 100644
--- a/programs/fileio.c
+++ b/programs/fileio.c
@@ -20,7 +20,7 @@
***************************************/
#ifndef ZSTD_LEGACY_SUPPORT
/* LEGACY_SUPPORT :
- * decompressor can decode older formats (starting from Zstd 0.1+) */
+ * decompressor can decode older formats (starting from zstd 0.1+) */
# define ZSTD_LEGACY_SUPPORT 1
#endif
@@ -119,8 +119,6 @@ static clock_t g_time = 0;
***************************************/
static U32 g_overwrite = 0;
void FIO_overwriteMode(void) { g_overwrite=1; }
-static U32 g_maxWLog = 23;
-void FIO_setMaxWLog(unsigned maxWLog) { g_maxWLog = maxWLog; }
static U32 g_sparseFileSupport = 1; /* 0 : no sparse allowed; 1: auto (file yes, stdout no); 2: force sparse */
void FIO_setSparseWrite(unsigned sparse) { g_sparseFileSupport=sparse; }
static U32 g_dictIDFlag = 1;
@@ -167,7 +165,9 @@ static FILE* FIO_openSrcFile(const char* srcFileName)
return f;
}
-/* `dstFileName must` be non-NULL */
+/** FIO_openDstFile() :
+ * condition : `dstFileName` must be non-NULL.
+ * @result : FILE* to `dstFileName`, or NULL if it fails */
static FILE* FIO_openDstFile(const char* dstFileName)
{
FILE* f;
@@ -250,14 +250,12 @@ typedef struct {
size_t srcBufferSize;
void* dstBuffer;
size_t dstBufferSize;
- void* dictBuffer;
- size_t dictBufferSize;
ZSTD_CStream* cctx;
FILE* dstFile;
FILE* srcFile;
} cRess_t;
-static cRess_t FIO_createCResources(const char* dictFileName)
+static cRess_t FIO_createCResources(const char* dictFileName, int cLevel, U64 srcSize)
{
cRess_t ress;
memset(&ress, 0, sizeof(ress));
@@ -271,19 +269,27 @@ static cRess_t FIO_createCResources(const char* dictFileName)
if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(31, "zstd: allocation error : not enough memory");
/* dictionary */
- ress.dictBufferSize = FIO_loadFile(&(ress.dictBuffer), dictFileName);
+ { void* dictBuffer;
+ size_t const dictBuffSize = FIO_loadFile(&dictBuffer, dictFileName);
+ if (dictFileName && (dictBuffer==NULL)) EXM_THROW(32, "zstd: allocation error : can't create dictBuffer");
+ { ZSTD_parameters params = ZSTD_getParams(cLevel, srcSize, dictBuffSize);
+ params.fParams.contentSizeFlag = 1;
+ params.fParams.checksumFlag = g_checksumFlag;
+ params.fParams.noDictIDFlag = !g_dictIDFlag;
+ { 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));
+ } }
+ free(dictBuffer);
+ }
return ress;
}
static void FIO_freeCResources(cRess_t ress)
{
- size_t errorCode;
free(ress.srcBuffer);
free(ress.dstBuffer);
- free(ress.dictBuffer);
- errorCode = ZSTD_freeCStream(ress.cctx);
- if (ZSTD_isError(errorCode)) EXM_THROW(38, "zstd: error : can't release ZSTD_CStream : %s", ZSTD_getErrorName(errorCode));
+ ZSTD_freeCStream(ress.cctx); /* never fails */
}
@@ -293,8 +299,7 @@ static void FIO_freeCResources(cRess_t ress)
* 1 : missing or pb opening srcFileName
*/
static int FIO_compressFilename_internal(cRess_t ress,
- const char* dstFileName, const char* srcFileName,
- int cLevel)
+ const char* dstFileName, const char* srcFileName)
{
FILE* const srcFile = ress.srcFile;
FILE* const dstFile = ress.dstFile;
@@ -303,17 +308,9 @@ static int FIO_compressFilename_internal(cRess_t ress,
U64 const fileSize = UTIL_getFileSize(srcFileName);
/* init */
- { ZSTD_parameters params = ZSTD_getParams(cLevel, fileSize, ress.dictBufferSize);
- params.fParams.contentSizeFlag = 1;
- params.fParams.checksumFlag = g_checksumFlag;
- params.fParams.noDictIDFlag = !g_dictIDFlag;
- if ((g_maxWLog) && (params.cParams.windowLog > g_maxWLog)) {
- params.cParams.windowLog = g_maxWLog;
- params.cParams = ZSTD_adjustCParams(params.cParams, fileSize, ress.dictBufferSize);
- }
- { size_t const errorCode = ZSTD_initCStream_advanced(ress.cctx, ress.dictBuffer, ress.dictBufferSize, params, fileSize);
- if (ZSTD_isError(errorCode)) EXM_THROW(21, "Error initializing compression : %s", ZSTD_getErrorName(errorCode));
- } }
+ { size_t const resetError = ZSTD_resetCStream(ress.cctx, fileSize);
+ if (ZSTD_isError(resetError)) EXM_THROW(21, "Error initializing compression : %s", ZSTD_getErrorName(resetError));
+ }
/* Main compression loop */
while (1) {
@@ -367,8 +364,7 @@ static int FIO_compressFilename_internal(cRess_t ress,
* 1 : missing or pb opening srcFileName
*/
static int FIO_compressFilename_srcFile(cRess_t ress,
- const char* dstFileName, const char* srcFileName,
- int cLevel)
+ const char* dstFileName, const char* srcFileName)
{
int result;
@@ -380,10 +376,10 @@ static int FIO_compressFilename_srcFile(cRess_t ress,
ress.srcFile = FIO_openSrcFile(srcFileName);
if (!ress.srcFile) return 1; /* srcFile could not be opened */
- result = FIO_compressFilename_internal(ress, dstFileName, srcFileName, cLevel);
+ result = FIO_compressFilename_internal(ress, dstFileName, srcFileName);
fclose(ress.srcFile);
- if ((g_removeSrcFile) && (!result)) { if (remove(srcFileName)) EXM_THROW(1, "zstd: %s: %s", srcFileName, strerror(errno)); }
+ if (g_removeSrcFile && !result) { if (remove(srcFileName)) EXM_THROW(1, "zstd: %s: %s", srcFileName, strerror(errno)); } /* remove source file : --rm */
return result;
}
@@ -393,17 +389,16 @@ static int FIO_compressFilename_srcFile(cRess_t ress,
* 1 : pb
*/
static int FIO_compressFilename_dstFile(cRess_t ress,
- const char* dstFileName, const char* srcFileName,
- int cLevel)
+ const char* dstFileName, const char* srcFileName)
{
int result;
ress.dstFile = FIO_openDstFile(dstFileName);
- if (ress.dstFile==0) return 1;
+ if (ress.dstFile==NULL) return 1; /* could not open dstFileName */
- result = FIO_compressFilename_srcFile(ress, dstFileName, srcFileName, cLevel);
+ result = FIO_compressFilename_srcFile(ress, dstFileName, srcFileName);
- if (fclose(ress.dstFile)) { DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno)); result=1; }
+ if (fclose(ress.dstFile)) { DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno)); result=1; } /* error closing dstFile */
if (result!=0) { if (remove(dstFileName)) EXM_THROW(1, "zstd: %s: %s", dstFileName, strerror(errno)); } /* remove operation artefact */
return result;
}
@@ -413,9 +408,10 @@ int FIO_compressFilename(const char* dstFileName, const char* srcFileName,
const char* dictFileName, int compressionLevel)
{
clock_t const start = clock();
+ U64 const srcSize = UTIL_getFileSize(srcFileName);
- cRess_t const ress = FIO_createCResources(dictFileName);
- int const result = FIO_compressFilename_dstFile(ress, dstFileName, srcFileName, compressionLevel);
+ cRess_t const ress = FIO_createCResources(dictFileName, compressionLevel, srcSize);
+ int const result = FIO_compressFilename_dstFile(ress, dstFileName, srcFileName);
double const seconds = (double)(clock() - start) / CLOCKS_PER_SEC;
DISPLAYLEVEL(4, "Completed in %.2f sec \n", seconds);
@@ -433,7 +429,8 @@ int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFile
size_t dfnSize = FNSPACE;
char* dstFileName = (char*)malloc(FNSPACE);
size_t const suffixSize = suffix ? strlen(suffix) : 0;
- cRess_t ress = FIO_createCResources(dictFileName);
+ U64 const srcSize = (nbFiles != 1) ? 0 : UTIL_getFileSize(inFileNamesTable[0]) ;
+ cRess_t ress = FIO_createCResources(dictFileName, compressionLevel, srcSize);
/* init */
if (dstFileName==NULL) EXM_THROW(27, "FIO_compressMultipleFilenames : allocation error for dstFileName");
@@ -445,8 +442,7 @@ int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFile
ress.dstFile = stdout;
SET_BINARY_MODE(stdout);
for (u=0; u= alreadyLoaded */
@@ -613,22 +610,22 @@ unsigned long long FIO_decompressFrame(dRess_t ress,
while (1) {
ZSTD_inBuffer inBuff = { ress.srcBuffer, readSize, 0 };
ZSTD_outBuffer outBuff= { ress.dstBuffer, ress.dstBufferSize, 0 };
- size_t const toRead = ZSTD_decompressStream(ress.dctx, &outBuff, &inBuff );
- if (ZSTD_isError(toRead)) EXM_THROW(36, "Decoding error : %s", ZSTD_getErrorName(toRead));
+ size_t const readSizeHint = ZSTD_decompressStream(ress.dctx, &outBuff, &inBuff );
+ if (ZSTD_isError(readSizeHint)) EXM_THROW(36, "Decoding error : %s", ZSTD_getErrorName(readSizeHint));
/* Write block */
storedSkips = FIO_fwriteSparse(foutput, ress.dstBuffer, outBuff.pos, storedSkips);
frameSize += outBuff.pos;
DISPLAYUPDATE(2, "\rDecoded : %u MB... ", (U32)(frameSize>>20) );
- if (toRead == 0) break; /* end of frame */
+ if (readSizeHint == 0) break; /* end of frame */
if (inBuff.size != inBuff.pos) EXM_THROW(37, "Decoding error : should consume entire input");
/* Fill input buffer */
- if (toRead > ress.srcBufferSize) EXM_THROW(38, "too large block");
- readSize = fread(ress.srcBuffer, 1, toRead, finput);
- if (readSize == 0) EXM_THROW(39, "Read error : premature end");
- }
+ { size_t const toRead = MIN(readSizeHint, ress.srcBufferSize); /* support large skippable frames */
+ readSize = fread(ress.srcBuffer, 1, toRead, finput);
+ if (readSize < toRead) EXM_THROW(39, "Read error : premature end");
+ } }
FIO_fwriteSparseEnd(foutput, storedSkips);
@@ -686,7 +683,7 @@ static int FIO_decompressSrcFile(dRess_t ress, const char* srcFileName)
if (readSomething==0) { DISPLAY("zstd: %s: unexpected end of file \n", srcFileName); fclose(srcFile); return 1; } /* srcFileName is empty */
break; /* no more input */
}
- readSomething = 1;
+ readSomething = 1; /* there is at least >= 4 bytes in srcFile */
if (sizeCheck != toRead) { DISPLAY("zstd: %s: unknown header \n", srcFileName); fclose(srcFile); return 1; } /* srcFileName is empty */
{ U32 const magic = MEM_readLE32(ress.srcBuffer);
if (((magic & 0xFFFFFFF0U) != ZSTD_MAGIC_SKIPPABLE_START) & (magic != ZSTD_MAGICNUMBER)
@@ -732,7 +729,10 @@ static int FIO_decompressDstFile(dRess_t ress,
result = FIO_decompressSrcFile(ress, srcFileName);
if (fclose(ress.dstFile)) EXM_THROW(38, "Write error : cannot properly close %s", dstFileName);
- if (result != 0) if (remove(dstFileName)) result=1; /* don't do anything if remove fails */
+ if ( (result != 0)
+ && strcmp(dstFileName, nulmark) /* special case : don't remove() /dev/null (#316) */
+ && remove(dstFileName) )
+ result=1; /* don't do anything special if remove() fails */
return result;
}
diff --git a/programs/fileio.h b/programs/fileio.h
index 66805f79c..1e89aec27 100644
--- a/programs/fileio.h
+++ b/programs/fileio.h
@@ -8,7 +8,8 @@
*/
-#pragma once
+#ifndef FILEIO_H_23981798732
+#define FILEIO_H_23981798732
#if defined (__cplusplus)
extern "C" {
@@ -32,7 +33,6 @@ extern "C" {
***************************************/
void FIO_overwriteMode(void);
void FIO_setNotificationLevel(unsigned level);
-void FIO_setMaxWLog(unsigned maxWLog); /**< if `maxWLog` == 0, no max enforced */
void FIO_setSparseWrite(unsigned sparse); /**< 0: no sparse; 1: disable on stdout; 2: always enabled */
void FIO_setDictIDFlag(unsigned dictIDFlag);
void FIO_setChecksumFlag(unsigned checksumFlag);
@@ -70,3 +70,5 @@ int FIO_decompressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles
#if defined (__cplusplus)
}
#endif
+
+#endif /* FILEIO_H_23981798732 */
diff --git a/programs/util.h b/programs/util.h
index ee130f4bd..aabebe961 100644
--- a/programs/util.h
+++ b/programs/util.h
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * 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
@@ -31,12 +31,12 @@ extern "C" {
/* 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__) /* Sun Solaris 32-bits requires specific definitions */
-# define _LARGEFILE_SOURCE /* fseeko, ftello */
-# else
-# define _LARGEFILE64_SOURCE /* off64_t, fseeko64, ftello64 */
+#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
@@ -199,48 +199,67 @@ UTIL_STATIC U32 UTIL_isDirectory(const char* infilename)
return 0;
}
+/*
+ * A modified version of realloc().
+ * If UTIL_realloc() fails the original block is freed.
+*/
+UTIL_STATIC void *UTIL_realloc(void *ptr, size_t size)
+{
+ void *newptr = realloc(ptr, size);
+ if (newptr) return newptr;
+ free(ptr);
+ return NULL;
+}
+
#ifdef _WIN32
# define UTIL_HAS_CREATEFILELIST
UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd)
{
- char path[MAX_PATH];
- int pathLength, nbFiles = 0;
+ char* path;
+ int dirLength, fnameLength, pathLength, nbFiles = 0;
WIN32_FIND_DATA cFile;
HANDLE hFile;
- pathLength = snprintf(path, MAX_PATH, "%s\\*", dirName);
- if (pathLength < 0 || pathLength >= MAX_PATH) {
- fprintf(stderr, "Path length has got too long.\n");
- return 0;
- }
+ dirLength = (int)strlen(dirName);
+ path = (char*) malloc(dirLength + 3);
+ if (!path) return 0;
+
+ memcpy(path, dirName, dirLength);
+ path[dirLength] = '\\';
+ path[dirLength+1] = '*';
+ path[dirLength+2] = 0;
hFile=FindFirstFile(path, &cFile);
if (hFile == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Cannot open directory '%s'\n", dirName);
return 0;
}
+ free(path);
do {
- pathLength = snprintf(path, MAX_PATH, "%s\\%s", dirName, cFile.cFileName);
- if (pathLength < 0 || pathLength >= MAX_PATH) {
- fprintf(stderr, "Path length has got too long.\n");
- continue;
- }
+ fnameLength = (int)strlen(cFile.cFileName);
+ path = (char*) malloc(dirLength + fnameLength + 2);
+ if (!path) { FindClose(hFile); return 0; }
+ memcpy(path, dirName, dirLength);
+ path[dirLength] = '\\';
+ memcpy(path+dirLength+1, cFile.cFileName, fnameLength);
+ pathLength = dirLength+1+fnameLength;
+ path[pathLength] = 0;
if (cFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (strcmp (cFile.cFileName, "..") == 0 ||
strcmp (cFile.cFileName, ".") == 0) continue;
nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd); /* Recursively call "UTIL_prepareFileList" with the new path. */
- if (*bufStart == NULL) { FindClose(hFile); return 0; }
+ if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }
}
else if ((cFile.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || (cFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) || (cFile.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)) {
if (*bufStart + *pos + pathLength >= *bufEnd) {
ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;
- *bufStart = (char*)realloc(*bufStart, newListSize);
+ *bufStart = (char*)UTIL_realloc(*bufStart, newListSize);
*bufEnd = *bufStart + newListSize;
- if (*bufStart == NULL) { FindClose(hFile); return 0; }
+ if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }
}
if (*bufStart + *pos + pathLength < *bufEnd) {
strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos));
@@ -248,48 +267,54 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
nbFiles++;
}
}
+ free(path);
} while (FindNextFile(hFile, &cFile));
FindClose(hFile);
return nbFiles;
}
-#elif (defined(__unix__) || defined(__unix) || defined(__midipix__) || (defined(__APPLE__) && defined(__MACH__))) && defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) /* snprintf, opendir */
+#elif (defined(__APPLE__) && defined(__MACH__)) || \
+ ((defined(__unix__) || defined(__unix) || defined(__midipix__)) && defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) /* snprintf, opendir */
# define UTIL_HAS_CREATEFILELIST
# include /* opendir, readdir */
-# include /* PATH_MAX */
# include
UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd)
{
DIR *dir;
struct dirent *entry;
- char path[PATH_MAX];
- int pathLength, nbFiles = 0;
+ char* path;
+ int dirLength, fnameLength, pathLength, nbFiles = 0;
if (!(dir = opendir(dirName))) {
fprintf(stderr, "Cannot open directory '%s': %s\n", dirName, strerror(errno));
return 0;
}
+ dirLength = (int)strlen(dirName);
errno = 0;
while ((entry = readdir(dir)) != NULL) {
if (strcmp (entry->d_name, "..") == 0 ||
strcmp (entry->d_name, ".") == 0) continue;
- pathLength = snprintf(path, PATH_MAX, "%s/%s", dirName, entry->d_name);
- if (pathLength < 0 || pathLength >= PATH_MAX) {
- fprintf(stderr, "Path length has got too long.\n");
- continue;
- }
+ fnameLength = (int)strlen(entry->d_name);
+ path = (char*) malloc(dirLength + fnameLength + 2);
+ if (!path) { closedir(dir); return 0; }
+ memcpy(path, dirName, dirLength);
+ path[dirLength] = '/';
+ memcpy(path+dirLength+1, entry->d_name, fnameLength);
+ pathLength = dirLength+1+fnameLength;
+ path[pathLength] = 0;
+
if (UTIL_isDirectory(path)) {
nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd); /* Recursively call "UTIL_prepareFileList" with the new path. */
- if (*bufStart == NULL) { closedir(dir); return 0; }
+ if (*bufStart == NULL) { free(path); closedir(dir); return 0; }
} else {
if (*bufStart + *pos + pathLength >= *bufEnd) {
ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;
- *bufStart = (char*)realloc(*bufStart, newListSize);
+ *bufStart = (char*)UTIL_realloc(*bufStart, newListSize);
*bufEnd = *bufStart + newListSize;
- if (*bufStart == NULL) { closedir(dir); return 0; }
+ if (*bufStart == NULL) { free(path); closedir(dir); return 0; }
}
if (*bufStart + *pos + pathLength < *bufEnd) {
strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos));
@@ -297,6 +322,7 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
nbFiles++;
}
}
+ free(path);
errno = 0; /* clear errno after UTIL_isDirectory, UTIL_prepareFileList */
}
@@ -342,7 +368,7 @@ UTIL_STATIC const char** UTIL_createFileList(const char **inputNames, unsigned i
size_t len = strlen(inputNames[i]);
if (buf + pos + len >= bufend) {
ptrdiff_t newListSize = (bufend - buf) + LIST_SIZE_INCREASE;
- buf = (char*)realloc(buf, newListSize);
+ buf = (char*)UTIL_realloc(buf, newListSize);
bufend = buf + newListSize;
if (!buf) return NULL;
}
diff --git a/programs/zstd.1 b/programs/zstd.1
index 0a0ad629d..c262a0c6a 100644
--- a/programs/zstd.1
+++ b/programs/zstd.1
@@ -89,6 +89,10 @@ It also features a very fast decoder, with speed > 500 MB/s per core.
.BR \-t ", " --test
Test the integrity of compressed files. This option is equivalent to \fB--decompress --stdout > /dev/null\fR.
No files are created or removed.
+.TP
+.BR --
+ All arguments after -- are treated as files
+
.SH DICTIONARY
.PP
@@ -135,7 +139,7 @@ Typical gains range from ~10% (at 64KB) to x5 better (at <1KB).
.SH BUGS
-Report bugs at:- https://github.com/Cyan4973/zstd/issues
+Report bugs at:- https://github.com/facebook/zstd/issues
.SH AUTHOR
Yann Collet
diff --git a/programs/zstdcli.c b/programs/zstdcli.c
index 2d6d45214..6d1d9f649 100644
--- a/programs/zstdcli.c
+++ b/programs/zstdcli.c
@@ -23,7 +23,7 @@
#endif
#ifndef ZSTDCLI_CLEVEL_MAX
-# define ZSTDCLI_CLEVEL_MAX 19
+# define ZSTDCLI_CLEVEL_MAX 19 /* when not using --ultra */
#endif
@@ -51,13 +51,11 @@
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
# include /* _isatty */
# define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
+#elif defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) || (defined(__APPLE__) && defined(__MACH__)) /* https://sourceforge.net/p/predef/wiki/OperatingSystems/ */
+# include /* isatty */
+# define IS_CONSOLE(stdStream) isatty(fileno(stdStream))
#else
-# if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)
-# include /* isatty */
-# define IS_CONSOLE(stdStream) isatty(fileno(stdStream))
-# else
-# define IS_CONSOLE(stdStream) 0
-# endif
+# define IS_CONSOLE(stdStream) 0
#endif
@@ -83,7 +81,7 @@
static const char* g_defaultDictName = "dictionary";
static const unsigned g_defaultMaxDictSize = 110 KB;
-static const int g_defaultDictCLevel = 5;
+static const int g_defaultDictCLevel = 3;
static const unsigned g_defaultSelectivityLevel = 9;
@@ -144,6 +142,7 @@ static int usage_advanced(const char* programName)
DISPLAY( "--test : test compressed file integrity \n");
DISPLAY( "--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)\n");
#endif
+ DISPLAY( "-- : All arguments after \"--\" are treated as files \n");
#ifndef ZSTD_NODICT
DISPLAY( "\n");
DISPLAY( "Dictionary builder :\n");
@@ -182,7 +181,7 @@ static void waitEnter(void)
/*! readU32FromChar() :
@return : unsigned integer value reach from input in `char` format
Will also modify `*stringPtr`, advancing it to position where it stopped reading.
- Note : this function can overflow if result > MAX_UINT */
+ Note : this function can overflow if digit string > MAX_UINT */
static unsigned readU32FromChar(const char** stringPtr)
{
unsigned result = 0;
@@ -194,7 +193,7 @@ static unsigned readU32FromChar(const char** stringPtr)
#define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
-int main(int argCount, char** argv)
+int main(int argCount, const char* argv[])
{
int argNb,
bench=0,
@@ -209,7 +208,8 @@ int main(int argCount, char** argv)
nextArgumentIsMaxDict=0,
nextArgumentIsDictID=0,
nextArgumentIsFile=0,
- ultra=0;
+ ultra=0,
+ lastCommand = 0;
int cLevel = ZSTDCLI_CLEVEL_DEFAULT;
int cLevelLast = 1;
unsigned recursive = 0;
@@ -218,13 +218,12 @@ int main(int argCount, char** argv)
const char* programName = argv[0];
const char* outFileName = NULL;
const char* dictFileName = NULL;
- char* dynNameSpace = NULL;
unsigned maxDictSize = g_defaultMaxDictSize;
unsigned dictID = 0;
int dictCLevel = g_defaultDictCLevel;
unsigned dictSelect = g_defaultSelectivityLevel;
#ifdef UTIL_HAS_CREATEFILELIST
- const char** fileNamesTable = NULL;
+ const char** extendedFileList = NULL;
char* fileNamesBuf = NULL;
unsigned fileNamesNb;
#endif
@@ -262,7 +261,7 @@ int main(int argCount, char** argv)
if (!strcmp(argument, "--verbose")) { displayLevel++; continue; }
if (!strcmp(argument, "--quiet")) { displayLevel--; continue; }
if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; displayLevel-=(displayLevel==2); continue; }
- if (!strcmp(argument, "--ultra")) { ultra=1; FIO_setMaxWLog(0); continue; }
+ if (!strcmp(argument, "--ultra")) { ultra=1; continue; }
if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(2); continue; }
if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(0); continue; }
if (!strcmp(argument, "--no-dictID")) { FIO_setDictIDFlag(0); continue; }
@@ -270,8 +269,8 @@ int main(int argCount, char** argv)
if (!strcmp(argument, "--no-sparse")) { FIO_setSparseWrite(0); continue; }
if (!strcmp(argument, "--test")) { testmode=1; decode=1; continue; }
if (!strcmp(argument, "--train")) { dictBuild=1; outFileName=g_defaultDictName; continue; }
- if (!strcmp(argument, "--maxdict")) { nextArgumentIsMaxDict=1; continue; }
- if (!strcmp(argument, "--dictID")) { nextArgumentIsDictID=1; continue; }
+ if (!strcmp(argument, "--maxdict")) { nextArgumentIsMaxDict=1; lastCommand=1; continue; }
+ if (!strcmp(argument, "--dictID")) { nextArgumentIsDictID=1; lastCommand=1; continue; }
if (!strcmp(argument, "--keep")) { FIO_setRemoveSrcFile(0); continue; }
if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(1); continue; }
@@ -289,13 +288,17 @@ int main(int argCount, char** argv)
argument++;
while (argument[0]!=0) {
- #ifndef ZSTD_NOCOMPRESS
+ if (lastCommand) {
+ DISPLAY("error : command must be followed by argument \n");
+ return 1;
+ }
+#ifndef ZSTD_NOCOMPRESS
/* compression Level */
if ((*argument>='0') && (*argument<='9')) {
dictCLevel = cLevel = readU32FromChar(&argument);
continue;
}
- #endif
+#endif
switch(argument[0])
{
@@ -311,7 +314,7 @@ int main(int argCount, char** argv)
case 'c': forceStdout=1; outFileName=stdoutmark; argument++; break;
/* Use file content as dictionary */
- case 'D': nextEntryIsDictionary = 1; argument++; break;
+ case 'D': nextEntryIsDictionary = 1; lastCommand = 1; argument++; break;
/* Overwrite */
case 'f': FIO_overwriteMode(); forceStdout=1; argument++; break;
@@ -332,12 +335,14 @@ int main(int argCount, char** argv)
case 't': testmode=1; decode=1; argument++; break;
/* destination file name */
- case 'o': nextArgumentIsOutFileName=1; argument++; break;
+ case 'o': nextArgumentIsOutFileName=1; lastCommand=1; argument++; break;
+#ifdef UTIL_HAS_CREATEFILELIST
/* recursive */
case 'r': recursive=1; argument++; break;
+#endif
- #ifndef ZSTD_NOBENCH
+#ifndef ZSTD_NOBENCH
/* Benchmark */
case 'b': bench=1; argument++; break;
@@ -368,7 +373,7 @@ int main(int argCount, char** argv)
BMK_SetBlockSize(bSize);
}
break;
- #endif /* ZSTD_NOBENCH */
+#endif /* ZSTD_NOBENCH */
/* Dictionary Selection level */
case 's':
@@ -378,11 +383,11 @@ int main(int argCount, char** argv)
/* Pause at the end (-p) or set an additional param (-p#) (hidden option) */
case 'p': argument++;
- #ifndef ZSTD_NOBENCH
+#ifndef ZSTD_NOBENCH
if ((*argument>='0') && (*argument<='9')) {
BMK_setAdditionalParam(readU32FromChar(&argument));
} else
- #endif
+#endif
main_pause=1;
break;
/* unknown command */
@@ -394,6 +399,7 @@ int main(int argCount, char** argv)
if (nextArgumentIsMaxDict) {
nextArgumentIsMaxDict = 0;
+ lastCommand = 0;
maxDictSize = readU32FromChar(&argument);
if (toupper(*argument)=='K') maxDictSize <<= 10;
if (toupper(*argument)=='M') maxDictSize <<= 20;
@@ -402,6 +408,7 @@ int main(int argCount, char** argv)
if (nextArgumentIsDictID) {
nextArgumentIsDictID = 0;
+ lastCommand = 0;
dictID = readU32FromChar(&argument);
continue;
}
@@ -410,12 +417,14 @@ int main(int argCount, char** argv)
if (nextEntryIsDictionary) {
nextEntryIsDictionary = 0;
+ lastCommand = 0;
dictFileName = argument;
continue;
}
if (nextArgumentIsOutFileName) {
nextArgumentIsOutFileName = 0;
+ lastCommand = 0;
outFileName = argument;
if (!strcmp(outFileName, "-")) outFileName = stdoutmark;
continue;
@@ -425,17 +434,19 @@ int main(int argCount, char** argv)
filenameTable[filenameIdx++] = argument;
}
+ if (lastCommand) { DISPLAY("error : command must be followed by argument \n"); return 1; } /* forgotten argument */
+
/* Welcome message (if verbose) */
DISPLAYLEVEL(3, WELCOME_MESSAGE);
#ifdef UTIL_HAS_CREATEFILELIST
- if (recursive) {
- fileNamesTable = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, &fileNamesNb);
- if (fileNamesTable) {
+ if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
+ extendedFileList = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, &fileNamesNb);
+ if (extendedFileList) {
unsigned u;
- for (u=0; u $(VOID)
$(VALGRIND) $(PRGDIR)/zstd ; if [ $$? -eq 0 ] ; then echo "zstd without argument should have failed"; false; fi
./datagen -g80 | $(VALGRIND) $(PRGDIR)/zstd - -c > $(VOID)
- ./datagen -g16KB | $(VALGRIND) $(PRGDIR)/zstd -vf - -o $(VOID)
+ ./datagen -g16KB | $(VALGRIND) $(PRGDIR)/zstd -vf - -c > $(VOID)
./datagen -g2930KB | $(VALGRIND) $(PRGDIR)/zstd -5 -vf - -o tmp
- $(VALGRIND) $(PRGDIR)/zstd -vdf tmp -o $(VOID)
- ./datagen -g64MB | $(VALGRIND) $(PRGDIR)/zstd -vf - -o $(VOID)
+ $(VALGRIND) $(PRGDIR)/zstd -vdf tmp -c > $(VOID)
+ ./datagen -g64MB | $(VALGRIND) $(PRGDIR)/zstd -vf - -c > $(VOID)
@rm tmp
$(VALGRIND) ./fuzzer -T1mn -t1
$(VALGRIND) ./fullbench -i1
diff --git a/tests/datagencli.c b/tests/datagencli.c
index 772e3dc99..2f3ebc4d6 100644
--- a/tests/datagencli.c
+++ b/tests/datagencli.c
@@ -9,7 +9,7 @@
/*-************************************
-* Includes
+* Dependencies
**************************************/
#include "util.h" /* Compiler options */
#include