From 8ea9e07bb3c36ee884ca37d6c212af91745a816c Mon Sep 17 00:00:00 2001 From: bapt Date: Sat, 15 Apr 2017 21:25:39 +0000 Subject: [PATCH 1/3] Remove files confusing the git exporter --- build/.gitignore | 20 - build/README.md | 56 -- build/VS2005/fullbench/fullbench.vcproj | 440 -------------- build/VS2005/fuzzer/fuzzer.vcproj | 488 --------------- build/VS2005/zstd.sln | 55 -- build/VS2005/zstd/zstd.vcproj | 548 ----------------- build/VS2005/zstdlib/zstdlib.vcproj | 562 ----------------- build/VS2008/fullbench/fullbench.vcproj | 441 -------------- build/VS2008/fuzzer/fuzzer.vcproj | 489 --------------- build/VS2008/zstd.sln | 56 -- build/VS2008/zstd/zstd.vcproj | 565 ------------------ build/VS2008/zstdlib/zstdlib.vcproj | 547 ----------------- build/VS2010/CompileAsCpp.props | 8 - build/VS2010/datagen/datagen.vcxproj | 167 ------ .../fullbench-dll/fullbench-dll.vcxproj | 185 ------ build/VS2010/fullbench/fullbench.vcxproj | 186 ------ build/VS2010/fuzzer/fuzzer.vcxproj | 197 ------ build/VS2010/libzstd-dll/libzstd-dll.rc | 51 -- build/VS2010/libzstd-dll/libzstd-dll.vcxproj | 233 -------- build/VS2010/libzstd/libzstd.vcxproj | 230 ------- build/VS2010/zstd.sln | 89 --- build/VS2010/zstd/zstd.rc | 51 -- build/VS2010/zstd/zstd.vcxproj | 230 ------- build/VS_scripts/README.md | 54 -- build/VS_scripts/build.VS2010.cmd | 7 - build/VS_scripts/build.VS2012.cmd | 6 - build/VS_scripts/build.VS2013.cmd | 7 - build/VS_scripts/build.VS2015.cmd | 7 - build/VS_scripts/build.generic.cmd | 52 -- build/cmake/.gitignore | 6 - build/cmake/CMakeLists.txt | 41 -- .../AddExtraCompilationFlags.cmake | 329 ---------- build/cmake/cmake_uninstall.cmake.in | 22 - build/cmake/contrib/CMakeLists.txt | 16 - build/cmake/contrib/pzstd/CMakeLists.txt | 30 - build/cmake/lib/CMakeLists.txt | 192 ------ build/cmake/programs/.gitignore | 3 - build/cmake/programs/CMakeLists.txt | 50 -- build/cmake/tests/.gitignore | 7 - build/cmake/tests/CMakeLists.txt | 58 -- lib/dll/example/Makefile | 47 -- lib/dll/example/README.md | 69 --- lib/dll/example/build_package.bat | 18 - lib/dll/example/fullbench-dll.sln | 25 - lib/dll/example/fullbench-dll.vcxproj | 181 ------ lib/dll/libzstd.def | 88 --- programs/fileio.c | 2 +- programs/windres/generate_res.bat | 11 - programs/windres/verrsrc.h | 8 - programs/windres/zstd.rc | 51 -- programs/windres/zstd32.res | Bin 1044 -> 0 bytes programs/windres/zstd64.res | Bin 1044 -> 0 bytes 52 files changed, 1 insertion(+), 7280 deletions(-) delete mode 100644 build/.gitignore delete mode 100644 build/README.md delete mode 100644 build/VS2005/fullbench/fullbench.vcproj delete mode 100644 build/VS2005/fuzzer/fuzzer.vcproj delete mode 100644 build/VS2005/zstd.sln delete mode 100644 build/VS2005/zstd/zstd.vcproj delete mode 100644 build/VS2005/zstdlib/zstdlib.vcproj delete mode 100644 build/VS2008/fullbench/fullbench.vcproj delete mode 100644 build/VS2008/fuzzer/fuzzer.vcproj delete mode 100644 build/VS2008/zstd.sln delete mode 100644 build/VS2008/zstd/zstd.vcproj delete mode 100644 build/VS2008/zstdlib/zstdlib.vcproj delete mode 100644 build/VS2010/CompileAsCpp.props delete mode 100644 build/VS2010/datagen/datagen.vcxproj delete mode 100644 build/VS2010/fullbench-dll/fullbench-dll.vcxproj delete mode 100644 build/VS2010/fullbench/fullbench.vcxproj delete mode 100644 build/VS2010/fuzzer/fuzzer.vcxproj delete mode 100644 build/VS2010/libzstd-dll/libzstd-dll.rc delete mode 100644 build/VS2010/libzstd-dll/libzstd-dll.vcxproj delete mode 100644 build/VS2010/libzstd/libzstd.vcxproj delete mode 100644 build/VS2010/zstd.sln delete mode 100644 build/VS2010/zstd/zstd.rc delete mode 100644 build/VS2010/zstd/zstd.vcxproj delete mode 100644 build/VS_scripts/README.md delete mode 100644 build/VS_scripts/build.VS2010.cmd delete mode 100644 build/VS_scripts/build.VS2012.cmd delete mode 100644 build/VS_scripts/build.VS2013.cmd delete mode 100644 build/VS_scripts/build.VS2015.cmd delete mode 100644 build/VS_scripts/build.generic.cmd delete mode 100644 build/cmake/.gitignore delete mode 100644 build/cmake/CMakeLists.txt delete mode 100644 build/cmake/CMakeModules/AddExtraCompilationFlags.cmake delete mode 100644 build/cmake/cmake_uninstall.cmake.in delete mode 100644 build/cmake/contrib/CMakeLists.txt delete mode 100644 build/cmake/contrib/pzstd/CMakeLists.txt delete mode 100644 build/cmake/lib/CMakeLists.txt delete mode 100644 build/cmake/programs/.gitignore delete mode 100644 build/cmake/programs/CMakeLists.txt delete mode 100644 build/cmake/tests/.gitignore delete mode 100644 build/cmake/tests/CMakeLists.txt delete mode 100644 lib/dll/example/Makefile delete mode 100644 lib/dll/example/README.md delete mode 100644 lib/dll/example/build_package.bat delete mode 100644 lib/dll/example/fullbench-dll.sln delete mode 100644 lib/dll/example/fullbench-dll.vcxproj delete mode 100644 lib/dll/libzstd.def delete mode 100644 programs/windres/generate_res.bat delete mode 100644 programs/windres/verrsrc.h delete mode 100644 programs/windres/zstd.rc delete mode 100644 programs/windres/zstd32.res delete mode 100644 programs/windres/zstd64.res diff --git a/build/.gitignore b/build/.gitignore deleted file mode 100644 index f03aac8b370f..000000000000 --- a/build/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -# Visual C++ -.vs/ -*Copy -*.db -*.opensdf -*.sdf -*.suo -*.user -*.opendb - -VS2005/ -VS2008/ -VS2010/bin/ -VS2010/zwrapbench/ -VS2012/bin/ -VS2013/bin/ -VS2015/bin/ - -# CMake -cmake/ diff --git a/build/README.md b/build/README.md deleted file mode 100644 index c4abe9efd481..000000000000 --- a/build/README.md +++ /dev/null @@ -1,56 +0,0 @@ -Projects for various integrated development environments (IDE) -============================================================== - -#### Included projects - -The following projects are included with the zstd distribution: -- `cmake` - CMake project contributed by Artyom Dymchenko -- `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) -- `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/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. -6. Change `Debug` to `Release` and if you have 64-bit Windows change also `Win32` to `x64`. -7. Press F7 on keyboard or select `BUILD` from the menu bar and choose `Build Solution`. -8. If compilation will be fine a compiled executable will be in `projects\VS2010\bin\x64\Release\zstd.exe` - - -#### Projects available within zstd.sln - -The Visual Studio solution file `visual\VS2010\zstd.sln` contains many projects that will be compiled to the -`visual\VS2010\bin\$(Platform)_$(Configuration)` directory. For example `zstd` set to `x64` and -`Release` will be compiled to `visual\VS2010\bin\x64_Release\zstd.exe`. The solution file contains the -following projects: - -- `zstd` : Command Line Utility, supporting gzip-like arguments -- `datagen` : Synthetic and parametrable data generator, for tests -- `fullbench` : Precisely measure speed for each zstd inner functions -- `fuzzer` : Test tool, to check zstd integrity on target platform -- `libzstd` : A static ZSTD library compiled to `libzstd_static.lib` -- `libzstd-dll` : A dynamic ZSTD library (DLL) compiled to `libzstd.dll` with the import library `libzstd.lib` -- `fullbench-dll` : The fullbench program compiled with the import library; the executable requires ZSTD DLL - - -#### Using ZSTD DLL with Microsoft Visual C++ project - -The header file `lib\zstd.h` and the import library -`visual\VS2010\bin\$(Platform)_$(Configuration)\libzstd.lib` are required to compile -a project using Visual C++. - -1. The path to header files should be added to `Additional Include Directories` that can - be found in Project Properties of Visual Studio IDE in the `C/C++` Property Pages on the `General` page. -2. The import library has to be added to `Additional Dependencies` that can - be found in Project Properties in the `Linker` Property Pages on the `Input` page. - If one will provide only the name `libzstd.lib` without a full path to the library - then the directory has to be added to `Linker\General\Additional Library Directories`. - -The compiled executable will require ZSTD DLL which is available at -`visual\VS2010\bin\$(Platform)_$(Configuration)\libzstd.dll`. diff --git a/build/VS2005/fullbench/fullbench.vcproj b/build/VS2005/fullbench/fullbench.vcproj deleted file mode 100644 index ca235d01d9eb..000000000000 --- a/build/VS2005/fullbench/fullbench.vcproj +++ /dev/null @@ -1,440 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2005/fuzzer/fuzzer.vcproj b/build/VS2005/fuzzer/fuzzer.vcproj deleted file mode 100644 index 58af602395c1..000000000000 --- a/build/VS2005/fuzzer/fuzzer.vcproj +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2005/zstd.sln b/build/VS2005/zstd.sln deleted file mode 100644 index dfc73b4685aa..000000000000 --- a/build/VS2005/zstd.sln +++ /dev/null @@ -1,55 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zstd", "zstd\zstd.vcproj", "{1A2AB08E-5CE7-4C5B-BE55-458157C14051}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fuzzer", "fuzzer\fuzzer.vcproj", "{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench", "fullbench\fullbench.vcproj", "{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zstdlib", "zstdlib\zstdlib.vcproj", "{99DE2A79-7298-4004-A0ED-030D7A3796CA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|Win32.ActiveCfg = Debug|Win32 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|Win32.Build.0 = Debug|Win32 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|x64.ActiveCfg = Debug|x64 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|x64.Build.0 = Debug|x64 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|Win32.ActiveCfg = Release|Win32 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|Win32.Build.0 = Release|Win32 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|x64.ActiveCfg = Release|x64 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|x64.Build.0 = Release|x64 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|Win32.ActiveCfg = Debug|Win32 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|Win32.Build.0 = Debug|Win32 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|x64.ActiveCfg = Debug|x64 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|x64.Build.0 = Debug|x64 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|Win32.ActiveCfg = Release|Win32 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|Win32.Build.0 = Release|Win32 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|x64.ActiveCfg = Release|x64 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|x64.Build.0 = Release|x64 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|Win32.ActiveCfg = Debug|Win32 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|Win32.Build.0 = Debug|Win32 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|x64.ActiveCfg = Debug|x64 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|x64.Build.0 = Debug|x64 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|Win32.ActiveCfg = Release|Win32 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|Win32.Build.0 = Release|Win32 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|x64.ActiveCfg = Release|x64 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|x64.Build.0 = Release|x64 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|Win32.ActiveCfg = Debug|Win32 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|Win32.Build.0 = Debug|Win32 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|x64.ActiveCfg = Debug|x64 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|x64.Build.0 = Debug|x64 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|Win32.ActiveCfg = Release|Win32 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|Win32.Build.0 = Release|Win32 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|x64.ActiveCfg = Release|x64 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/build/VS2005/zstd/zstd.vcproj b/build/VS2005/zstd/zstd.vcproj deleted file mode 100644 index 37fc423c5fa3..000000000000 --- a/build/VS2005/zstd/zstd.vcproj +++ /dev/null @@ -1,548 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2005/zstdlib/zstdlib.vcproj b/build/VS2005/zstdlib/zstdlib.vcproj deleted file mode 100644 index 19ab436e16fa..000000000000 --- a/build/VS2005/zstdlib/zstdlib.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2008/fullbench/fullbench.vcproj b/build/VS2008/fullbench/fullbench.vcproj deleted file mode 100644 index 8679a1238615..000000000000 --- a/build/VS2008/fullbench/fullbench.vcproj +++ /dev/null @@ -1,441 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2008/fuzzer/fuzzer.vcproj b/build/VS2008/fuzzer/fuzzer.vcproj deleted file mode 100644 index 0a5b96ba8281..000000000000 --- a/build/VS2008/fuzzer/fuzzer.vcproj +++ /dev/null @@ -1,489 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2008/zstd.sln b/build/VS2008/zstd.sln deleted file mode 100644 index 89b6993ba4e3..000000000000 --- a/build/VS2008/zstd.sln +++ /dev/null @@ -1,56 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zstd", "zstd\zstd.vcproj", "{1A2AB08E-5CE7-4C5B-BE55-458157C14051}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fuzzer", "fuzzer\fuzzer.vcproj", "{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench", "fullbench\fullbench.vcproj", "{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zstdlib", "zstdlib\zstdlib.vcproj", "{99DE2A79-7298-4004-A0ED-030D7A3796CA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|Win32.ActiveCfg = Debug|Win32 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|Win32.Build.0 = Debug|Win32 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|x64.ActiveCfg = Debug|x64 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|x64.Build.0 = Debug|x64 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|Win32.ActiveCfg = Release|Win32 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|Win32.Build.0 = Release|Win32 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|x64.ActiveCfg = Release|x64 - {1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|x64.Build.0 = Release|x64 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|Win32.ActiveCfg = Debug|Win32 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|Win32.Build.0 = Debug|Win32 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|x64.ActiveCfg = Debug|x64 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|x64.Build.0 = Debug|x64 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|Win32.ActiveCfg = Release|Win32 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|Win32.Build.0 = Release|Win32 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|x64.ActiveCfg = Release|x64 - {A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|x64.Build.0 = Release|x64 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|Win32.ActiveCfg = Debug|Win32 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|Win32.Build.0 = Debug|Win32 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|x64.ActiveCfg = Debug|x64 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|x64.Build.0 = Debug|x64 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|Win32.ActiveCfg = Release|Win32 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|Win32.Build.0 = Release|Win32 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|x64.ActiveCfg = Release|x64 - {CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|x64.Build.0 = Release|x64 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|Win32.ActiveCfg = Debug|Win32 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|Win32.Build.0 = Debug|Win32 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|x64.ActiveCfg = Debug|x64 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|x64.Build.0 = Debug|x64 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|Win32.ActiveCfg = Release|Win32 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|Win32.Build.0 = Release|Win32 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|x64.ActiveCfg = Release|x64 - {99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/build/VS2008/zstd/zstd.vcproj b/build/VS2008/zstd/zstd.vcproj deleted file mode 100644 index f0e3f185d938..000000000000 --- a/build/VS2008/zstd/zstd.vcproj +++ /dev/null @@ -1,565 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2008/zstdlib/zstdlib.vcproj b/build/VS2008/zstdlib/zstdlib.vcproj deleted file mode 100644 index 877d393472d3..000000000000 --- a/build/VS2008/zstdlib/zstdlib.vcproj +++ /dev/null @@ -1,547 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2010/CompileAsCpp.props b/build/VS2010/CompileAsCpp.props deleted file mode 100644 index 372a94b1f9b7..000000000000 --- a/build/VS2010/CompileAsCpp.props +++ /dev/null @@ -1,8 +0,0 @@ - - - - - CompileAsCpp - - - diff --git a/build/VS2010/datagen/datagen.vcxproj b/build/VS2010/datagen/datagen.vcxproj deleted file mode 100644 index 280a56e63a0b..000000000000 --- a/build/VS2010/datagen/datagen.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {037E781E-81A6-494B-B1B3-438AB1200523} - Win32Proj - datagen - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - MultiByte - - - Application - true - MultiByte - - - Application - false - true - MultiByte - - - Application - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - false - $(IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - - - true - false - $(IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - - - false - false - $(IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - - - false - false - $(IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/VS2010/fullbench-dll/fullbench-dll.vcxproj b/build/VS2010/fullbench-dll/fullbench-dll.vcxproj deleted file mode 100644 index a13525b2f047..000000000000 --- a/build/VS2010/fullbench-dll/fullbench-dll.vcxproj +++ /dev/null @@ -1,185 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8} - Win32Proj - fullbench-dll - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - MultiByte - - - Application - true - MultiByte - - - Application - false - true - MultiByte - - - Application - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - false - - - Console - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - false - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - false - - - Console - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - false - - - - - Level4 - - - MaxSpeed - true - true - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - {00000000-94d5-4bf9-8a50-7bd9929a0850} - - - - - - \ No newline at end of file diff --git a/build/VS2010/fullbench/fullbench.vcxproj b/build/VS2010/fullbench/fullbench.vcxproj deleted file mode 100644 index 7766c94024c1..000000000000 --- a/build/VS2010/fullbench/fullbench.vcxproj +++ /dev/null @@ -1,186 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8} - Win32Proj - fullbench - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - MultiByte - - - Application - true - MultiByte - - - Application - false - true - MultiByte - - - Application - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2010/fuzzer/fuzzer.vcxproj b/build/VS2010/fuzzer/fuzzer.vcxproj deleted file mode 100644 index 57d4d54d0663..000000000000 --- a/build/VS2010/fuzzer/fuzzer.vcxproj +++ /dev/null @@ -1,197 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {6FD4352B-346C-4703-96EA-D4A8B9A6976E} - Win32Proj - fuzzer - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - MultiByte - - - Application - true - MultiByte - - - Application - false - true - MultiByte - - - Application - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - - - true - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - - - false - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - - - false - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/VS2010/libzstd-dll/libzstd-dll.rc b/build/VS2010/libzstd-dll/libzstd-dll.rc deleted file mode 100644 index d3c00b4bd74b..000000000000 --- a/build/VS2010/libzstd-dll/libzstd-dll.rc +++ /dev/null @@ -1,51 +0,0 @@ -// 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, Facebook, Inc." - VALUE "FileDescription", "Zstandard - Fast and efficient compression algorithm" - VALUE "FileVersion", ZSTD_VERSION_STRING - VALUE "InternalName", "libzstd.dll" - VALUE "LegalCopyright", "Copyright (c) 2013-present, Yann Collet, Facebook, Inc." - VALUE "OriginalFilename", "libzstd.dll" - VALUE "ProductName", "Zstandard" - VALUE "ProductVersion", ZSTD_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1200 - END -END - -#endif diff --git a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj deleted file mode 100644 index e923f86c87e9..000000000000 --- a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj +++ /dev/null @@ -1,233 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {00000000-94D5-4BF9-8A50-7BD9929A0850} - Win32Proj - libzstd-dll - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - DynamicLibrary - true - MultiByte - - - DynamicLibrary - true - MultiByte - - - DynamicLibrary - false - true - MultiByte - - - DynamicLibrary - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - libzstd - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - - - true - libzstd - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - - - false - libzstd - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - - - false - libzstd - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - - - - - - Level4 - Disabled - ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - EditAndContinue - true - false - - - Console - true - MachineX86 - - - - - - - Level4 - Disabled - ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - ProgramDatabase - false - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - false - MultiThreaded - ProgramDatabase - All - - - Console - true - true - true - MachineX86 - - - - - Level4 - - - MaxSpeed - true - true - ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - false - false - MultiThreaded - ProgramDatabase - true - true - All - - - Console - true - true - true - - - - - - diff --git a/build/VS2010/libzstd/libzstd.vcxproj b/build/VS2010/libzstd/libzstd.vcxproj deleted file mode 100644 index 1eae64c0b7ec..000000000000 --- a/build/VS2010/libzstd/libzstd.vcxproj +++ /dev/null @@ -1,230 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} - Win32Proj - libzstd - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - StaticLibrary - true - MultiByte - - - StaticLibrary - true - MultiByte - - - StaticLibrary - false - true - MultiByte - - - StaticLibrary - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - libzstd_static - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - - - true - libzstd_static - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - - - false - libzstd_static - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - - - false - libzstd_static - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - - - - - - Level4 - Disabled - ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - EditAndContinue - true - false - - - Console - true - MachineX86 - - - - - - - Level4 - Disabled - ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - ProgramDatabase - false - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - false - MultiThreaded - ProgramDatabase - All - - - Console - true - true - true - MachineX86 - - - - - Level4 - - - MaxSpeed - true - true - ZSTD_DLL_EXPORT=1;ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - false - false - MultiThreaded - ProgramDatabase - true - true - All - - - Console - true - true - true - - - - - - diff --git a/build/VS2010/zstd.sln b/build/VS2010/zstd.sln deleted file mode 100644 index ddcf8401a21d..000000000000 --- a/build/VS2010/zstd.sln +++ /dev/null @@ -1,89 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2012 for Windows Desktop -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zstd", "zstd\zstd.vcxproj", "{4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fuzzer", "fuzzer\fuzzer.vcxproj", "{6FD4352B-346C-4703-96EA-D4A8B9A6976E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench", "fullbench\fullbench.vcxproj", "{61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench-dll", "fullbench-dll\fullbench-dll.vcxproj", "{00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}" - ProjectSection(ProjectDependencies) = postProject - {00000000-94D5-4BF9-8A50-7BD9929A0850} = {00000000-94D5-4BF9-8A50-7BD9929A0850} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "datagen", "datagen\datagen.vcxproj", "{037E781E-81A6-494B-B1B3-438AB1200523}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd", "libzstd\libzstd.vcxproj", "{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd-dll", "libzstd-dll\libzstd-dll.vcxproj", "{00000000-94D5-4BF9-8A50-7BD9929A0850}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}.Debug|Win32.ActiveCfg = Debug|Win32 - {4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}.Debug|Win32.Build.0 = Debug|Win32 - {4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}.Debug|x64.ActiveCfg = Debug|x64 - {4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}.Debug|x64.Build.0 = Debug|x64 - {4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}.Release|Win32.ActiveCfg = Release|Win32 - {4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}.Release|Win32.Build.0 = Release|Win32 - {4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}.Release|x64.ActiveCfg = Release|x64 - {4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}.Release|x64.Build.0 = Release|x64 - {6FD4352B-346C-4703-96EA-D4A8B9A6976E}.Debug|Win32.ActiveCfg = Debug|Win32 - {6FD4352B-346C-4703-96EA-D4A8B9A6976E}.Debug|Win32.Build.0 = Debug|Win32 - {6FD4352B-346C-4703-96EA-D4A8B9A6976E}.Debug|x64.ActiveCfg = Debug|x64 - {6FD4352B-346C-4703-96EA-D4A8B9A6976E}.Debug|x64.Build.0 = Debug|x64 - {6FD4352B-346C-4703-96EA-D4A8B9A6976E}.Release|Win32.ActiveCfg = Release|Win32 - {6FD4352B-346C-4703-96EA-D4A8B9A6976E}.Release|Win32.Build.0 = Release|Win32 - {6FD4352B-346C-4703-96EA-D4A8B9A6976E}.Release|x64.ActiveCfg = Release|x64 - {6FD4352B-346C-4703-96EA-D4A8B9A6976E}.Release|x64.Build.0 = Release|x64 - {61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}.Debug|Win32.ActiveCfg = Debug|Win32 - {61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}.Debug|Win32.Build.0 = Debug|Win32 - {61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}.Debug|x64.ActiveCfg = Debug|x64 - {61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}.Debug|x64.Build.0 = Debug|x64 - {61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}.Release|Win32.ActiveCfg = Release|Win32 - {61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}.Release|Win32.Build.0 = Release|Win32 - {61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}.Release|x64.ActiveCfg = Release|x64 - {61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}.Release|x64.Build.0 = Release|x64 - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}.Debug|Win32.ActiveCfg = Debug|Win32 - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}.Debug|Win32.Build.0 = Debug|Win32 - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}.Debug|x64.ActiveCfg = Debug|x64 - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}.Debug|x64.Build.0 = Debug|x64 - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}.Release|Win32.ActiveCfg = Release|Win32 - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}.Release|Win32.Build.0 = Release|Win32 - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}.Release|x64.ActiveCfg = Release|x64 - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}.Release|x64.Build.0 = Release|x64 - {037E781E-81A6-494B-B1B3-438AB1200523}.Debug|Win32.ActiveCfg = Debug|Win32 - {037E781E-81A6-494B-B1B3-438AB1200523}.Debug|Win32.Build.0 = Debug|Win32 - {037E781E-81A6-494B-B1B3-438AB1200523}.Debug|x64.ActiveCfg = Debug|x64 - {037E781E-81A6-494B-B1B3-438AB1200523}.Debug|x64.Build.0 = Debug|x64 - {037E781E-81A6-494B-B1B3-438AB1200523}.Release|Win32.ActiveCfg = Release|Win32 - {037E781E-81A6-494B-B1B3-438AB1200523}.Release|Win32.Build.0 = Release|Win32 - {037E781E-81A6-494B-B1B3-438AB1200523}.Release|x64.ActiveCfg = Release|x64 - {037E781E-81A6-494B-B1B3-438AB1200523}.Release|x64.Build.0 = Release|x64 - {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|Win32.ActiveCfg = Debug|Win32 - {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|Win32.Build.0 = Debug|Win32 - {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.ActiveCfg = Debug|x64 - {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.Build.0 = Debug|x64 - {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|Win32.ActiveCfg = Release|Win32 - {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|Win32.Build.0 = Release|Win32 - {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.ActiveCfg = Release|x64 - {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.Build.0 = Release|x64 - {00000000-94D5-4BF9-8A50-7BD9929A0850}.Debug|Win32.ActiveCfg = Debug|Win32 - {00000000-94D5-4BF9-8A50-7BD9929A0850}.Debug|Win32.Build.0 = Debug|Win32 - {00000000-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.ActiveCfg = Debug|x64 - {00000000-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.Build.0 = Debug|x64 - {00000000-94D5-4BF9-8A50-7BD9929A0850}.Release|Win32.ActiveCfg = Release|Win32 - {00000000-94D5-4BF9-8A50-7BD9929A0850}.Release|Win32.Build.0 = Release|Win32 - {00000000-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.ActiveCfg = Release|x64 - {00000000-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/build/VS2010/zstd/zstd.rc b/build/VS2010/zstd/zstd.rc deleted file mode 100644 index 4a8aef3b1392..000000000000 --- a/build/VS2010/zstd/zstd.rc +++ /dev/null @@ -1,51 +0,0 @@ -// 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, Facebook, Inc." - VALUE "FileDescription", "Zstandard - Fast and efficient compression algorithm" - VALUE "FileVersion", ZSTD_VERSION_STRING - VALUE "InternalName", "zstd.exe" - VALUE "LegalCopyright", "Copyright (c) 2013-present, Yann Collet, Facebook, Inc." - 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/build/VS2010/zstd/zstd.vcxproj b/build/VS2010/zstd/zstd.vcxproj deleted file mode 100644 index 7b1d420f3419..000000000000 --- a/build/VS2010/zstd/zstd.vcxproj +++ /dev/null @@ -1,230 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C} - Win32Proj - zstd - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - MultiByte - - - Application - true - MultiByte - - - Application - false - true - MultiByte - - - Application - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - $(LibraryPath) - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - $(LibraryPath); - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - $(LibraryPath) - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); - false - $(LibraryPath); - - - - - - Level4 - Disabled - ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - - - Console - true - setargv.obj;%(AdditionalDependencies) - - - - - - - Level4 - Disabled - ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - - - Console - true - setargv.obj;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - setargv.obj;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - /DZSTD_MULTITHREAD %(AdditionalOptions) - - - Console - true - true - true - setargv.obj;%(AdditionalDependencies) - - - - - - diff --git a/build/VS_scripts/README.md b/build/VS_scripts/README.md deleted file mode 100644 index 3942e381176c..000000000000 --- a/build/VS_scripts/README.md +++ /dev/null @@ -1,54 +0,0 @@ -Command line scripts for Visual Studio compilation without IDE -============================================================== - -Here are a few command lines for reference : - -### Build with Visual Studio 2013 for msvcr120.dll - -Running the following command will build both the `Release Win32` and `Release x64` versions: -```batch -build\build.VS2013.cmd -``` -The result of each build will be in the corresponding `build\bin\Release\{ARCH}\` folder. - -If you want to only need one architecture: -- Win32: `build\build.generic.cmd VS2013 Win32 Release v120` -- x64: `build\build.generic.cmd VS2013 x64 Release v120` - -If you want a Debug build: -- Win32: `build\build.generic.cmd VS2013 Win32 Debug v120` -- x64: `build\build.generic.cmd VS2013 x64 Debug v120` - -### Build with Visual Studio 2015 for msvcr140.dll - -Running the following command will build both the `Release Win32` and `Release x64` versions: -```batch -build\build.VS2015.cmd -``` -The result of each build will be in the corresponding `build\bin\Release\{ARCH}\` folder. - -If you want to only need one architecture: -- Win32: `build\build.generic.cmd VS2015 Win32 Release v140` -- x64: `build\build.generic.cmd VS2015 x64 Release v140` - -If you want a Debug build: -- Win32: `build\build.generic.cmd VS2015 Win32 Debug v140` -- x64: `build\build.generic.cmd VS2015 x64 Debug v140` - -### Build with Visual Studio 2015 for msvcr120.dll - -You need to invoke `build\build.generic.cmd` with the proper arguments: - -**For Win32** -```batch -build\build.generic.cmd VS2015 Win32 Release v120 -``` -The result of the build will be in the `build\bin\Release\Win32\` folder. - -**For x64** -```batch -build\build.generic.cmd VS2015 x64 Release v120 -``` -The result of the build will be in the `build\bin\Release\x64\` folder. - -If you want Debug builds, replace `Release` with `Debug`. diff --git a/build/VS_scripts/build.VS2010.cmd b/build/VS_scripts/build.VS2010.cmd deleted file mode 100644 index 60fbbf69e327..000000000000 --- a/build/VS_scripts/build.VS2010.cmd +++ /dev/null @@ -1,7 +0,0 @@ -@echo off - -rem build 32-bit -call "%~p0%build.generic.cmd" VS2010 Win32 Release v100 - -rem build 64-bit -call "%~p0%build.generic.cmd" VS2010 x64 Release v100 \ No newline at end of file diff --git a/build/VS_scripts/build.VS2012.cmd b/build/VS_scripts/build.VS2012.cmd deleted file mode 100644 index 4328bae921af..000000000000 --- a/build/VS_scripts/build.VS2012.cmd +++ /dev/null @@ -1,6 +0,0 @@ -@echo off - -rem build 32-bit -call "%~p0%build.generic.cmd" VS2012 Win32 Release v110 -rem build 64-bit -call "%~p0%build.generic.cmd" VS2012 x64 Release v110 \ No newline at end of file diff --git a/build/VS_scripts/build.VS2013.cmd b/build/VS_scripts/build.VS2013.cmd deleted file mode 100644 index f906d9025838..000000000000 --- a/build/VS_scripts/build.VS2013.cmd +++ /dev/null @@ -1,7 +0,0 @@ -@echo off - -rem build 32-bit -call "%~p0%build.generic.cmd" VS2013 Win32 Release v120 - -rem build 64-bit -call "%~p0%build.generic.cmd" VS2013 x64 Release v120 \ No newline at end of file diff --git a/build/VS_scripts/build.VS2015.cmd b/build/VS_scripts/build.VS2015.cmd deleted file mode 100644 index 798e9dcb06b5..000000000000 --- a/build/VS_scripts/build.VS2015.cmd +++ /dev/null @@ -1,7 +0,0 @@ -@echo off - -rem build 32-bit -call "%~p0%build.generic.cmd" VS2015 Win32 Release v140 - -rem build 64-bit -call "%~p0%build.generic.cmd" VS2015 x64 Release v140 \ No newline at end of file diff --git a/build/VS_scripts/build.generic.cmd b/build/VS_scripts/build.generic.cmd deleted file mode 100644 index 7c31d556fc44..000000000000 --- a/build/VS_scripts/build.generic.cmd +++ /dev/null @@ -1,52 +0,0 @@ -@echo off - -IF "%1%" == "" GOTO display_help - -SETLOCAL - -SET msbuild_version=%1 - -SET msbuild_platform=%2 -IF "%msbuild_platform%" == "" SET msbuild_platform=x64 - -SET msbuild_configuration=%3 -IF "%msbuild_configuration%" == "" SET msbuild_configuration=Release - -SET msbuild_toolset=%4 - -GOTO build - -:display_help - -echo Syntax: build.generic.cmd msbuild_version msbuild_platform msbuild_configuration msbuild_toolset -echo msbuild_version: VS installed version (VS2012, VS2013, VS2015, ...) -echo msbuild_platform: Platform (x64 or Win32) -echo msbuild_configuration: VS configuration (Release or Debug) -echo msbuild_toolset: Platform Toolset (v100, v110, v120, v140) - -EXIT /B 1 - -:build - -SET msbuild="%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" -IF %msbuild_version% == VS2013 SET msbuild="%programfiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe" -IF %msbuild_version% == VS2015 SET msbuild="%programfiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe" -rem TODO: Visual Studio "15" (vNext) will use MSBuild 15.0 ? - -SET project="%~p0\..\VS2010\zstd.sln" - -SET msbuild_params=/verbosity:minimal /nologo /t:Clean,Build /p:Platform=%msbuild_platform% /p:Configuration=%msbuild_configuration% -IF NOT "%msbuild_toolset%" == "" SET msbuild_params=%msbuild_params% /p:PlatformToolset=%msbuild_toolset% - -SET output=%~p0%bin -SET output="%output%/%msbuild_configuration%/%msbuild_platform%/" -SET msbuild_params=%msbuild_params% /p:OutDir=%output% - -echo ### Building %msbuild_version% project for %msbuild_configuration% %msbuild_platform% (%msbuild_toolset%)... -echo ### Build Params: %msbuild_params% - -%msbuild% %project% %msbuild_params% -IF ERRORLEVEL 1 EXIT /B 1 -echo # Success -echo # OutDir: %output% -echo # diff --git a/build/cmake/.gitignore b/build/cmake/.gitignore deleted file mode 100644 index 98f29c79d994..000000000000 --- a/build/cmake/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# cmake producted -CMakeCache.txt -CMakeFiles -Makefile -cmake_install.cmake -cmake_uninstall.cmake diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt deleted file mode 100644 index 4805cc2c95b4..000000000000 --- a/build/cmake/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -# ################################################################ -# 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) -OPTION(ZSTD_MULTITHREAD_SUPPORT "MULTITHREADING SUPPORT" ON) -OPTION(ZSTD_BUILD_CONTRIB "BUILD CONTRIB" OFF) - -IF (ZSTD_LEGACY_SUPPORT) - MESSAGE(STATUS "ZSTD_LEGACY_SUPPORT defined!") - ADD_DEFINITIONS(-DZSTD_LEGACY_SUPPORT=4) -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) -IF (ZSTD_BUILD_CONTRIB) - ADD_SUBDIRECTORY(contrib) -ENDIF (ZSTD_BUILD_CONTRIB) - -#----------------------------------------------------------------------------- -# 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/build/cmake/CMakeModules/AddExtraCompilationFlags.cmake b/build/cmake/CMakeModules/AddExtraCompilationFlags.cmake deleted file mode 100644 index e480c7eadff7..000000000000 --- a/build/cmake/CMakeModules/AddExtraCompilationFlags.cmake +++ /dev/null @@ -1,329 +0,0 @@ -MACRO(ADD_EXTRA_COMPILATION_FLAGS) - include(CheckCXXCompilerFlag) - include(CheckCCompilerFlag) - if (CMAKE_COMPILER_IS_GNUCXX OR MINGW) #Not only UNIX but also WIN32 for MinGW - - set(POSITION_INDEPENDENT_CODE_FLAG "-fPIC") - CHECK_C_COMPILER_FLAG(${POSITION_INDEPENDENT_CODE_FLAG} POSITION_INDEPENDENT_CODE_FLAG_ALLOWED) - if (POSITION_INDEPENDENT_CODE_FLAG_ALLOWED) - MESSAGE("Compiler flag ${POSITION_INDEPENDENT_CODE_FLAG} allowed") - set(ACTIVATE_POSITION_INDEPENDENT_CODE_FLAG "ON" CACHE BOOL "activate -fPIC flag") - else () - MESSAGE("Compiler flag ${POSITION_INDEPENDENT_CODE_FLAG} not allowed") - endif (POSITION_INDEPENDENT_CODE_FLAG_ALLOWED) - - set(WARNING_UNDEF "-Wundef") - CHECK_C_COMPILER_FLAG(${WARNING_UNDEF} WARNING_UNDEF_ALLOWED) - if (WARNING_UNDEF_ALLOWED) - MESSAGE("Compiler flag ${WARNING_UNDEF} allowed") - set(ACTIVATE_WARNING_UNDEF "ON" CACHE BOOL "activate -Wundef flag") - else () - MESSAGE("Compiler flag ${WARNING_UNDEF} not allowed") - endif (WARNING_UNDEF_ALLOWED) - - set(WARNING_SHADOW "-Wshadow") - CHECK_C_COMPILER_FLAG(${WARNING_SHADOW} WARNING_SHADOW_ALLOWED) - if (WARNING_SHADOW_ALLOWED) - MESSAGE("Compiler flag ${WARNING_SHADOW} allowed") - set(ACTIVATE_WARNING_SHADOW "ON" CACHE BOOL "activate -Wshadow flag") - else () - MESSAGE("Compiler flag ${WARNING_SHADOW} not allowed") - endif (WARNING_SHADOW_ALLOWED) - - set(WARNING_CAST_ALIGN "-Wcast-align") - CHECK_C_COMPILER_FLAG(${WARNING_CAST_ALIGN} WARNING_CAST_ALIGN_ALLOWED) - if (WARNING_CAST_ALIGN_ALLOWED) - MESSAGE("Compiler flag ${WARNING_CAST_ALIGN} allowed") - set(ACTIVATE_WARNING_CAST_ALIGN "ON" CACHE BOOL "activate -Wcast-align flag") - else () - MESSAGE("Compiler flag ${WARNING_CAST_ALIGN} not allowed") - endif (WARNING_CAST_ALIGN_ALLOWED) - - set(WARNING_CAST_QUAL "-Wcast-qual") - CHECK_C_COMPILER_FLAG(${WARNING_CAST_QUAL} WARNING_CAST_QUAL_ALLOWED) - if (WARNING_CAST_QUAL_ALLOWED) - MESSAGE("Compiler flag ${WARNING_CAST_QUAL} allowed") - set(ACTIVATE_WARNING_CAST_QUAL "ON" CACHE BOOL "activate -Wcast-qual flag") - else () - MESSAGE("Compiler flag ${WARNING_CAST_QUAL} not allowed") - endif (WARNING_CAST_QUAL_ALLOWED) - - set(WARNING_STRICT_PROTOTYPES "-Wstrict-prototypes") - CHECK_C_COMPILER_FLAG(${WARNING_STRICT_PROTOTYPES} WARNING_STRICT_PROTOTYPES_ALLOWED) - if (WARNING_STRICT_PROTOTYPES_ALLOWED) - MESSAGE("Compiler flag ${WARNING_STRICT_PROTOTYPES} allowed") - set(ACTIVATE_WARNING_STRICT_PROTOTYPES "ON" CACHE BOOL "activate -Wstrict-prototypes flag") - else () - MESSAGE("Compiler flag ${WARNING_STRICT_PROTOTYPES} not allowed") - endif (WARNING_STRICT_PROTOTYPES_ALLOWED) - - set(WARNING_ALL "-Wall") - CHECK_C_COMPILER_FLAG(${WARNING_ALL} WARNING_ALL_ALLOWED) - if (WARNING_ALL_ALLOWED) - MESSAGE("Compiler flag ${WARNING_ALL} allowed") - set(ACTIVATE_WARNING_ALL "ON" CACHE BOOL "activate -Wall flag") - else () - MESSAGE("Compiler flag ${WARNING_ALL} not allowed") - endif (WARNING_ALL_ALLOWED) - - set(WARNING_EXTRA "-Wextra") - CHECK_C_COMPILER_FLAG(${WARNING_EXTRA} WARNING_EXTRA_ALLOWED) - if (WARNING_EXTRA_ALLOWED) - MESSAGE("Compiler flag ${WARNING_EXTRA} allowed") - set(ACTIVATE_WARNING_EXTRA "ON" CACHE BOOL "activate -Wextra flag") - else () - MESSAGE("Compiler flag ${WARNING_EXTRA} not allowed") - endif (WARNING_EXTRA_ALLOWED) - - set(WARNING_FLOAT_EQUAL "-Wfloat-equal") - CHECK_C_COMPILER_FLAG(${WARNING_FLOAT_EQUAL} WARNING_FLOAT_EQUAL_ALLOWED) - if (WARNING_FLOAT_EQUAL_ALLOWED) - MESSAGE("Compiler flag ${WARNING_FLOAT_EQUAL} allowed") - set(ACTIVATE_WARNING_FLOAT_EQUAL "OFF" CACHE BOOL "activate -Wfloat-equal flag") - else () - MESSAGE("Compiler flag ${WARNING_FLOAT_EQUAL} not allowed") - endif (WARNING_FLOAT_EQUAL_ALLOWED) - - set(WARNING_SIGN_CONVERSION "-Wsign-conversion") - CHECK_C_COMPILER_FLAG(${WARNING_SIGN_CONVERSION} WARNING_SIGN_CONVERSION_ALLOWED) - if (WARNING_SIGN_CONVERSION_ALLOWED) - MESSAGE("Compiler flag ${WARNING_SIGN_CONVERSION} allowed") - set(ACTIVATE_WARNING_SIGN_CONVERSION "OFF" CACHE BOOL "activate -Wsign-conversion flag") - else () - MESSAGE("Compiler flag ${WARNING_SIGN_CONVERSION} not allowed") - endif (WARNING_SIGN_CONVERSION_ALLOWED) - - if (ACTIVATE_POSITION_INDEPENDENT_CODE_FLAG) - list(APPEND CMAKE_C_FLAGS ${POSITION_INDEPENDENT_CODE_FLAG}) - else () - string(REPLACE ${POSITION_INDEPENDENT_CODE_FLAG} "" CMAKE_C_FLAGS "${POSITION_INDEPENDENT_CODE_FLAG}") - endif (ACTIVATE_POSITION_INDEPENDENT_CODE_FLAG) - - if (ACTIVATE_WARNING_UNDEF) - list(APPEND CMAKE_CXX_FLAGS ${WARNING_UNDEF}) - list(APPEND CMAKE_C_FLAGS ${WARNING_UNDEF}) - else () - string(REPLACE ${WARNING_UNDEF} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${WARNING_UNDEF} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_UNDEF) - - if (ACTIVATE_WARNING_SHADOW) - list(APPEND CMAKE_CXX_FLAGS ${WARNING_SHADOW}) - list(APPEND CMAKE_C_FLAGS ${WARNING_SHADOW}) - else () - string(REPLACE ${WARNING_SHADOW} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${WARNING_SHADOW} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_SHADOW) - - if (ACTIVATE_WARNING_CAST_QUAL) - list(APPEND CMAKE_CXX_FLAGS ${WARNING_CAST_QUAL}) - list(APPEND CMAKE_C_FLAGS ${WARNING_CAST_QUAL}) - else () - string(REPLACE ${WARNING_CAST_QUAL} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${WARNING_CAST_QUAL} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_CAST_QUAL) - - if (ACTIVATE_WARNING_CAST_ALIGN) - list(APPEND CMAKE_CXX_FLAGS ${WARNING_CAST_ALIGN}) - list(APPEND CMAKE_C_FLAGS ${WARNING_CAST_ALIGN}) - else () - string(REPLACE ${WARNING_CAST_ALIGN} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${WARNING_CAST_ALIGN} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_CAST_ALIGN) - - if (ACTIVATE_WARNING_STRICT_PROTOTYPES) - list(APPEND CMAKE_C_FLAGS ${WARNING_STRICT_PROTOTYPES}) - else () - string(REPLACE ${WARNING_STRICT_PROTOTYPES} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_STRICT_PROTOTYPES) - - if (ACTIVATE_WARNING_ALL) - list(APPEND CMAKE_CXX_FLAGS ${WARNING_ALL}) - list(APPEND CMAKE_C_FLAGS ${WARNING_ALL}) - else () - string(REPLACE ${WARNING_ALL} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${WARNING_ALL} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_ALL) - - if (ACTIVATE_WARNING_EXTRA) - list(APPEND CMAKE_CXX_FLAGS ${WARNING_EXTRA}) - list(APPEND CMAKE_C_FLAGS ${WARNING_EXTRA}) - else () - string(REPLACE ${WARNING_EXTRA} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${WARNING_EXTRA} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_EXTRA) - - if (ACTIVATE_WARNING_FLOAT_EQUAL) - list(APPEND CMAKE_CXX_FLAGS ${WARNING_FLOAT_EQUAL}) - list(APPEND CMAKE_C_FLAGS ${WARNING_FLOAT_EQUAL}) - else () - string(REPLACE ${WARNING_FLOAT_EQUAL} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${WARNING_FLOAT_EQUAL} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_FLOAT_EQUAL) - - if (ACTIVATE_WARNING_SIGN_CONVERSION) - list(APPEND CMAKE_CXX_FLAGS ${WARNING_SIGN_CONVERSION}) - list(APPEND CMAKE_C_FLAGS ${WARNING_SIGN_CONVERSION}) - else () - string(REPLACE ${WARNING_SIGN_CONVERSION} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${WARNING_SIGN_CONVERSION} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_SIGN_CONVERSION) - - #Set c++11 by default - list(APPEND CMAKE_CXX_FLAGS "-std=c++11") - - #Set c99 by default - list(APPEND CMAKE_C_FLAGS "-std=c99") - - elseif (MSVC) - # Add specific compilation flags for Windows Visual - - set(WARNING_ALL "/Wall") - CHECK_C_COMPILER_FLAG(${WARNING_ALL} WARNING_ALL_ALLOWED) - if (WARNING_ALL_ALLOWED) - MESSAGE("Compiler flag ${WARNING_ALL} allowed") - set(ACTIVATE_WARNING_ALL "OFF" CACHE BOOL "activate /Wall flag") - else () - MESSAGE("Compiler flag ${WARNING_ALL} not allowed") - endif (WARNING_ALL_ALLOWED) - - set(RTC_FLAG "/RTC1") - CHECK_C_COMPILER_FLAG(${RTC_FLAG} RTC_FLAG_ALLOWED) - if (RTC_FLAG_ALLOWED) - MESSAGE("Compiler flag ${RTC_FLAG} allowed") - set(ACTIVATE_RTC_FLAG "ON" CACHE BOOL "activate /RTC1 flag") - else () - MESSAGE("Compiler flag ${RTC_FLAG} not allowed") - endif (RTC_FLAG_ALLOWED) - - set(ZC_FLAG "/Zc:forScope") - CHECK_C_COMPILER_FLAG(${ZC_FLAG} ZC_FLAG_ALLOWED) - if (ZC_FLAG_ALLOWED) - MESSAGE("Compiler flag ${ZC_FLAG} allowed") - set(ACTIVATE_ZC_FLAG "ON" CACHE BOOL "activate /Zc:forScope flag") - else () - MESSAGE("Compiler flag ${ZC_FLAG} not allowed") - endif (ZC_FLAG_ALLOWED) - - set(GD_FLAG "/Gd") - CHECK_C_COMPILER_FLAG(${GD_FLAG} GD_FLAG_ALLOWED) - if (GD_FLAG_ALLOWED) - MESSAGE("Compiler flag ${GD_FLAG} allowed") - set(ACTIVATE_GD_FLAG "ON" CACHE BOOL "activate /Gd flag") - else () - MESSAGE("Compiler flag ${GD_FLAG} not allowed") - endif (GD_FLAG_ALLOWED) - - set(ANALYZE_FLAG "/analyze:stacksize25000") - CHECK_C_COMPILER_FLAG(${ANALYZE_FLAG} ANALYZE_FLAG_ALLOWED) - if (ANALYZE_FLAG_ALLOWED) - MESSAGE("Compiler flag ${ANALYZE_FLAG} allowed") - set(ACTIVATE_ANALYZE_FLAG "ON" CACHE BOOL "activate /ANALYZE flag") - else () - MESSAGE("Compiler flag ${ANALYZE_FLAG} not allowed") - endif (ANALYZE_FLAG_ALLOWED) - - if (ACTIVATE_WARNING_ALL) - list(APPEND CMAKE_CXX_FLAGS ${WARNING_ALL}) - list(APPEND CMAKE_C_FLAGS ${WARNING_ALL}) - else () - string(REPLACE ${WARNING_ALL} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${WARNING_ALL} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_WARNING_ALL) - - # Only for DEBUG version - if (ACTIVATE_RTC_FLAG) - list(APPEND CMAKE_CXX_FLAGS_DEBUG ${RTC_FLAG}) - list(APPEND CMAKE_C_FLAGS_DEBUG ${RTC_FLAG}) - else () - string(REPLACE ${RTC_FLAG} "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE ${RTC_FLAG} "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - endif (ACTIVATE_RTC_FLAG) - - if (ACTIVATE_ZC_FLAG) - list(APPEND CMAKE_CXX_FLAGS ${ZC_FLAG}) - list(APPEND CMAKE_C_FLAGS ${ZC_FLAG}) - else () - string(REPLACE ${ZC_FLAG} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${ZC_FLAG} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_ZC_FLAG) - - if (ACTIVATE_GD_FLAG) - list(APPEND CMAKE_CXX_FLAGS ${GD_FLAG}) - list(APPEND CMAKE_C_FLAGS ${GD_FLAG}) - else () - string(REPLACE ${GD_FLAG} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${GD_FLAG} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_GD_FLAG) - - if (ACTIVATE_ANALYZE_FLAG) - list(APPEND CMAKE_CXX_FLAGS ${ANALYZE_FLAG}) - list(APPEND CMAKE_C_FLAGS ${ANALYZE_FLAG}) - else () - string(REPLACE ${ANALYZE_FLAG} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${ANALYZE_FLAG} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_ANALYZE_FLAG) - - if (MSVC80 OR MSVC90 OR MSVC10 OR MSVC11) - # To avoid compiler warning (level 4) C4571, compile with /EHa if you still want - # your catch(...) blocks to catch structured exceptions. - list(APPEND CMAKE_CXX_FLAGS "/EHa") - endif (MSVC80 OR MSVC90 OR MSVC10 OR MSVC11) - - set(MULTITHREADED_COMPILATION "/MP") - MESSAGE("Compiler flag ${MULTITHREADED_COMPILATION} allowed") - set(ACTIVATE_MULTITHREADED_COMPILATION "ON" CACHE BOOL "activate /MP flag") - - if (ACTIVATE_MULTITHREADED_COMPILATION) - list(APPEND CMAKE_CXX_FLAGS ${MULTITHREADED_COMPILATION}) - list(APPEND CMAKE_C_FLAGS ${MULTITHREADED_COMPILATION}) - else () - string(REPLACE ${MULTITHREADED_COMPILATION} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE ${MULTITHREADED_COMPILATION} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - endif (ACTIVATE_MULTITHREADED_COMPILATION) - - #For exceptions - list(APPEND CMAKE_CXX_FLAGS "/EHsc") - list(APPEND CMAKE_C_FLAGS "/EHsc") - - # UNICODE SUPPORT - list(APPEND CMAKE_CXX_FLAGS "/D_UNICODE /DUNICODE") - list(APPEND CMAKE_C_FLAGS "/D_UNICODE /DUNICODE") - endif () - - # Remove duplicates compilation flags - FOREACH (flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - separate_arguments(${flag_var}) - list(REMOVE_DUPLICATES ${flag_var}) - string(REPLACE ";" " " ${flag_var} "${${flag_var}}") - set(${flag_var} "${${flag_var}}" CACHE STRING "common build flags" FORCE) - ENDFOREACH (flag_var) - - if (MSVC) - # Replace /MT to /MD flag - # Replace /O2 to /O3 flag - FOREACH (flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - STRING(REGEX REPLACE "/MT" "/MD" ${flag_var} "${${flag_var}}") - STRING(REGEX REPLACE "/O2" "/Ox" ${flag_var} "${${flag_var}}") - ENDFOREACH (flag_var) - endif () - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "Updated flags" FORCE) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "Updated flags" FORCE) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "Updated flags" FORCE) - set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}" CACHE STRING "Updated flags" FORCE) - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" CACHE STRING "Updated flags" FORCE) - - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "Updated flags" FORCE) - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "Updated flags" FORCE) - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "Updated flags" FORCE) - set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}" CACHE STRING "Updated flags" FORCE) - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}" CACHE STRING "Updated flags" FORCE) - -ENDMACRO(ADD_EXTRA_COMPILATION_FLAGS) diff --git a/build/cmake/cmake_uninstall.cmake.in b/build/cmake/cmake_uninstall.cmake.in deleted file mode 100644 index e3774dc10ce7..000000000000 --- a/build/cmake/cmake_uninstall.cmake.in +++ /dev/null @@ -1,22 +0,0 @@ - -if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") - message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") -endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") - -file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) -string(REGEX REPLACE "\n" ";" files "${files}") -foreach(file ${files}) - message(STATUS "Uninstalling $ENV{DESTDIR}${file}") - if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") - exec_program( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - if(NOT "${rm_retval}" STREQUAL 0) - message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") - endif(NOT "${rm_retval}" STREQUAL 0) - else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") - message(STATUS "File $ENV{DESTDIR}${file} does not exist.") - endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") -endforeach(file) diff --git a/build/cmake/contrib/CMakeLists.txt b/build/cmake/contrib/CMakeLists.txt deleted file mode 100644 index 68e0881c5b6d..000000000000 --- a/build/cmake/contrib/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -# ################################################################ -# * Copyright (c) 2015-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. -# -# You can contact the author at : -# - zstd homepage : http://www.zstd.net/ -# ################################################################ - -PROJECT(contrib) - -ADD_SUBDIRECTORY(pzstd) - diff --git a/build/cmake/contrib/pzstd/CMakeLists.txt b/build/cmake/contrib/pzstd/CMakeLists.txt deleted file mode 100644 index 2a3663f31ff5..000000000000 --- a/build/cmake/contrib/pzstd/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# ################################################################ -# * Copyright (c) 2015-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. -# -# You can contact the author at : -# - zstd homepage : http://www.zstd.net/ -# ################################################################ - -PROJECT(pzstd) - -SET(CMAKE_INCLUDE_CURRENT_DIR TRUE) - -# Define project root directory -SET(ROOT_DIR ../../../..) - -# Define programs directory, where sources and header files are located -SET(LIBRARY_DIR ${ROOT_DIR}/lib) -SET(PROGRAMS_DIR ${ROOT_DIR}/programs) -SET(PZSTD_DIR ${ROOT_DIR}/contrib/pzstd) -INCLUDE_DIRECTORIES(${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/common ${PZSTD_DIR}) - -ADD_EXECUTABLE(pzstd ${PZSTD_DIR}/main.cpp ${PZSTD_DIR}/Options.cpp ${PZSTD_DIR}/Pzstd.cpp ${PZSTD_DIR}/SkippableFrame.cpp) -TARGET_LINK_LIBRARIES(pzstd libzstd_static pthread) -SET_TARGET_PROPERTIES(pzstd PROPERTIES COMPILE_DEFINITIONS "NDEBUG") -SET_TARGET_PROPERTIES(pzstd PROPERTIES COMPILE_OPTIONS "-Wno-shadow") - diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt deleted file mode 100644 index 1950d97cd1f2..000000000000 --- a/build/cmake/lib/CMakeLists.txt +++ /dev/null @@ -1,192 +0,0 @@ -# ################################################################ -# * Copyright (c) 2014-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. -# -# You can contact the author at : -# - zstd homepage : http://www.zstd.net/ -# ################################################################ - -# Get library version based on information from input content (use regular exp) -function(GetLibraryVersion _content _outputVar1 _outputVar2 _outputVar3) - string(REGEX MATCHALL ".*define ZSTD_VERSION_MAJOR+.* ([0-9]+).*define ZSTD_VERSION_MINOR+.* ([0-9]+).*define ZSTD_VERSION_RELEASE+.* ([0-9]+)" VERSION_REGEX "${_content}") - SET(${_outputVar1} ${CMAKE_MATCH_1} PARENT_SCOPE) - SET(${_outputVar2} ${CMAKE_MATCH_2} PARENT_SCOPE) - SET(${_outputVar3} ${CMAKE_MATCH_3} PARENT_SCOPE) -endfunction() - -PROJECT(libzstd) - -SET(CMAKE_INCLUDE_CURRENT_DIR TRUE) - -# Define project root directory -SET(ROOT_DIR ../../..) - -# Define library directory, where sources and header files are located -SET(LIBRARY_DIR ${ROOT_DIR}/lib) -INCLUDE_DIRECTORIES(${LIBRARY_DIR} ${LIBRARY_DIR}/common) - -# Read file content -FILE(READ ${LIBRARY_DIR}/zstd.h HEADER_CONTENT) - -# Parse version -GetLibraryVersion("${HEADER_CONTENT}" LIBVER_MAJOR LIBVER_MINOR LIBVER_RELEASE) -MESSAGE("ZSTD VERSION ${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}") - -SET(Sources - ${LIBRARY_DIR}/common/entropy_common.c - ${LIBRARY_DIR}/common/fse_decompress.c - ${LIBRARY_DIR}/common/threading.c - ${LIBRARY_DIR}/common/pool.c - ${LIBRARY_DIR}/common/zstd_common.c - ${LIBRARY_DIR}/common/error_private.c - ${LIBRARY_DIR}/common/xxhash.c - ${LIBRARY_DIR}/compress/fse_compress.c - ${LIBRARY_DIR}/compress/huf_compress.c - ${LIBRARY_DIR}/compress/zstd_compress.c - ${LIBRARY_DIR}/compress/zstdmt_compress.c - ${LIBRARY_DIR}/decompress/huf_decompress.c - ${LIBRARY_DIR}/decompress/zstd_decompress.c - ${LIBRARY_DIR}/dictBuilder/cover.c - ${LIBRARY_DIR}/dictBuilder/divsufsort.c - ${LIBRARY_DIR}/dictBuilder/zdict.c - ${LIBRARY_DIR}/deprecated/zbuff_common.c - ${LIBRARY_DIR}/deprecated/zbuff_compress.c - ${LIBRARY_DIR}/deprecated/zbuff_decompress.c) - -SET(Headers - ${LIBRARY_DIR}/zstd.h - ${LIBRARY_DIR}/common/pool.h - ${LIBRARY_DIR}/common/threading.h - ${LIBRARY_DIR}/common/bitstream.h - ${LIBRARY_DIR}/common/error_private.h - ${LIBRARY_DIR}/common/zstd_errors.h - ${LIBRARY_DIR}/common/fse.h - ${LIBRARY_DIR}/common/huf.h - ${LIBRARY_DIR}/common/mem.h - ${LIBRARY_DIR}/common/zstd_internal.h - ${LIBRARY_DIR}/compress/zstdmt_compress.h - ${LIBRARY_DIR}/dictBuilder/zdict.h - ${LIBRARY_DIR}/deprecated/zbuff.h) - -IF (ZSTD_LEGACY_SUPPORT) - SET(LIBRARY_LEGACY_DIR ${LIBRARY_DIR}/legacy) - INCLUDE_DIRECTORIES(${LIBRARY_LEGACY_DIR}) - - SET(Sources ${Sources} - ${LIBRARY_LEGACY_DIR}/zstd_v01.c - ${LIBRARY_LEGACY_DIR}/zstd_v02.c - ${LIBRARY_LEGACY_DIR}/zstd_v03.c - ${LIBRARY_LEGACY_DIR}/zstd_v04.c - ${LIBRARY_LEGACY_DIR}/zstd_v05.c - ${LIBRARY_LEGACY_DIR}/zstd_v06.c - ${LIBRARY_LEGACY_DIR}/zstd_v07.c) - - SET(Headers ${Headers} - ${LIBRARY_LEGACY_DIR}/zstd_legacy.h - ${LIBRARY_LEGACY_DIR}/zstd_v01.h - ${LIBRARY_LEGACY_DIR}/zstd_v02.h - ${LIBRARY_LEGACY_DIR}/zstd_v03.h - ${LIBRARY_LEGACY_DIR}/zstd_v04.h - ${LIBRARY_LEGACY_DIR}/zstd_v05.h - ${LIBRARY_LEGACY_DIR}/zstd_v06.h - ${LIBRARY_LEGACY_DIR}/zstd_v07.h) -ENDIF (ZSTD_LEGACY_SUPPORT) - -IF (MSVC) - SET(MSVC_RESOURCE_DIR ${ROOT_DIR}/build/VS2010/libzstd-dll) - SET(PlatformDependResources ${MSVC_RESOURCE_DIR}/libzstd-dll.rc) -ENDIF (MSVC) - -# Split project to static and shared libraries build -ADD_LIBRARY(libzstd_static STATIC ${Sources} ${Headers}) -ADD_LIBRARY(libzstd_shared SHARED ${Sources} ${Headers} ${PlatformDependResources}) - -# Add specific compile definitions for MSVC project -IF (MSVC) - SET_TARGET_PROPERTIES(libzstd_static PROPERTIES COMPILE_DEFINITIONS "ZSTD_HEAPMODE=0;_CRT_SECURE_NO_WARNINGS") - SET_TARGET_PROPERTIES(libzstd_shared PROPERTIES COMPILE_DEFINITIONS "ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;_CONSOLE;_CRT_SECURE_NO_WARNINGS") -ENDIF (MSVC) - -# Define library base name -IF (MSVC) - SET(LIBRARY_BASE_NAME zstdlib) -ELSE () - SET(LIBRARY_BASE_NAME libzstd) -ENDIF (MSVC) - -IF (MSVC) - IF (CMAKE_SIZEOF_VOID_P MATCHES "8") - SET(LIBRARY_ARCH_SUFFIX "_x64") - ELSE () - SET(LIBRARY_ARCH_SUFFIX "_x86") - ENDIF (CMAKE_SIZEOF_VOID_P MATCHES "8") -ELSE () - SET(LIBRARY_ARCH_SUFFIX "") -ENDIF (MSVC) - -# Define static and shared library names -SET(STATIC_LIBRARY_OUTPUT_NAME ${LIBRARY_BASE_NAME}${LIBRARY_ARCH_SUFFIX} CACHE STRING "Static library output name") -SET(SHARED_LIBRARY_OUTPUT_NAME ${LIBRARY_BASE_NAME}.${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}${LIBRARY_ARCH_SUFFIX} CACHE STRING "Shared library output name") - -SET_TARGET_PROPERTIES( - libzstd_static - PROPERTIES - PREFIX "" - OUTPUT_NAME ${STATIC_LIBRARY_OUTPUT_NAME}) - -SET_TARGET_PROPERTIES( - libzstd_shared - PROPERTIES - PREFIX "" - OUTPUT_NAME ${SHARED_LIBRARY_OUTPUT_NAME}) - -IF (UNIX) - IF ("${PREFIX}" STREQUAL "") - SET(PREFIX /usr/local) - ENDIF() - MESSAGE("the variable PREFIX=${PREFIX}") - SET(INSTALL_LIBRARY_DIR ${PREFIX}/lib) - SET(INSTALL_INCLUDE_DIR ${PREFIX}/include) - - # install target - INSTALL(FILES ${LIBRARY_DIR}/zstd.h ${LIBRARY_DIR}/deprecated/zbuff.h ${LIBRARY_DIR}/dictBuilder/zdict.h DESTINATION ${INSTALL_INCLUDE_DIR}) - INSTALL(TARGETS libzstd_static DESTINATION ${INSTALL_LIBRARY_DIR}) - INSTALL(TARGETS libzstd_shared LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR}) - - # Create symlinks and setup this files - SET(SHARED_LIBRARY_LINK ${SHARED_LIBRARY_OUTPUT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) - SET(SHARED_LIBRARY_SYMLINK1 ${LIBRARY_BASE_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) - SET(SHARED_LIBRARY_SYMLINK2 ${LIBRARY_BASE_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}.${LIBVER_MAJOR}) - - SET(SHARED_LIBRARY_LINK_PATH ${CMAKE_CURRENT_BINARY_DIR}/${SHARED_LIBRARY_LINK}) - SET(SHARED_LIBRARY_SYMLINK1_PATH ${CMAKE_CURRENT_BINARY_DIR}/${SHARED_LIBRARY_SYMLINK1}) - SET(SHARED_LIBRARY_SYMLINK2_PATH ${CMAKE_CURRENT_BINARY_DIR}/${SHARED_LIBRARY_SYMLINK2}) - - ADD_CUSTOM_COMMAND(TARGET libzstd_shared POST_BUILD - COMMAND ${CMAKE_COMMAND} -E create_symlink ${SHARED_LIBRARY_LINK} ${SHARED_LIBRARY_SYMLINK1} - DEPENDS ${SHARED_LIBRARY_LINK_PATH} - COMMENT "Generating symbolic link ${SHARED_LIBRARY_LINK} -> ${SHARED_LIBRARY_SYMLINK1}") - - ADD_CUSTOM_COMMAND(TARGET libzstd_shared POST_BUILD - COMMAND ${CMAKE_COMMAND} -E create_symlink ${SHARED_LIBRARY_LINK} ${SHARED_LIBRARY_SYMLINK2} - DEPENDS ${SHARED_LIBRARY_LINK_PATH} - COMMENT "Generating symbolic link ${SHARED_LIBRARY_LINK} -> ${SHARED_LIBRARY_SYMLINK2}") - - SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${SHARED_LIBRARY_SYMLINK1};${SHARED_LIBRARY_SYMLINK2}") - - INSTALL(FILES ${SHARED_LIBRARY_SYMLINK1_PATH} DESTINATION ${INSTALL_LIBRARY_DIR}) - INSTALL(FILES ${SHARED_LIBRARY_SYMLINK2_PATH} DESTINATION ${INSTALL_LIBRARY_DIR}) - - # uninstall target - CONFIGURE_FILE( - "${CMAKE_SOURCE_DIR}/cmake_uninstall.cmake.in" - "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY) - - ADD_CUSTOM_TARGET(uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake_uninstall.cmake) -ENDIF (UNIX) diff --git a/build/cmake/programs/.gitignore b/build/cmake/programs/.gitignore deleted file mode 100644 index f04c5b429aa7..000000000000 --- a/build/cmake/programs/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# produced by make -zstd -zstd-frugal diff --git a/build/cmake/programs/CMakeLists.txt b/build/cmake/programs/CMakeLists.txt deleted file mode 100644 index c88ee5cc993f..000000000000 --- a/build/cmake/programs/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ -# ################################################################ -# * Copyright (c) 2015-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. -# -# You can contact the author at : -# - zstd homepage : http://www.zstd.net/ -# ################################################################ - -PROJECT(programs) - -SET(CMAKE_INCLUDE_CURRENT_DIR TRUE) - -# Define project root directory -SET(ROOT_DIR ../../..) - -# Define programs directory, where sources and header files are located -SET(LIBRARY_DIR ${ROOT_DIR}/lib) -SET(PROGRAMS_DIR ${ROOT_DIR}/programs) -INCLUDE_DIRECTORIES(${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/common ${LIBRARY_DIR}/compress ${LIBRARY_DIR}/dictBuilder) - -IF (ZSTD_LEGACY_SUPPORT) - SET(PROGRAMS_LEGACY_DIR ${PROGRAMS_DIR}/legacy) - INCLUDE_DIRECTORIES(${PROGRAMS_LEGACY_DIR} ${LIBRARY_DIR}/legacy) -ENDIF (ZSTD_LEGACY_SUPPORT) - -IF (MSVC) - SET(MSVC_RESOURCE_DIR ${ROOT_DIR}/build/VS2010/zstd) - SET(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstd.rc) -ENDIF (MSVC) - -ADD_EXECUTABLE(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/bench.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${PlatformDependResources}) -TARGET_LINK_LIBRARIES(zstd libzstd_static) -IF (UNIX) - ADD_EXECUTABLE(zstd-frugal ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/fileio.c) - TARGET_LINK_LIBRARIES(zstd-frugal libzstd_static) - SET_TARGET_PROPERTIES(zstd-frugal PROPERTIES COMPILE_DEFINITIONS "ZSTD_NOBENCH;ZSTD_NODICT") -ENDIF (UNIX) - -IF (ZSTD_MULTITHREAD_SUPPORT) - ADD_EXECUTABLE(zstdmt ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/bench.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${PlatformDependResources}) - SET_TARGET_PROPERTIES(zstdmt PROPERTIES COMPILE_DEFINITIONS "ZSTD_MULTITHREAD") - TARGET_LINK_LIBRARIES(zstdmt libzstd_static) - IF (UNIX) - TARGET_LINK_LIBRARIES(zstdmt pthread) - ENDIF (UNIX) -ENDIF (ZSTD_MULTITHREAD_SUPPORT) diff --git a/build/cmake/tests/.gitignore b/build/cmake/tests/.gitignore deleted file mode 100644 index 2ab62a3e1ef5..000000000000 --- a/build/cmake/tests/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# produced by make -datagen -fullbench -fuzzer -paramgrill -zbufftest - diff --git a/build/cmake/tests/CMakeLists.txt b/build/cmake/tests/CMakeLists.txt deleted file mode 100644 index 53a6994490ca..000000000000 --- a/build/cmake/tests/CMakeLists.txt +++ /dev/null @@ -1,58 +0,0 @@ -# ################################################################ -# zstd - Makefile -# Copyright (C) Yann Collet 2014-2016 -# All rights reserved. -# -# BSD license -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# You can contact the author at : -# - zstd homepage : http://www.zstd.net/ -# ################################################################ - -PROJECT(tests) - -SET(CMAKE_INCLUDE_CURRENT_DIR TRUE) - -# Define project root directory -SET(ROOT_DIR ../../..) - -# Define programs directory, where sources and header files are located -SET(LIBRARY_DIR ${ROOT_DIR}/lib) -SET(PROGRAMS_DIR ${ROOT_DIR}/programs) -SET(TESTS_DIR ${ROOT_DIR}/tests) -INCLUDE_DIRECTORIES(${TESTS_DIR} ${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/common ${LIBRARY_DIR}/compress ${LIBRARY_DIR}/dictBuilder) - -ADD_EXECUTABLE(fullbench ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/fullbench.c) -TARGET_LINK_LIBRARIES(fullbench libzstd_static) - -ADD_EXECUTABLE(fuzzer ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/fuzzer.c) -TARGET_LINK_LIBRARIES(fuzzer libzstd_static) - -IF (UNIX) - ADD_EXECUTABLE(paramgrill ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/paramgrill.c) - TARGET_LINK_LIBRARIES(paramgrill libzstd_static m) #m is math library - - ADD_EXECUTABLE(datagen ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/datagencli.c) - TARGET_LINK_LIBRARIES(datagen libzstd_static) -ENDIF (UNIX) diff --git a/lib/dll/example/Makefile b/lib/dll/example/Makefile deleted file mode 100644 index 36041a0e300e..000000000000 --- a/lib/dll/example/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# ########################################################################## -# 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. -# ########################################################################## - -VOID := /dev/null -ZSTDDIR := ../include -LIBDIR := ../static -DLLDIR := ../dll - -CFLAGS ?= -O3 # can select custom flags. For example : CFLAGS="-O2 -g" make -CFLAGS += -Wall -Wextra -Wundef -Wcast-qual -Wcast-align -Wshadow -Wswitch-enum \ - -Wdeclaration-after-statement -Wstrict-prototypes \ - -Wpointer-arith -Wstrict-aliasing=1 -CFLAGS += $(MOREFLAGS) -CPPFLAGS:= -I$(ZSTDDIR) -DXXH_NAMESPACE=ZSTD_ -FLAGS := $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) - - -# Define *.exe as extension for Windows systems -ifneq (,$(filter Windows%,$(OS))) -EXT =.exe -else -EXT = -endif - -.PHONY: default fullbench-dll fullbench-lib - - -default: all - -all: fullbench-dll fullbench-lib - - -fullbench-lib: fullbench.c datagen.c - $(CC) $(FLAGS) $^ -o $@$(EXT) $(LIBDIR)/libzstd_static.lib - -fullbench-dll: fullbench.c datagen.c - $(CC) $(FLAGS) $^ -o $@$(EXT) -DZSTD_DLL_IMPORT=1 $(DLLDIR)/libzstd.dll - -clean: - @$(RM) fullbench-dll$(EXT) fullbench-lib$(EXT) \ - @echo Cleaning completed diff --git a/lib/dll/example/README.md b/lib/dll/example/README.md deleted file mode 100644 index 957a29f3560f..000000000000 --- a/lib/dll/example/README.md +++ /dev/null @@ -1,69 +0,0 @@ -ZSTD Windows binary package -==================================== - -#### The package contents - -- `zstd.exe` : Command Line Utility, supporting gzip-like arguments -- `dll\libzstd.dll` : The DLL of ZSTD library -- `dll\libzstd.lib` : The import library of ZSTD library for Visual C++ -- `example\` : The example of usage of ZSTD library -- `include\` : Header files required with ZSTD library -- `static\libzstd_static.lib` : The static ZSTD library - - -#### Usage of Command Line Interface - -Command Line Interface (CLI) supports gzip-like arguments. -By default CLI takes an input file and compresses it to an output file: -``` - Usage: zstd [arg] [input] [output] -``` -The full list of commands for CLI can be obtained with `-h` or `-H`. The ratio can -be improved with commands from `-3` to `-16` but higher levels also have slower -compression. CLI includes in-memory compression benchmark module with compression -levels starting from `-b` and ending with `-e` with iteration time of `-i` seconds. -CLI supports aggregation of parameters i.e. `-b1`, `-e18`, and `-i1` can be joined -into `-b1e18i1`. - - -#### The example of usage of static and dynamic ZSTD libraries with gcc/MinGW - -Use `cd example` and `make` to build `fullbench-dll` and `fullbench-lib`. -`fullbench-dll` uses a dynamic ZSTD library from the `dll` directory. -`fullbench-lib` uses a static ZSTD library from the `lib` directory. - - -#### Using ZSTD DLL with gcc/MinGW - -The header files from `include\` and the dynamic library `dll\libzstd.dll` -are required to compile a project using gcc/MinGW. -The dynamic library has to be added to linking options. -It means that if a project that uses ZSTD consists of a single `test-dll.c` -file it should be linked with `dll\libzstd.dll`. For example: -``` - gcc $(CFLAGS) -Iinclude\ test-dll.c -o test-dll dll\libzstd.dll -``` -The compiled executable will require ZSTD DLL which is available at `dll\libzstd.dll`. - - -#### The example of usage of static and dynamic ZSTD libraries with Visual C++ - -Open `example\fullbench-dll.sln` to compile `fullbench-dll` that uses a -dynamic ZSTD library from the `dll` directory. The solution works with Visual C++ -2010 or newer. When one will open the solution with Visual C++ newer than 2010 -then the solution will upgraded to the current version. - - -#### Using ZSTD DLL with Visual C++ - -The header files from `include\` and the import library `dll\libzstd.lib` -are required to compile a project using Visual C++. - -1. The path to header files should be added to `Additional Include Directories` that can - be found in project properties `C/C++` then `General`. -2. The import library has to be added to `Additional Dependencies` that can - be found in project properties `Linker` then `Input`. - If one will provide only the name `libzstd.lib` without a full path to the library - the directory has to be added to `Linker\General\Additional Library Directories`. - -The compiled executable will require ZSTD DLL which is available at `dll\libzstd.dll`. diff --git a/lib/dll/example/build_package.bat b/lib/dll/example/build_package.bat deleted file mode 100644 index cf351e762336..000000000000 --- a/lib/dll/example/build_package.bat +++ /dev/null @@ -1,18 +0,0 @@ -@ECHO OFF -MKDIR bin\dll bin\static bin\example bin\include -COPY tests\fullbench.c bin\example\ -COPY programs\datagen.c bin\example\ -COPY programs\datagen.h bin\example\ -COPY programs\util.h bin\example\ -COPY programs\platform.h bin\example\ -COPY lib\common\mem.h bin\example\ -COPY lib\common\zstd_errors.h bin\example\ -COPY lib\common\zstd_internal.h bin\example\ -COPY lib\common\error_private.h bin\example\ -COPY lib\zstd.h bin\include\ -COPY lib\libzstd.a bin\static\libzstd_static.lib -COPY lib\dll\libzstd.* bin\dll\ -COPY lib\dll\example\Makefile bin\example\ -COPY lib\dll\example\fullbench-dll.* bin\example\ -COPY lib\dll\example\README.md bin\ -COPY programs\zstd.exe bin\zstd.exe diff --git a/lib/dll/example/fullbench-dll.sln b/lib/dll/example/fullbench-dll.sln deleted file mode 100644 index ef8d4c024629..000000000000 --- a/lib/dll/example/fullbench-dll.sln +++ /dev/null @@ -1,25 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2012 for Windows Desktop -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench-dll", "fullbench-dll.vcxproj", "{13992FD2-077E-4954-B065-A428198201A9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.ActiveCfg = Debug|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.Build.0 = Debug|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.ActiveCfg = Debug|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.Build.0 = Debug|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.ActiveCfg = Release|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.Build.0 = Release|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Release|x64.ActiveCfg = Release|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/lib/dll/example/fullbench-dll.vcxproj b/lib/dll/example/fullbench-dll.vcxproj deleted file mode 100644 index fbea7832c806..000000000000 --- a/lib/dll/example/fullbench-dll.vcxproj +++ /dev/null @@ -1,181 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8} - Win32Proj - fullbench-dll - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - MultiByte - - - Application - true - MultiByte - - - Application - false - true - MultiByte - - - Application - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - false - ..\include - - - Console - true - $(SolutionDir)..\dll;%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - false - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - false - ..\include - - - Console - true - $(SolutionDir)..\dll;%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - ..\include - false - MultiThreaded - - - Console - true - true - true - $(SolutionDir)..\dll;%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - false - - - - - Level4 - - - MaxSpeed - true - true - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - false - ..\include - MultiThreaded - - - Console - true - true - true - $(SolutionDir)..\dll;%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/dll/libzstd.def b/lib/dll/libzstd.def deleted file mode 100644 index 51d0c192550f..000000000000 --- a/lib/dll/libzstd.def +++ /dev/null @@ -1,88 +0,0 @@ -LIBRARY libzstd.dll -EXPORTS - ZDICT_getDictID - ZDICT_getErrorName - ZDICT_isError - ZDICT_trainFromBuffer - ZSTD_CStreamInSize - ZSTD_CStreamOutSize - ZSTD_DStreamInSize - ZSTD_DStreamOutSize - ZSTD_adjustCParams - ZSTD_checkCParams - ZSTD_compress - ZSTD_compressBegin - ZSTD_compressBegin_advanced - ZSTD_compressBegin_usingDict - ZSTD_compressBlock - ZSTD_compressBound - ZSTD_compressCCtx - ZSTD_compressContinue - ZSTD_compressEnd - ZSTD_compressStream - ZSTD_compress_advanced - ZSTD_compress_usingCDict - ZSTD_compress_usingDict - ZSTD_copyCCtx - ZSTD_copyDCtx - ZSTD_createCCtx - ZSTD_createCCtx_advanced - ZSTD_createCDict - ZSTD_createCDict_advanced - ZSTD_createCStream - ZSTD_createCStream_advanced - ZSTD_createDCtx - ZSTD_createDCtx_advanced - ZSTD_createDDict - ZSTD_createDStream - ZSTD_createDStream_advanced - ZSTD_decompress - ZSTD_decompressBegin - ZSTD_decompressBegin_usingDict - ZSTD_decompressBlock - ZSTD_decompressContinue - ZSTD_decompressDCtx - ZSTD_decompressStream - ZSTD_decompress_usingDDict - ZSTD_decompress_usingDict - ZSTD_endStream - ZSTD_estimateCCtxSize - ZSTD_estimateDCtxSize - ZSTD_flushStream - ZSTD_freeCCtx - ZSTD_freeCDict - ZSTD_freeCStream - ZSTD_freeDCtx - ZSTD_freeDDict - ZSTD_freeDStream - ZSTD_getBlockSizeMax - ZSTD_getCParams - ZSTD_getDecompressedSize - ZSTD_findDecompressedSize - ZSTD_getFrameContentSize - ZSTD_getErrorName - ZSTD_getFrameParams - ZSTD_getParams - ZSTD_initCStream - ZSTD_initCStream_advanced - ZSTD_initCStream_usingCDict - ZSTD_initCStream_usingDict - ZSTD_initDStream - ZSTD_initDStream_usingDDict - ZSTD_initDStream_usingDict - ZSTD_insertBlock - ZSTD_isError - ZSTD_isFrame - ZSTD_maxCLevel - ZSTD_nextInputType - ZSTD_nextSrcSizeToDecompress - ZSTD_resetCStream - ZSTD_resetDStream - ZSTD_setDStreamParameter - ZSTD_sizeof_CCtx - ZSTD_sizeof_CDict - ZSTD_sizeof_CStream - ZSTD_sizeof_DCtx - ZSTD_sizeof_DDict - ZSTD_sizeof_DStream - ZSTD_versionNumber diff --git a/programs/fileio.c b/programs/fileio.c index e6481f1fa726..cabb6ec524a2 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -138,7 +138,7 @@ static U32 g_dictIDFlag = 1; void FIO_setDictIDFlag(unsigned dictIDFlag) { g_dictIDFlag = dictIDFlag; } static U32 g_checksumFlag = 1; void FIO_setChecksumFlag(unsigned checksumFlag) { g_checksumFlag = checksumFlag; } -static U32 g_removeSrcFile = 0; +static U32 g_removeSrcFile = 1; void FIO_setRemoveSrcFile(unsigned flag) { g_removeSrcFile = (flag>0); } static U32 g_memLimit = 0; void FIO_setMemLimit(unsigned memLimit) { g_memLimit = memLimit; } diff --git a/programs/windres/generate_res.bat b/programs/windres/generate_res.bat deleted file mode 100644 index 53891050ba29..000000000000 --- a/programs/windres/generate_res.bat +++ /dev/null @@ -1,11 +0,0 @@ -@echo off -REM http://stackoverflow.com/questions/708238/how-do-i-add-an-icon-to-a-mingw-gcc-compiled-executable - -where /q windres.exe -IF ERRORLEVEL 1 ( - ECHO The windres.exe is missing. Ensure it is installed and placed in your PATH. - EXIT /B -) ELSE ( - windres.exe -I ../lib -I windres -i windres/zstd.rc -O coff -F pe-x86-64 -o windres/zstd64.res - windres.exe -I ../lib -I windres -i windres/zstd.rc -O coff -F pe-i386 -o windres/zstd32.res -) diff --git a/programs/windres/verrsrc.h b/programs/windres/verrsrc.h deleted file mode 100644 index e282add025ac..000000000000 --- a/programs/windres/verrsrc.h +++ /dev/null @@ -1,8 +0,0 @@ -/* minimal set of defines required to generate zstd.res from zstd.rc */ - -#define VS_VERSION_INFO 1 - -#define VS_FFI_FILEFLAGSMASK 0x0000003FL -#define VOS_NT_WINDOWS32 0x00040004L -#define VFT_DLL 0x00000002L -#define VFT2_UNKNOWN 0x00000000L diff --git a/programs/windres/zstd.rc b/programs/windres/zstd.rc deleted file mode 100644 index 4a8aef3b1392..000000000000 --- a/programs/windres/zstd.rc +++ /dev/null @@ -1,51 +0,0 @@ -// 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, Facebook, Inc." - VALUE "FileDescription", "Zstandard - Fast and efficient compression algorithm" - VALUE "FileVersion", ZSTD_VERSION_STRING - VALUE "InternalName", "zstd.exe" - VALUE "LegalCopyright", "Copyright (c) 2013-present, Yann Collet, Facebook, Inc." - 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/programs/windres/zstd32.res b/programs/windres/zstd32.res deleted file mode 100644 index b5dd78db717ce9c7ddb2f69a9bc81804e51aedf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1044 zcmbW0K~ED=6ot>&38t=GvS87L3rV0UP!b>}8pVbt4HzX25)x9{QYO}EGaV9P-9 z{24A?Na8m9v*`zW&oKY+ zwPCmys{Jy%7=a$MSd=~&KC=SH*Y5F`Lun7h5${RPZ4oD>I&)j^bjti%Z?T#>&_3%X za|7GPP5ApZ<2OZNep0CCzH6RP4|03@`H3TdFIA#Qu?Db38mbR-taFV3esfGsb=9=Z zTh~iw)44?KD=;55RtNkQYC5d?PXFG0u_}%kI%}#G)(v*Lpw5UL>4W?1ysoN5e$ghp zQyshDChVBLF*+k6V&^}`pZXa+=0rW1S95mTspNYV7|wYjSR(A$_qw_6#Q7&Vuf+_h z!pP4{bwM^ZR4laxl-p~aT2~pY<&!!tcFv+Q*RHz#n zqphlA>S#OJ~IW3dvIvrWl2KkSPv5IARTDAYT4?CX6L9W4Wht+1<7h7eW zzAvA;9+A%*Vn_7l5|!!P-MHI3k%85CKIY#_&(?XDngsk2*88cd;?_z}xbM;-yLLAx bXz!q+=vg`ZZUF!1?E6r&e|mtY1{sCk^*z(_i+!V?OY; zVYpdU@60Ynpb-}DrSrmPR^a&REBh{mj_K>6Ga@2({$2d3pV4Ga)P(s{&Tc!Ee6Iq-K2HQogdO`{BiEfce?RB7m=0Cw z`gy4i$i~LF-agT^MNGo!g_cQ_+iRVgQW>n}lR7ST&Z07BuDc1kr4wEoSNcNCDyz1m zt*SlhX<4^Xk%D>Yt7wdzK9cDa9huZL`S*yiie-6Pwg0yd-#m}?T!Y;XtIeP Date: Sat, 15 Apr 2017 21:33:44 +0000 Subject: [PATCH 2/3] revert a change committed by accident: it is freebsd specific and should remain in contrib, not vendor --- programs/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/fileio.c b/programs/fileio.c index cabb6ec524a2..e6481f1fa726 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -138,7 +138,7 @@ static U32 g_dictIDFlag = 1; void FIO_setDictIDFlag(unsigned dictIDFlag) { g_dictIDFlag = dictIDFlag; } static U32 g_checksumFlag = 1; void FIO_setChecksumFlag(unsigned checksumFlag) { g_checksumFlag = checksumFlag; } -static U32 g_removeSrcFile = 1; +static U32 g_removeSrcFile = 0; void FIO_setRemoveSrcFile(unsigned flag) { g_removeSrcFile = (flag>0); } static U32 g_memLimit = 0; void FIO_setMemLimit(unsigned memLimit) { g_memLimit = memLimit; } From a490b59f8eab5dc0519e4ee6f9617b60910b86c5 Mon Sep 17 00:00:00 2001 From: bapt Date: Sat, 6 May 2017 10:17:59 +0000 Subject: [PATCH 3/3] Import Zstandard 1.2.0 Among changes: threading support is now default and supports freebsd --- .gitignore | 41 -- .travis.yml | 51 -- Makefile | 34 +- NEWS | 32 +- README.md | 13 +- appveyor.yml | 271 ++++--- circle.yml | 2 +- contrib/cleanTabs | 2 + contrib/pzstd/Options.cpp | 22 +- contrib/pzstd/utils/test/ThreadPoolTest.cpp | 6 +- contrib/pzstd/utils/test/WorkQueueTest.cpp | 7 + doc/educational_decoder/zstd_decompress.c | 243 ++++--- doc/images/Cspeed4.png | Bin 35361 -> 71276 bytes doc/images/Dspeed4.png | Bin 8984 -> 24692 bytes doc/images/dict-cr.png | Bin 23323 -> 90047 bytes doc/images/dict-cs.png | Bin 25052 -> 93837 bytes doc/images/dict-ds.png | Bin 27053 -> 89590 bytes doc/zstd_compression_format.md | 383 +++++----- doc/zstd_manual.html | 153 ++-- examples/simple_compression.c | 3 +- examples/streaming_compression.c | 3 +- examples/streaming_decompression.c | 3 +- lib/Makefile | 12 +- lib/README.md | 8 + lib/common/bitstream.h | 83 ++- lib/common/error_private.c | 3 +- lib/common/fse.h | 10 +- lib/common/huf.h | 61 +- lib/common/mem.h | 5 +- lib/common/zstd_errors.h | 1 + lib/common/zstd_internal.h | 5 +- lib/compress/fse_compress.c | 20 +- lib/compress/zstd_compress.c | 739 +++++++++++++------- lib/compress/zstd_opt.h | 10 +- lib/compress/zstdmt_compress.c | 68 +- lib/decompress/zstd_decompress.c | 334 +++------ lib/dictBuilder/cover.c | 47 +- lib/dictBuilder/zdict.c | 108 +-- lib/dictBuilder/zdict.h | 14 +- lib/legacy/zstd_v01.c | 2 +- lib/legacy/zstd_v02.c | 42 +- lib/legacy/zstd_v03.c | 40 +- lib/legacy/zstd_v04.c | 8 +- lib/legacy/zstd_v05.c | 4 +- lib/legacy/zstd_v06.c | 4 +- lib/zstd.h | 156 +++-- programs/Makefile | 102 ++- programs/README.md | 50 +- programs/bench.c | 41 +- programs/dibio.c | 7 +- programs/fileio.c | 271 +++++-- programs/fileio.h | 3 +- programs/platform.h | 19 +- programs/util.h | 245 ++++++- programs/zstd.1 | 640 ++++++++--------- programs/zstd.1.md | 343 +++++++++ programs/zstdcli.c | 220 ++++-- tests/Makefile | 22 +- tests/decodecorpus.c | 60 +- tests/fullbench.c | 4 +- tests/fuzzer.c | 264 +++++-- tests/paramgrill.c | 82 ++- tests/playTests.sh | 168 ++++- tests/test-zstd-speed.py | 20 +- tests/zbufftest.c | 2 +- tests/zstreamtest.c | 112 ++- zlibWrapper/examples/zwrapbench.c | 16 +- 67 files changed, 3685 insertions(+), 2059 deletions(-) delete mode 100644 .gitignore delete mode 100644 .travis.yml create mode 100755 contrib/cleanTabs create mode 100644 programs/zstd.1.md diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e02119883a7d..000000000000 --- a/.gitignore +++ /dev/null @@ -1,41 +0,0 @@ -# Object files -*.o -*.ko -*.dSYM - -# Libraries -*.lib -*.a - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -zstd -zstdmt -*.exe -*.out -*.app - -# Test artefacts -tmp* -dictionary* - -# Other files -.directory -_codelite/ -_zstdbench/ -.clang_complete -*.idea -*.swp -.DS_Store -googletest/ -*.d - -# Directories -bin/ -.buckd/ -buck-out/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3f98ea04dd75..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -# Long tests: run on commits to master branch/cron builds - -language: c -sudo: required -dist: trusty -matrix: - include: - # Ubuntu 14.04 - - env: Cmd='make gcc6install && CC=gcc-6 make clean uasan-test' - - env: Cmd='make gcc6install libc6install && CC=gcc-6 make clean uasan-test32' - - env: Cmd='make clang38install && CC=clang-3.8 make clean msan-test' - - env: Cmd='make clang38install && CC=clang-3.8 make clean tsan-test-zstream' - - env: Cmd='make valgrindinstall && make -C tests clean valgrindTest' - - - env: Cmd='make arminstall && make armtest' - - env: Cmd='make arminstall && make aarch64test' - - env: Cmd='make ppcinstall && make ppctest' - - env: Cmd='make ppcinstall && make ppc64test' - - - - env: Cmd='make gpp6install valgrindinstall && make -C zlibWrapper test && make -C zlibWrapper valgrindTest' - - env: Cmd='make -C tests versionsTest' - - env: Cmd='make gpp6install && cd contrib/pzstd && make test-pzstd && make test-pzstd32 && make test-pzstd-tsan && make test-pzstd-asan' - install: - - export CXX="g++-6" CC="gcc-6" - - env: Cmd='make gcc6install && CC=gcc-6 make uasan-test-zstd-nolegacy' - - env: Cmd='make gcc6install && CC=gcc-6 make uasan-test-zbuff' - - # OS X Mavericks - - env: Cmd="make gnu90build && make clean && make test && make clean && make travis-install" - os: osx - -git: - depth: 1 - -branches: - only: - - dev - - master - -script: - - JOB_NUMBER=$(echo $TRAVIS_JOB_NUMBER | sed -e 's:[0-9][0-9]*\.\(.*\):\1:') - - echo JOB_NUMBER=$JOB_NUMBER TRAVIS_BRANCH=$TRAVIS_BRANCH TRAVIS_EVENT_TYPE=$TRAVIS_EVENT_TYPE TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST - - export FUZZERTEST=-T5mn; - export ZSTREAM_TESTTIME=-T5mn; - export DECODECORPUS_TESTTIME=-T1mn; - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then - git fetch origin dev; - git checkout -f FETCH_HEAD; - fi; - sh -c "$Cmd" || travis_terminate 1; diff --git a/Makefile b/Makefile index 49f29d782276..54652665bc76 100644 --- a/Makefile +++ b/Makefile @@ -90,6 +90,10 @@ examples: manual: $(MAKE) -C contrib/gen_html $@ +.PHONY: cleanTabs +cleanTabs: + cd contrib; ./cleanTabs + .PHONY: clean clean: @$(MAKE) -C $(ZSTDDIR) $@ > $(VOID) @@ -105,9 +109,15 @@ clean: # make install is validated only for Linux, OSX, Hurd and some BSD targets #------------------------------------------------------------------------------ ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU FreeBSD DragonFly NetBSD)) -HOST_OS = POSIX -.PHONY: install uninstall travis-install clangtest gpptest armtest usan asan uasan +HOST_OS = POSIX +CMAKE_PARAMS = -DZSTD_BUILD_CONTRIB:BOOL=ON -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_ZLIB_SUPPORT:BOOL=ON -DZSTD_LZMA_SUPPORT:BOOL=ON + +.PHONY: list +list: + @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs + +.PHONY: install uninstall travis-install clangtest gpptest armtest usan asan uasan install: @$(MAKE) -C $(ZSTDDIR) $@ @$(MAKE) -C $(PRGDIR) $@ @@ -152,16 +162,16 @@ ppc64build: clean CC=powerpc-linux-gnu-gcc CFLAGS="-m64 -Werror" $(MAKE) allarch armfuzz: clean - CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static MOREFLAGS="-static" $(MAKE) -C $(TESTDIR) fuzztest + CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static MOREFLAGS="-static" FUZZER_FLAGS=--no-big-tests $(MAKE) -C $(TESTDIR) fuzztest aarch64fuzz: clean - CC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static MOREFLAGS="-static" $(MAKE) -C $(TESTDIR) fuzztest + CC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static MOREFLAGS="-static" FUZZER_FLAGS=--no-big-tests $(MAKE) -C $(TESTDIR) fuzztest ppcfuzz: clean - CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static MOREFLAGS="-static" $(MAKE) -C $(TESTDIR) fuzztest + CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static MOREFLAGS="-static" FUZZER_FLAGS=--no-big-tests $(MAKE) -C $(TESTDIR) fuzztest ppc64fuzz: clean - CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static MOREFLAGS="-m64 -static" $(MAKE) -C $(TESTDIR) fuzztest + CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static MOREFLAGS="-m64 -static" FUZZER_FLAGS=--no-big-tests $(MAKE) -C $(TESTDIR) fuzztest gpptest: clean CC=g++ $(MAKE) -C $(PRGDIR) all CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror" @@ -180,19 +190,19 @@ clangtest: clean armtest: clean $(MAKE) -C $(TESTDIR) datagen # use native, faster - $(MAKE) -C $(TESTDIR) test CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS="-Werror -static" + $(MAKE) -C $(TESTDIR) test CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS="-Werror -static" FUZZER_FLAGS=--no-big-tests aarch64test: $(MAKE) -C $(TESTDIR) datagen # use native, faster - $(MAKE) -C $(TESTDIR) test CC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static ZSTDRTTEST= MOREFLAGS="-Werror -static" + $(MAKE) -C $(TESTDIR) test CC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static ZSTDRTTEST= MOREFLAGS="-Werror -static" FUZZER_FLAGS=--no-big-tests ppctest: clean $(MAKE) -C $(TESTDIR) datagen # use native, faster - $(MAKE) -C $(TESTDIR) test CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static ZSTDRTTEST= MOREFLAGS="-Werror -Wno-attributes -static" + $(MAKE) -C $(TESTDIR) test CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static ZSTDRTTEST= MOREFLAGS="-Werror -Wno-attributes -static" FUZZER_FLAGS=--no-big-tests ppc64test: clean $(MAKE) -C $(TESTDIR) datagen # use native, faster - $(MAKE) -C $(TESTDIR) test CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static ZSTDRTTEST= MOREFLAGS="-m64 -static" + $(MAKE) -C $(TESTDIR) test CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static ZSTDRTTEST= MOREFLAGS="-m64 -static" FUZZER_FLAGS=--no-big-tests arm-ppc-compilation: $(MAKE) -C $(PRGDIR) clean zstd CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS="-Werror -static" @@ -263,7 +273,7 @@ endif ifneq (,$(filter MSYS%,$(shell uname))) HOST_OS = MSYS -CMAKE_PARAMS = -G"MSYS Makefiles" +CMAKE_PARAMS = -G"MSYS Makefiles" -DZSTD_MULTITHREAD_SUPPORT:BOOL=OFF -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON endif @@ -275,7 +285,7 @@ cmakebuild: cmake --version $(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 + cd $(BUILDIR)/cmake/build ; cmake -DCMAKE_INSTALL_PREFIX:PATH=~/install_test_dir $(CMAKE_PARAMS) .. ; $(MAKE) install ; $(MAKE) uninstall c90build: clean gcc -v diff --git a/NEWS b/NEWS index bbd9e1688386..7d9c9c94e186 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,25 @@ +v1.2.0 +cli : changed : Multithreading enabled by default (use target zstd-nomt or HAVE_THREAD=0 to disable) +cli : new : command -T0 means "detect and use nb of cores", by Sean Purcell +cli : new : zstdmt symlink hardwired to `zstd -T0` +cli : new : command --threads=# (#671) +cli : changed : cover dictionary builder by default, for improved quality, by Nick Terrell +cli : new : commands --train-cover and --train-legacy, to select dictionary algorithm and parameters +cli : experimental targets `zstd4` and `xzstd4`, with support for lz4 format, by Sean Purcell +cli : fix : does not output compressed data on console +cli : fix : ignore symbolic links unless --force specified, +API : breaking change : ZSTD_createCDict_advanced(), only use compressionParameters as argument +API : added : prototypes ZSTD_*_usingCDict_advanced(), for direct control over frameParameters. +API : improved: ZSTDMT_compressCCtx() reduced memory usage +API : fix : ZSTDMT_compressCCtx() now provides srcSize in header (#634) +API : fix : src size stored in frame header is controlled at end of frame +API : fix : enforced consistent rules for pledgedSrcSize==0 (#641) +API : fix : error code "GENERIC" replaced by "dstSizeTooSmall" when appropriate +build: improved cmake script, by @Majlen +build: enabled Multi-threading support for *BSD, by Baptiste Daroussin +tools: updated Paramgrill. Command -O# provides best parameters for sample and speed target. +new : contrib/linux-kernel version, by Nick Terrell + v1.1.4 cli : new : can compress in *.gz format, using --format=gzip command, by Przemyslaw Skibinski cli : new : advanced benchmark command --priority=rt @@ -5,13 +27,13 @@ cli : fix : write on sparse-enabled file systems in 32-bits mode, by @ds77 cli : fix : --rm remains silent when input is stdin cli : experimental : xzstd, with support for xz/lzma decoding, by Przemyslaw Skibinski speed : improved decompression speed in streaming mode for single shot scenarios (+5%) -memory : DDict (decompression dictionary) memory usage down from 150 KB to 20 KB -arch : 32-bits variant able to generate and decode very long matches (>32 MB), by Sean Purcell +memory: DDict (decompression dictionary) memory usage down from 150 KB to 20 KB +arch: 32-bits variant able to generate and decode very long matches (>32 MB), by Sean Purcell API : new : ZSTD_findFrameCompressedSize(), ZSTD_getFrameContentSize(), ZSTD_findDecompressedSize() API : changed : dropped support of legacy versions <= v0.3 (can be changed by modifying ZSTD_LEGACY_SUPPORT value) -build: new: meson build system in contrib/meson, by Dima Krasner -build: improved cmake script, by @Majlen -build: added -Wformat-security flag, as recommended by Padraig Brady +build : new: meson build system in contrib/meson, by Dima Krasner +build : improved cmake script, by @Majlen +build : added -Wformat-security flag, as recommended by Padraig Brady doc : new : educational decoder, by Sean Purcell v1.1.3 diff --git a/README.md b/README.md index 6de5a10790db..7caee5fd3f67 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,13 @@ you can consult a list of known ports on [Zstandard homepage](http://www.zstd.ne |dev | [![Build Status](https://travis-ci.org/facebook/zstd.svg?branch=dev)](https://travis-ci.org/facebook/zstd) | As a reference, several fast compression algorithms were tested and compared -on a server running Linux Mint Debian Edition (`Linux version 4.8.0-1-amd64`), +on a server running Linux Debian (`Linux version 4.8.0-1-amd64`), with a Core i7-6700K CPU @ 4.0GHz, -using [lzbench v1.6], an open-source in-memory benchmark by @inikep +using [lzbench], an open-source in-memory benchmark by @inikep compiled with GCC 6.3.0, on the [Silesia compression corpus]. -[lzbench v1.6]: https://github.com/inikep/lzbench +[lzbench]: https://github.com/inikep/lzbench [Silesia compression corpus]: http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia | Compressor name | Ratio | Compression| Decompress.| @@ -38,7 +38,12 @@ on the [Silesia compression corpus]. Zstd can also offer stronger compression ratios at the cost of compression speed. 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 server running Linux Debian (`Linux version 4.8.0-1-amd64`) +with a Core i7-6700K CPU @ 4.0GHz, +using [lzbench], an open-source in-memory benchmark by @inikep +compiled with GCC 6.3.0, +on the [Silesia compression corpus]. Compression Speed vs Ratio | Decompression Speed ---------------------------|-------------------- diff --git a/appveyor.yml b/appveyor.yml index 9507fec6e24c..67c4f72d7995 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,66 +1,103 @@ -version: 1.0.{build} -environment: - matrix: - - COMPILER: "gcc" - PLATFORM: "mingw64" - MAKE_PARAMS: '"make test && make lib && make -C tests test-symbols fullbench-dll fullbench-lib"' - - COMPILER: "gcc" - PLATFORM: "mingw32" - MAKE_PARAMS: '"make -C tests test-zstd test-fullbench test-fuzzer test-invalidDictionaries"' - - COMPILER: "gcc" - PLATFORM: "clang" - MAKE_PARAMS: '"make -C tests zstd fullbench fuzzer paramgrill datagen CC=clang MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion""' - - COMPILER: "visual" - CONFIGURATION: "Debug" - PLATFORM: "x64" - - COMPILER: "visual" - CONFIGURATION: "Debug" - PLATFORM: "Win32" - - COMPILER: "visual" - CONFIGURATION: "Release" - PLATFORM: "x64" - - COMPILER: "visual" - CONFIGURATION: "Release" - PLATFORM: "Win32" +- + version: 1.0.{build} + branches: + only: + - dev + - master + environment: + matrix: + - COMPILER: "gcc" + HOST: "mingw" + PLATFORM: "x64" + SCRIPT: "make allarch && make -C tests test-symbols fullbench-dll fullbench-lib" + ARTIFACT: "true" + BUILD: "true" + - COMPILER: "gcc" + HOST: "mingw" + PLATFORM: "x86" + SCRIPT: "make allarch" + ARTIFACT: "true" + BUILD: "true" + - COMPILER: "clang" + HOST: "mingw" + PLATFORM: "x64" + SCRIPT: "MOREFLAGS='--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion' make allarch" + BUILD: "true" -install: + - COMPILER: "gcc" + HOST: "mingw" + PLATFORM: "x64" + SCRIPT: "" + TEST: "cmake" + + - COMPILER: "gcc" + HOST: "mingw" + PLATFORM: "x64" + SCRIPT: "" + TEST: "pzstd" + + - COMPILER: "visual" + HOST: "visual" + PLATFORM: "x64" + CONFIGURATION: "Debug" + - COMPILER: "visual" + HOST: "visual" + PLATFORM: "Win32" + CONFIGURATION: "Debug" + - COMPILER: "visual" + HOST: "visual" + PLATFORM: "x64" + CONFIGURATION: "Release" + - COMPILER: "visual" + HOST: "visual" + PLATFORM: "Win32" + CONFIGURATION: "Release" + + install: - ECHO Installing %COMPILER% %PLATFORM% %CONFIGURATION% - - MKDIR bin - - if [%COMPILER%]==[gcc] SET PATH_ORIGINAL=%PATH% - - if [%COMPILER%]==[gcc] ( - SET "PATH_MINGW32=c:\MinGW\bin;c:\MinGW\usr\bin" && - SET "PATH_MINGW64=c:\msys64\mingw64\bin;c:\msys64\usr\bin" && - COPY C:\msys64\usr\bin\make.exe C:\MinGW\bin\make.exe && - COPY C:\MinGW\bin\gcc.exe C:\MinGW\bin\cc.exe - ) else ( - IF [%PLATFORM%]==[x64] (SET ADDITIONALPARAM=/p:LibraryPath="C:\Program Files\Microsoft SDKs\Windows\v7.1\lib\x64;c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64;C:\Program Files (x86)\Microsoft Visual Studio 10.0\;C:\Program Files (x86)\Microsoft Visual Studio 10.0\lib\amd64;") + - SET PATH_ORIGINAL=%PATH% + - if [%HOST%]==[mingw] ( + SET "PATH_MINGW32=C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin" && + SET "PATH_MINGW64=C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin" && + COPY C:\msys64\usr\bin\make.exe C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin\make.exe && + COPY C:\msys64\usr\bin\make.exe C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin\make.exe + ) + - IF [%HOST%]==[visual] IF [%PLATFORM%]==[x64] ( + SET ADDITIONALPARAM=/p:LibraryPath="C:\Program Files\Microsoft SDKs\Windows\v7.1\lib\x64;c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64;C:\Program Files (x86)\Microsoft Visual Studio 10.0\;C:\Program Files (x86)\Microsoft Visual Studio 10.0\lib\amd64;" ) -build_script: - - 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%]==[clang] SET PATH=%PATH_MINGW64%;%PATH_ORIGINAL% - - if [%COMPILER%]==[gcc] ( - ECHO *** && - ECHO *** Building %PLATFORM% && - ECHO *** && + build_script: + - if [%HOST%]==[mingw] ( + ( if [%PLATFORM%]==[x64] ( + SET "PATH=%PATH_MINGW64%;%PATH_ORIGINAL%" + ) else if [%PLATFORM%]==[x86] ( + SET "PATH=%PATH_MINGW32%;%PATH_ORIGINAL%" + ) ) + ) + - if [%HOST%]==[mingw] if [%BUILD%]==[true] ( make -v && - cc -v && - ECHO %MAKE_PARAMS% && - sh -c %MAKE_PARAMS% + sh -c "%COMPILER% -v" && + ECHO Building zlib to static link && + SET "CC=%COMPILER%" && + sh -c "cd .. && git clone --depth 1 --branch v1.2.11 https://github.com/madler/zlib" && + sh -c "cd ../zlib && make -f win32/Makefile.gcc libz.a" + ECHO Building zstd && + SET "CPPFLAGS=-I../../zlib" && + SET "LDFLAGS=../../zlib/libz.a" && + sh -c "%SCRIPT%" && + ( if [%COMPILER%]==[gcc] if [%ARTIFACT%]==[true] + lib\dll\example\build_package.bat && + make -C programs DEBUGFLAGS= clean zstd && + cp programs\zstd.exe zstd_%PLATFORM%.exe && + appveyor PushArtifact zstd_%PLATFORM%.exe && + cp programs\zstd.exe bin\zstd.exe && + make -C programs DEBUGFLAGS= clean zstdmt && + cp programs\zstd.exe bin\zstdmt.exe && + cd bin\ && 7z a -tzip zstd-win-release-%PLATFORM%.zip * && + appveyor PushArtifact zstd-win-release-%PLATFORM%.zip + ) ) - - if [%PLATFORM%]==[clang] COPY tests\fuzzer.exe tests\fuzzer_clang.exe - - 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] ( + - if [%HOST%]==[visual] ( ECHO *** && ECHO *** Building Visual Studio 2008 %PLATFORM%\%CONFIGURATION% in %APPVEYOR_BUILD_FOLDER% && ECHO *** && @@ -111,29 +148,26 @@ build_script: COPY build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe tests\ ) -test_script: + test_script: - ECHO Testing %COMPILER% %PLATFORM% %CONFIGURATION% - - SET FUZZERTEST=-T1mn - - if [%COMPILER%]==[gcc] if [%PLATFORM%]==[clang] ( - tests\fuzzer_clang.exe %FUZZERTEST% && - ECHO *** && - ECHO *** Building cmake for %PLATFORM% && - ECHO *** && + - SET "CC=gcc" + - SET "CXX=g++" + - if [%TEST%]==[cmake] ( mkdir build\cmake\build && cd build\cmake\build && cmake -G "Visual Studio 14 2015 Win64" .. && cd ..\..\.. && - make clean && - ECHO *** && - ECHO *** Building pzstd for %PLATFORM% && - ECHO *** && + make clean + ) + - if [%TEST%]==[pzstd] ( make -C contrib\pzstd googletest-mingw64 && make -C contrib\pzstd pzstd.exe && make -C contrib\pzstd tests && make -C contrib\pzstd check && make -C contrib\pzstd clean ) - - if [%COMPILER%]==[visual] if [%CONFIGURATION%]==[Release] ( + - SET "FUZZERTEST=-T30s" + - if [%HOST%]==[visual] if [%CONFIGURATION%]==[Release] ( CD tests && SET ZSTD=./zstd.exe && sh -e playTests.sh --test-large-data && @@ -146,33 +180,76 @@ test_script: fuzzer_VS2015_%PLATFORM%_Release.exe %FUZZERTEST% ) -branches: - only: - - dev - - master +- + version: 1.0.{build} + environment: + matrix: + - COMPILER: "gcc" + HOST: "mingw" + PLATFORM: "x64" + SCRIPT: "make allarch" + - COMPILER: "gcc" + HOST: "mingw" + PLATFORM: "x86" + SCRIPT: "make allarch" + - COMPILER: "clang" + HOST: "mingw" + PLATFORM: "x64" + SCRIPT: "MOREFLAGS='--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion' make allarch" -artifacts: - - path: bin\zstd.exe - - path: bin\zstd32.exe + - COMPILER: "visual" + HOST: "visual" + PLATFORM: "x64" + CONFIGURATION: "Debug" + - COMPILER: "visual" + HOST: "visual" + PLATFORM: "Win32" + CONFIGURATION: "Debug" + - COMPILER: "visual" + HOST: "visual" + PLATFORM: "x64" + CONFIGURATION: "Release" + - COMPILER: "visual" + HOST: "visual" + PLATFORM: "Win32" + CONFIGURATION: "Release" -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 + install: + - ECHO Installing %COMPILER% %PLATFORM% %CONFIGURATION% + - SET PATH_ORIGINAL=%PATH% + - if [%HOST%]==[mingw] ( + SET "PATH_MINGW32=C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin" && + SET "PATH_MINGW64=C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin" && + COPY C:\msys64\usr\bin\make.exe C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin\make.exe && + COPY C:\msys64\usr\bin\make.exe C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin\make.exe + ) + - IF [%HOST%]==[visual] IF [%PLATFORM%]==[x64] ( + SET ADDITIONALPARAM=/p:LibraryPath="C:\Program Files\Microsoft SDKs\Windows\v7.1\lib\x64;c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64;C:\Program Files (x86)\Microsoft Visual Studio 10.0\;C:\Program Files (x86)\Microsoft Visual Studio 10.0\lib\amd64;" + ) + + build_script: + - ECHO Building %COMPILER% %PLATFORM% %CONFIGURATION% + - if [%HOST%]==[mingw] ( + ( if [%PLATFORM%]==[x64] ( + SET "PATH=%PATH_MINGW64%;%PATH_ORIGINAL%" + ) else if [%PLATFORM%]==[x86] ( + SET "PATH=%PATH_MINGW32%;%PATH_ORIGINAL%" + ) ) && + make -v && + sh -c "%COMPILER% -v" && + set "CC=%COMPILER%" && + sh -c "%SCRIPT%" + ) + - if [%HOST%]==[visual] ( + ECHO *** && + ECHO *** Building Visual Studio 2015 %PLATFORM%\%CONFIGURATION% && + ECHO *** && + 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\ + ) diff --git a/circle.yml b/circle.yml index 298569d14551..218e33bfc333 100644 --- a/circle.yml +++ b/circle.yml @@ -3,7 +3,7 @@ dependencies: - sudo dpkg --add-architecture i386 - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; sudo apt-get -y -qq update - sudo apt-get -y install gcc-powerpc-linux-gnu gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross - - sudo apt-get -y install libstdc++-6-dev clang gcc g++ gcc-5 gcc-6 + - sudo apt-get -y install libstdc++-6-dev clang gcc g++ gcc-5 gcc-6 zlib1g-dev liblzma-dev - sudo apt-get -y install linux-libc-dev:i386 libc6-dev-i386 test: diff --git a/contrib/cleanTabs b/contrib/cleanTabs new file mode 100755 index 000000000000..215913a90ace --- /dev/null +++ b/contrib/cleanTabs @@ -0,0 +1,2 @@ +#!/bin/sh +sed -i '' $'s/\t/ /g' ../lib/**/*.{h,c} ../programs/*.{h,c} ../tests/*.c ./**/*.{h,cpp} ../examples/*.c ../zlibWrapper/*.{h,c} diff --git a/contrib/pzstd/Options.cpp b/contrib/pzstd/Options.cpp index a0d969393c9b..1f53f2bff78a 100644 --- a/contrib/pzstd/Options.cpp +++ b/contrib/pzstd/Options.cpp @@ -91,7 +91,7 @@ void usage() { 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, " -f, --force : overwrite output without prompting, (de)compress links\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"); @@ -121,6 +121,7 @@ Options::Status Options::parse(int argc, const char **argv) { bool recursive = false; bool ultra = false; bool forceStdout = false; + bool followLinks = false; // Local copy of input files, which are pointers into argv. std::vector localInputFiles; for (int i = 1; i < argc; ++i) { @@ -255,6 +256,7 @@ Options::Status Options::parse(int argc, const char **argv) { case 'f': overwrite = true; forceStdout = true; + followLinks = true; break; case 't': test = true; @@ -328,13 +330,29 @@ Options::Status Options::parse(int argc, const char **argv) { } } + g_utilDisplayLevel = verbosity; + // Remove local input files that are symbolic links + if (!followLinks) { + std::remove_if(localInputFiles.begin(), localInputFiles.end(), + [&](const char *path) { + bool isLink = UTIL_isLink(path); + if (isLink && verbosity >= 2) { + std::fprintf( + stderr, + "Warning : %s is symbolic link, ignoring\n", + path); + } + return isLink; + }); + } + // 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); + &scratchBuffer, &numFiles, followLinks); if (files == nullptr) { std::fprintf(stderr, "Error traversing directories\n"); return Status::Failure; diff --git a/contrib/pzstd/utils/test/ThreadPoolTest.cpp b/contrib/pzstd/utils/test/ThreadPoolTest.cpp index 1d857aae808d..89085afd434c 100644 --- a/contrib/pzstd/utils/test/ThreadPoolTest.cpp +++ b/contrib/pzstd/utils/test/ThreadPoolTest.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -34,16 +35,19 @@ TEST(ThreadPool, AllJobsFinished) { std::atomic numFinished{0}; std::atomic start{false}; { + std::cerr << "Creating executor" << std::endl; ThreadPool executor(5); for (int i = 0; i < 10; ++i) { executor.add([ &numFinished, &start ] { while (!start.load()) { - // spin + std::this_thread::yield(); } ++numFinished; }); } + std::cerr << "Starting" << std::endl; start.store(true); + std::cerr << "Finishing" << std::endl; } EXPECT_EQ(10, numFinished.load()); } diff --git a/contrib/pzstd/utils/test/WorkQueueTest.cpp b/contrib/pzstd/utils/test/WorkQueueTest.cpp index 7f58ccb3f199..8caf170d2948 100644 --- a/contrib/pzstd/utils/test/WorkQueueTest.cpp +++ b/contrib/pzstd/utils/test/WorkQueueTest.cpp @@ -10,6 +10,7 @@ #include "utils/WorkQueue.h" #include +#include #include #include #include @@ -201,11 +202,13 @@ TEST(WorkQueue, BoundedSizeMPMC) { WorkQueue queue(10); std::vector results(200, -1); std::mutex mutex; + std::cerr << "Creating popperThreads" << std::endl; std::vector popperThreads; for (int i = 0; i < 4; ++i) { popperThreads.emplace_back(Popper{&queue, results.data(), &mutex}); } + std::cerr << "Creating pusherThreads" << std::endl; std::vector pusherThreads; for (int i = 0; i < 2; ++i) { auto min = i * 100; @@ -218,15 +221,19 @@ TEST(WorkQueue, BoundedSizeMPMC) { }); } + std::cerr << "Joining pusherThreads" << std::endl; for (auto& thread : pusherThreads) { thread.join(); } + std::cerr << "Finishing queue" << std::endl; queue.finish(); + std::cerr << "Joining popperThreads" << std::endl; for (auto& thread : popperThreads) { thread.join(); } + std::cerr << "Inspecting results" << std::endl; for (int i = 0; i < 200; ++i) { EXPECT_EQ(i, results[i]); } diff --git a/doc/educational_decoder/zstd_decompress.c b/doc/educational_decoder/zstd_decompress.c index ae4eaa81c6ae..7c8d8114d401 100644 --- a/doc/educational_decoder/zstd_decompress.c +++ b/doc/educational_decoder/zstd_decompress.c @@ -27,16 +27,19 @@ size_t ZSTD_decompress_with_dict(void *const dst, const size_t dst_len, /// Get the decompressed size of an input stream so memory can be allocated in /// advance +/// Returns -1 if the size can't be determined size_t ZSTD_get_decompressed_size(const void *const src, const size_t src_len); /******* UTILITY MACROS AND TYPES *********************************************/ -// Max block size decompressed size is 128 KB and literal blocks must be smaller -// than that +// Max block size decompressed size is 128 KB and literal blocks can't be +// larger than their block #define MAX_LITERALS_SIZE ((size_t)128 * 1024) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) +/// This decoder calls exit(1) when it encounters an error, however a production +/// library should propagate error codes #define ERROR(s) \ do { \ fprintf(stderr, "Error: %s\n", s); \ @@ -67,29 +70,31 @@ typedef int64_t i64; /// decompression functions. /*** IO STREAM OPERATIONS *************/ -/// These structs are the interface for IO, and do bounds checking on all -/// operations. They should be used opaquely to ensure safety. -/// Output is always done byte-by-byte +/// ostream_t/istream_t are used to wrap the pointers/length data passed into +/// ZSTD_decompress, so that all IO operations are safely bounds checked +/// They are written/read forward, and reads are treated as little-endian +/// They should be used opaquely to ensure safety typedef struct { u8 *ptr; size_t len; } ostream_t; -/// Input often reads a few bits at a time, so maintain an internal offset typedef struct { const u8 *ptr; - int bit_offset; size_t len; + + // Input often reads a few bits at a time, so maintain an internal offset + int bit_offset; } istream_t; /// The following two functions are the only ones that allow the istream to be /// non-byte aligned /// Reads `num` bits from a bitstream, and updates the internal offset -static inline u64 IO_read_bits(istream_t *const in, const int num); -/// Rewinds the stream by `num` bits -static inline void IO_rewind_bits(istream_t *const in, const int num); +static inline u64 IO_read_bits(istream_t *const in, const int num_bits); +/// Backs-up the stream by `num` bits so they can be read again +static inline void IO_rewind_bits(istream_t *const in, const int num_bits); /// If the remaining bits in a byte will be unused, advance to the end of the /// byte static inline void IO_align_stream(istream_t *const in); @@ -101,30 +106,31 @@ static inline void IO_write_byte(ostream_t *const out, u8 symb); /// be byte aligned. static inline size_t IO_istream_len(const istream_t *const in); -/// Returns a pointer where `len` bytes can be read, and advances the internal -/// state. The stream must be byte aligned. +/// Advances the stream by `len` bytes, and returns a pointer to the chunk that +/// was skipped. The stream must be byte aligned. static inline const u8 *IO_read_bytes(istream_t *const in, size_t len); -/// Returns a pointer where `len` bytes can be written, and advances the internal -/// state. The stream must be byte aligned. +/// Advances the stream by `len` bytes, and returns a pointer to the chunk that +/// was skipped so it can be written to. static inline u8 *IO_write_bytes(ostream_t *const out, size_t len); /// Advance the inner state by `len` bytes. The stream must be byte aligned. static inline void IO_advance_input(istream_t *const in, size_t len); -/// Returns an `ostream_t` constructed from the given pointer and length +/// Returns an `ostream_t` constructed from the given pointer and length. static inline ostream_t IO_make_ostream(u8 *out, size_t len); -/// Returns an `istream_t` constructed from the given pointer and length +/// Returns an `istream_t` constructed from the given pointer and length. static inline istream_t IO_make_istream(const u8 *in, size_t len); -/// Returns an `istream_t` with the same base as `in`, and length `len` -/// Then, advance `in` to account for the consumed bytes -/// `in` must be byte aligned +/// Returns an `istream_t` with the same base as `in`, and length `len`. +/// Then, advance `in` to account for the consumed bytes. +/// `in` must be byte aligned. static inline istream_t IO_make_sub_istream(istream_t *const in, size_t len); /*** END IO STREAM OPERATIONS *********/ /*** BITSTREAM OPERATIONS *************/ -/// Read `num` bits (up to 64) from `src + offset`, where `offset` is in bits -static inline u64 read_bits_LE(const u8 *src, const int num, +/// Read `num` bits (up to 64) from `src + offset`, where `offset` is in bits, +/// and return them interpreted as a little-endian unsigned integer. +static inline u64 read_bits_LE(const u8 *src, const int num_bits, const size_t offset); /// Read bits from the end of a HUF or FSE bitstream. `offset` is in bits, so @@ -136,9 +142,8 @@ static inline u64 STREAM_read_bits(const u8 *src, const int bits, /*** END BITSTREAM OPERATIONS *********/ /*** BIT COUNTING OPERATIONS **********/ -/// Returns `x`, where `2^x` is the largest power of 2 less than or equal to -/// `num`, or `-1` if `num == 0`. -static inline int log2inf(const u64 num); +/// Returns the index of the highest set bit in `num`, or `-1` if `num == 0` +static inline int highest_set_bit(const u64 num); /*** END BIT COUNTING OPERATIONS ******/ /*** HUFFMAN PRIMITIVES ***************/ @@ -384,8 +389,8 @@ size_t ZSTD_decompress_with_dict(void *const dst, const size_t dst_len, parse_dictionary(&parsed_dict, (const u8 *)dict, dict_len); } - istream_t in = {(const u8 *)src, 0, src_len}; - ostream_t out = {(u8 *)dst, dst_len}; + istream_t in = IO_make_istream(src, src_len); + ostream_t out = IO_make_ostream(dst, dst_len); // "A content compressed by Zstandard is transformed into a Zstandard frame. // Multiple frames can be appended into a single file or stream. A frame is @@ -633,6 +638,7 @@ static void frame_context_apply_dict(frame_context_t *const ctx, FSE_copy_dtable(&ctx->of_dtable, &dict->of_dtable); FSE_copy_dtable(&ctx->ml_dtable, &dict->ml_dtable); + // Copy the repeated offsets memcpy(ctx->previous_offsets, dict->previous_offsets, sizeof(ctx->previous_offsets)); } @@ -668,7 +674,7 @@ static void decompress_data(frame_context_t *const ctx, ostream_t *const out, // number of bytes to read and copy." const u8 *const read_ptr = IO_read_bytes(in, block_len); u8 *const write_ptr = IO_write_bytes(out, block_len); - // + // Copy the raw data into the output memcpy(write_ptr, read_ptr, block_len); @@ -682,7 +688,7 @@ static void decompress_data(frame_context_t *const ctx, ostream_t *const out, const u8 *const read_ptr = IO_read_bytes(in, 1); u8 *const write_ptr = IO_write_bytes(out, block_len); - // Copy `block_len` copies of `streams->src[0]` to the output + // Copy `block_len` copies of `read_ptr[0]` to the output memset(write_ptr, read_ptr[0], block_len); ctx->current_total_output += block_len; @@ -751,7 +757,7 @@ static size_t decode_literals_compressed(frame_context_t *const ctx, u8 **const literals, const int block_type, const int size_format); -static void decode_huf_table(istream_t *const in, HUF_dtable *const dtable); +static void decode_huf_table(HUF_dtable *const dtable, istream_t *const in); static void fse_decode_hufweights(ostream_t *weights, istream_t *const in, int *const num_symbs); @@ -894,12 +900,12 @@ static size_t decode_literals_compressed(frame_context_t *const ctx, istream_t huf_stream = IO_make_sub_istream(in, compressed_size); if (block_type == 2) { - // Decode provided Huffman table + // Decode the provided Huffman table // "This section is only present when Literals_Block_Type type is // Compressed_Literals_Block (2)." HUF_free_dtable(&ctx->literals_dtable); - decode_huf_table(&huf_stream, &ctx->literals_dtable); + decode_huf_table(&ctx->literals_dtable, &huf_stream); } else { // If the previous Huffman table is being repeated, ensure it exists if (!ctx->literals_dtable.symbols) { @@ -922,13 +928,13 @@ static size_t decode_literals_compressed(frame_context_t *const ctx, } // Decode the Huffman table description -static void decode_huf_table(istream_t *const in, HUF_dtable *const dtable) { - const u8 header = IO_read_bits(in, 8); - +static void decode_huf_table(HUF_dtable *const dtable, istream_t *const in) { // "All literal values from zero (included) to last present one (excluded) // are represented by Weight with values from 0 to Max_Number_of_Bits." // "This is a single byte value (0-255), which describes how to decode the list of weights." + const u8 header = IO_read_bits(in, 8); + u8 weights[HUF_MAX_SYMBS]; memset(weights, 0, sizeof(weights)); @@ -997,7 +1003,7 @@ typedef struct { u16 ll_state; u16 of_state; u16 ml_state; -} sequence_state_t; +} sequence_states_t; /// Different modes to signal to decode_seq_tables what to do typedef enum { @@ -1052,10 +1058,10 @@ static void decompress_sequences(frame_context_t *const ctx, istream_t *const in, sequence_command_t *const sequences, const size_t num_sequences); -static sequence_command_t decode_sequence(sequence_state_t *const state, +static sequence_command_t decode_sequence(sequence_states_t *const state, const u8 *const src, i64 *const offset); -static void decode_seq_table(istream_t *const in, FSE_dtable *const table, +static void decode_seq_table(FSE_dtable *const table, istream_t *const in, const seq_part_t type, const seq_mode_t mode); static size_t decode_sequences(frame_context_t *const ctx, istream_t *in, @@ -1131,34 +1137,33 @@ static void decompress_sequences(frame_context_t *const ctx, istream_t *in, // Offsets // Match Lengths" // Update the tables we have stored in the context - decode_seq_table(in, &ctx->ll_dtable, seq_literal_length, + decode_seq_table(&ctx->ll_dtable, in, seq_literal_length, (compression_modes >> 6) & 3); - decode_seq_table(in, &ctx->of_dtable, seq_offset, + decode_seq_table(&ctx->of_dtable, in, seq_offset, (compression_modes >> 4) & 3); - decode_seq_table(in, &ctx->ml_dtable, seq_match_length, + decode_seq_table(&ctx->ml_dtable, in, seq_match_length, (compression_modes >> 2) & 3); - // Check to make sure none of the tables are uninitialized - if (!ctx->ll_dtable.symbols || !ctx->of_dtable.symbols || - !ctx->ml_dtable.symbols) { - CORRUPTION(); + + sequence_states_t states; + + // Initialize the decoding tables + { + states.ll_table = ctx->ll_dtable; + states.of_table = ctx->of_dtable; + states.ml_table = ctx->ml_dtable; } - sequence_state_t state; - // Copy the context's tables into the local state - memcpy(&state.ll_table, &ctx->ll_dtable, sizeof(FSE_dtable)); - memcpy(&state.of_table, &ctx->of_dtable, sizeof(FSE_dtable)); - memcpy(&state.ml_table, &ctx->ml_dtable, sizeof(FSE_dtable)); - - size_t len = IO_istream_len(in); + const size_t len = IO_istream_len(in); const u8 *const src = IO_read_bytes(in, len); // "After writing the last bit containing information, the compressor writes // a single 1-bit and then fills the byte with 0-7 0 bits of padding." - const int padding = 8 - log2inf(src[len - 1]); - i64 offset = len * 8 - padding; + const int padding = 8 - highest_set_bit(src[len - 1]); + // The offset starts at the end because FSE streams are read backwards + i64 bit_offset = len * 8 - padding; // "The bitstream starts with initial state values, each using the required // number of bits in their respective accuracy, decoded previously from @@ -1166,24 +1171,22 @@ static void decompress_sequences(frame_context_t *const ctx, istream_t *in, // // It starts by Literals_Length_State, followed by Offset_State, and finally // Match_Length_State." - FSE_init_state(&state.ll_table, &state.ll_state, src, &offset); - FSE_init_state(&state.of_table, &state.of_state, src, &offset); - FSE_init_state(&state.ml_table, &state.ml_state, src, &offset); + FSE_init_state(&states.ll_table, &states.ll_state, src, &bit_offset); + FSE_init_state(&states.of_table, &states.of_state, src, &bit_offset); + FSE_init_state(&states.ml_table, &states.ml_state, src, &bit_offset); for (size_t i = 0; i < num_sequences; i++) { // Decode sequences one by one - sequences[i] = decode_sequence(&state, src, &offset); + sequences[i] = decode_sequence(&states, src, &bit_offset); } - if (offset != 0) { + if (bit_offset != 0) { CORRUPTION(); } - - // Don't free tables so they can be used in the next block } // Decode a single sequence and update the state -static sequence_command_t decode_sequence(sequence_state_t *const state, +static sequence_command_t decode_sequence(sequence_states_t *const states, const u8 *const src, i64 *const offset) { // "Each symbol is a code in its own context, which specifies Baseline and @@ -1191,9 +1194,9 @@ static sequence_command_t decode_sequence(sequence_state_t *const state, // additional bits in the same bitstream." // Decode symbols, but don't update states - const u8 of_code = FSE_peek_symbol(&state->of_table, state->of_state); - const u8 ll_code = FSE_peek_symbol(&state->ll_table, state->ll_state); - const u8 ml_code = FSE_peek_symbol(&state->ml_table, state->ml_state); + const u8 of_code = FSE_peek_symbol(&states->of_table, states->of_state); + const u8 ll_code = FSE_peek_symbol(&states->ll_table, states->ll_state); + const u8 ml_code = FSE_peek_symbol(&states->ml_table, states->ml_state); // Offset doesn't need a max value as it's not decoded using a table if (ll_code > SEQ_MAX_CODES[seq_literal_length] || @@ -1221,17 +1224,18 @@ static sequence_command_t decode_sequence(sequence_state_t *const state, // then Offset_State." // If the stream is complete don't read bits to update state if (*offset != 0) { - FSE_update_state(&state->ll_table, &state->ll_state, src, offset); - FSE_update_state(&state->ml_table, &state->ml_state, src, offset); - FSE_update_state(&state->of_table, &state->of_state, src, offset); + FSE_update_state(&states->ll_table, &states->ll_state, src, offset); + FSE_update_state(&states->ml_table, &states->ml_state, src, offset); + FSE_update_state(&states->of_table, &states->of_state, src, offset); } return seq; } /// Given a sequence part and table mode, decode the FSE distribution -static void decode_seq_table(istream_t *const in, FSE_dtable *const table, - const seq_part_t type, const seq_mode_t mode) { +/// Errors if the mode is `seq_repeat` without a pre-existing table in `table` +static void decode_seq_table(FSE_dtable *const table, istream_t *const in, + const seq_part_t type, const seq_mode_t mode) { // Constant arrays indexed by seq_part_t const i16 *const default_distributions[] = {SEQ_LITERAL_LENGTH_DEFAULT_DIST, SEQ_OFFSET_DEFAULT_DIST, @@ -1272,12 +1276,17 @@ static void decode_seq_table(istream_t *const in, FSE_dtable *const table, // "Repeat_Mode : re-use distribution table from previous compressed // block." // Nothing to do here, table will be unchanged + if (!table->symbols) { + // This mode is invalid if we don't already have a table + CORRUPTION(); + } break; default: // Impossible, as mode is from 0-3 IMPOSSIBLE(); break; } + } /******* END SEQUENCE DECODING ************************************************/ @@ -1296,6 +1305,8 @@ static void execute_sequences(frame_context_t *const ctx, ostream_t *const out, const sequence_command_t seq = sequences[i]; { + // If the sequence asks for more literals than are left, the + // sequence must be corrupted if (seq.literal_length > IO_istream_len(&litstream)) { CORRUPTION(); } @@ -1336,7 +1347,8 @@ static void execute_sequences(frame_context_t *const ctx, ostream_t *const out, // as per the exception listed above offset = idx < 3 ? offset_hist[idx] : offset_hist[0] - 1; - // If idx == 1 we don't need to modify offset_hist[2] + // If idx == 1 we don't need to modify offset_hist[2], since + // we're using the second-most recent code if (idx > 1) { offset_hist[2] = offset_hist[1]; } @@ -1344,6 +1356,8 @@ static void execute_sequences(frame_context_t *const ctx, ostream_t *const out, offset_hist[0] = offset; } } else { + // When it's not a repeat offset: + // "if (Offset_Value > 3) offset = Offset_Value - 3;" offset = seq.offset - 3; // Shift back history @@ -1391,11 +1405,11 @@ static void execute_sequences(frame_context_t *const ctx, ostream_t *const out, total_output += seq.match_length; } + // Copy any leftover literals { size_t len = IO_istream_len(&litstream); u8 *const write_ptr = IO_write_bytes(out, len); const u8 *const read_ptr = IO_read_bytes(&litstream, len); - // Copy any leftover literals memcpy(write_ptr, read_ptr, len); total_output += len; @@ -1517,10 +1531,10 @@ static void parse_dictionary(dictionary_t *const dict, const u8 *src, // recent offsets (instead of using {1,4,8}), stored in order, 4-bytes // little-endian each, for a total of 12 bytes. Each recent offset must have // a value < dictionary size." - decode_huf_table(&in, &dict->literals_dtable); - decode_seq_table(&in, &dict->of_dtable, seq_offset, seq_fse); - decode_seq_table(&in, &dict->ml_dtable, seq_match_length, seq_fse); - decode_seq_table(&in, &dict->ll_dtable, seq_literal_length, seq_fse); + decode_huf_table(&dict->literals_dtable, &in); + decode_seq_table(&dict->of_dtable, &in, seq_offset, seq_fse); + decode_seq_table(&dict->ml_dtable, &in, seq_match_length, seq_fse); + decode_seq_table(&dict->ll_dtable, &in, seq_literal_length, seq_fse); // Read in the previous offset history dict->previous_offsets[0] = IO_read_bits(&in, 32); @@ -1571,20 +1585,20 @@ static void free_dictionary(dictionary_t *const dict) { /******* IO STREAM OPERATIONS *************************************************/ #define UNALIGNED() ERROR("Attempting to operate on a non-byte aligned stream") /// Reads `num` bits from a bitstream, and updates the internal offset -static inline u64 IO_read_bits(istream_t *const in, const int num) { - if (num > 64 || num <= 0) { +static inline u64 IO_read_bits(istream_t *const in, const int num_bits) { + if (num_bits > 64 || num_bits <= 0) { ERROR("Attempt to read an invalid number of bits"); } - const size_t bytes = (num + in->bit_offset + 7) / 8; - const size_t full_bytes = (num + in->bit_offset) / 8; + const size_t bytes = (num_bits + in->bit_offset + 7) / 8; + const size_t full_bytes = (num_bits + in->bit_offset) / 8; if (bytes > in->len) { INP_SIZE(); } - const u64 result = read_bits_LE(in->ptr, num, in->bit_offset); + const u64 result = read_bits_LE(in->ptr, num_bits, in->bit_offset); - in->bit_offset = (num + in->bit_offset) % 8; + in->bit_offset = (num_bits + in->bit_offset) % 8; in->ptr += full_bytes; in->len -= full_bytes; @@ -1593,16 +1607,21 @@ static inline u64 IO_read_bits(istream_t *const in, const int num) { /// If a non-zero number of bits have been read from the current byte, advance /// the offset to the next byte -static inline void IO_rewind_bits(istream_t *const in, int num) { - if (num < 0) { +static inline void IO_rewind_bits(istream_t *const in, int num_bits) { + if (num_bits < 0) { ERROR("Attempting to rewind stream by a negative number of bits"); } - const int new_offset = in->bit_offset - num; - const i64 bytes = (new_offset - 7) / 8; + // move the offset back by `num_bits` bits + const int new_offset = in->bit_offset - num_bits; + // determine the number of whole bytes we have to rewind, rounding up to an + // integer number (e.g. if `new_offset == -5`, `bytes == 1`) + const i64 bytes = -(new_offset - 7) / 8; - in->ptr += bytes; - in->len -= bytes; + in->ptr -= bytes; + in->len += bytes; + // make sure the resulting `bit_offset` is positive, as mod in C does not + // convert numbers from negative to positive (e.g. -22 % 8 == -6) in->bit_offset = ((new_offset % 8) + 8) % 8; } @@ -1683,33 +1702,26 @@ static inline ostream_t IO_make_ostream(u8 *out, size_t len) { /// Returns an `istream_t` constructed from the given pointer and length static inline istream_t IO_make_istream(const u8 *in, size_t len) { - return (istream_t) { in, 0, len }; + return (istream_t) { in, len, 0 }; } /// Returns an `istream_t` with the same base as `in`, and length `len` /// Then, advance `in` to account for the consumed bytes /// `in` must be byte aligned static inline istream_t IO_make_sub_istream(istream_t *const in, size_t len) { - if (len > in->len) { - INP_SIZE(); - } - if (in->bit_offset != 0) { - UNALIGNED(); - } - const istream_t sub = { in->ptr, in->bit_offset, len }; + // Consume `len` bytes of the parent stream + const u8 *const ptr = IO_read_bytes(in, len); - in->ptr += len; - in->len -= len; - - return sub; + // Make a substream using the pointer to those `len` bytes + return IO_make_istream(ptr, len); } /******* END IO STREAM OPERATIONS *********************************************/ /******* BITSTREAM OPERATIONS *************************************************/ /// Read `num` bits (up to 64) from `src + offset`, where `offset` is in bits -static inline u64 read_bits_LE(const u8 *src, const int num, +static inline u64 read_bits_LE(const u8 *src, const int num_bits, const size_t offset) { - if (num > 64) { + if (num_bits > 64) { ERROR("Attempt to read an invalid number of bits"); } @@ -1719,10 +1731,10 @@ static inline u64 read_bits_LE(const u8 *src, const int num, u64 res = 0; int shift = 0; - int left = num; + int left = num_bits; while (left > 0) { u64 mask = left >= 8 ? 0xff : (((u64)1 << left) - 1); - // Dead the next byte, shift it to account for the offset, and then mask + // Read the next byte, shift it to account for the offset, and then mask // out the top part if we don't need all the bits res += (((u64)*src++ >> bit_offset) & mask) << shift; shift += 8 - bit_offset; @@ -1761,7 +1773,7 @@ static inline u64 STREAM_read_bits(const u8 *const src, const int bits, /******* BIT COUNTING OPERATIONS **********************************************/ /// Returns `x`, where `2^x` is the largest power of 2 less than or equal to /// `num`, or `-1` if `num == 0`. -static inline int log2inf(const u64 num) { +static inline int highest_set_bit(const u64 num) { for (int i = 63; i >= 0; i--) { if (((u64)1 << i) <= num) { return i; @@ -1813,17 +1825,18 @@ static size_t HUF_decompress_1stream(const HUF_dtable *const dtable, // final-bit-flag. Consequently, a last byte of 0 is not possible. And the // final-bit-flag itself is not part of the useful bitstream. Hence, the // last byte contains between 0 and 7 useful bits." - const int padding = 8 - log2inf(src[len - 1]); + const int padding = 8 - highest_set_bit(src[len - 1]); - i64 offset = len * 8 - padding; + // Offset starts at the end because HUF streams are read backwards + i64 bit_offset = len * 8 - padding; u16 state; - HUF_init_state(dtable, &state, src, &offset); + HUF_init_state(dtable, &state, src, &bit_offset); size_t symbols_written = 0; - while (offset > -dtable->max_bits) { + while (bit_offset > -dtable->max_bits) { // Iterate over the stream, decoding one symbol at a time - IO_write_byte(out, HUF_decode_symbol(dtable, &state, src, &offset)); + IO_write_byte(out, HUF_decode_symbol(dtable, &state, src, &bit_offset)); symbols_written++; } // "The process continues up to reading the required number of symbols per @@ -1836,7 +1849,7 @@ static size_t HUF_decompress_1stream(const HUF_dtable *const dtable, // before the start of `src` // Therefore `offset`, the edge to start reading new bits at, should be // dtable->max_bits before the start of the stream - if (offset != -dtable->max_bits) { + if (bit_offset != -dtable->max_bits) { CORRUPTION(); } @@ -1960,7 +1973,7 @@ static void HUF_init_dtable_usingweights(HUF_dtable *const table, } // Find the first power of 2 larger than the sum - const int max_bits = log2inf(weight_sum) + 1; + const int max_bits = highest_set_bit(weight_sum) + 1; const u64 left_over = ((u64)1 << max_bits) - weight_sum; // If the left over isn't a power of 2, the weights are invalid if (left_over & (left_over - 1)) { @@ -1969,7 +1982,7 @@ static void HUF_init_dtable_usingweights(HUF_dtable *const table, // left_over is used to find the last weight as it's not transmitted // by inverting 2^(weight - 1) we can determine the value of last_weight - const int last_weight = log2inf(left_over) + 1; + const int last_weight = highest_set_bit(left_over) + 1; for (int i = 0; i < num_symbs; i++) { // "Number_of_Bits = Number_of_Bits ? Max_Number_of_Bits + 1 - Weight : 0" @@ -2063,7 +2076,7 @@ static size_t FSE_decompress_interleaved2(const FSE_dtable *const dtable, // final-bit-flag. Consequently, a last byte of 0 is not possible. And the // final-bit-flag itself is not part of the useful bitstream. Hence, the // last byte contains between 0 and 7 useful bits." - const int padding = 8 - log2inf(src[len - 1]); + const int padding = 8 - highest_set_bit(src[len - 1]); i64 offset = len * 8 - padding; u16 state1, state2; @@ -2184,7 +2197,7 @@ static void FSE_init_dtable(FSE_dtable *const dtable, u16 next_state_desc = state_desc[symbol]++; // Fills in the table appropriately, next_state_desc increases by symbol // over time, decreasing number of bits - dtable->num_bits[i] = (u8)(accuracy_log - log2inf(next_state_desc)); + dtable->num_bits[i] = (u8)(accuracy_log - highest_set_bit(next_state_desc)); // Baseline increases until the bit threshold is passed, at which point // it resets to 0 dtable->new_state_base[i] = @@ -2235,7 +2248,7 @@ static void FSE_decode_header(FSE_dtable *const dtable, istream_t *const in, int symb = 0; while (remaining > 0 && symb < FSE_MAX_SYMBS) { // Log of the number of possible values we could read - int bits = log2inf(remaining + 1) + 1; + int bits = highest_set_bit(remaining + 1) + 1; u16 val = IO_read_bits(in, bits); diff --git a/doc/images/Cspeed4.png b/doc/images/Cspeed4.png index f0ca0ffba9c4413cc2a8a19dd5768e03e236c095..318204c00e96311529ed76351481db81d8212770 100644 GIT binary patch literal 71276 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�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 Sv^=p6ess^_w2Cxs!~YMALH64K literal 35361 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 KryRX}>;C{7W5ebE diff --git a/doc/images/Dspeed4.png b/doc/images/Dspeed4.png index eba485d0d1ed779b61c1dd1698049ad6628a8a5e..b7baef1ff3f7adc356d69bbabf2290bb38a1c994 100644 GIT binary patch literal 24692 zcmeHwcT^PXx1}N~%9S8d1VK@dEGjt~00jXN$w|pMNDkdCCM2Us4vmtts34Q0Z)Vo4HEU+xd$asQ?-IJYs=oT_oPGA*=Unf{3Nq);(w#ka?AW=7 z5AHuXc8ov+{J|2P0zY{|-unvt=eYe7nY+ibTIg}$A7^YIXxJY+MsptebKC^k0S=Ko z_VE6lr!L3mht5RP8^uVB2%MH-y882_B$FiJtGGDA@6QD9PpIFowh+31oRs>GXpgTH z;T_3|#bbno+Jo2N5h26bx*)gFDkl$`uKmTlS?+@tRym zhDKfoF;97$RmtXy@2^gZ#oDMethwAd`Frh-6L3+|4*J*+Iri${d^oZmD2n3^OMiZp z>sTDE5{X{_>~%?2Vyiu{BgT0+LN!DE!>PY$gPg#pS4T+^f>vL@pJHfGh!N(~fvt7p zQj=pF)&m(t_!*oB?aZRA3UMkWB&YGe9~u$aG^=MfUA<)V1au<)hx((mibm%urPE=M9x_0i8 zs9+3i9b?uKEmV-(9GcEBa_;DHAy2Au817E+ARY#aZ5CILrah-FEDgligv)dY`%j;WG+ZSaP$r3bL)mr zZ2yC^%sP$!DqDzM?=uL@Xh7`F>Zxh2)eLy?3iG}AS;rYSaT-mZQ9SR`cIUKFyc&Mb zZoDS3Jzgf6wnF%4(7oIe&E`*yfqF5$5w}dTT1Eq|{a&TBS8qK3@dlpRZ0>J(j_!7f zT8RIL)LKS_Xc<>Has-!*Y#FvL#2DkV`e(y=4Lb5##iL->h1&DaY>u9%6`6YGhm7H# zjhc%#O|dryov|>BvjFbh!YAkLnAPDCx5-+3D+conNRf6Lxgu{JnUOIiUwM zBd>hP_2-Ax7399?e14}wftJ5rtj7-z&XeuM=ja7*pcO5fLoGzTT900sJ<93cAgcJs zQ!&oEbbRJd`SBH%pYM5*G>dcVmKVdFt*~F8SLJRrht4{j7dg7j-Ro^OmuE|+V&(L9 zXVg07cq%?|jR$!pmSHDj74$!IN4iu>oGVviaBcTU zGhtN0V>ZR3@A7R&e^^#zq^NN|p!=K-2Me;xJ4|sH54SX#^i1pv?yBmk-hA?mQ=g7F z%&CY^E33?YGvFu;vwMmfIwGHGIu__gCu0V}z|)YTqCX18(*=^KM;;4~^Yjl6qvG|{ zmq98W0m@bfQCu>v4+PDeZJGJQkoyq?$!qh1-7LRv&4-K0kg5#Pb$Gh}{ewejHYWv8 z5yQK`oRc>xEL8?|-EfJwOSlPo~Ysw{mP$3cJN>L4NCa$Qsjy`?xaIs<^+?x*r{j*u$@W2=qwk+;Dm- zCs~)KiZF-bR6h$Dv$XwGOEVlq)b_%lHJlUmBRdMK zya^U4A3bLlvQ z(035{M!k+sMTr;?oucx=_a&PkVf^z2y}CFMAmx#}b0*69b}B_+rNFxso>jRubK9^k zs6SBxU$5A6S5>fjz8!qHY`sFDn}RGitv6ZoK6naAC-qy}S`m9I+>J>479q1<9p~mB z%`~V@G^M@YOc4khw?X(o$=X@WeNt9P-Di(+>Nmqo#RmwpGr(5cG27Rjm+M)bi3~tY zw{n`zsQP}6@e*QZX*DF<d&^-K$2lqkwR|>)-EG!kJ3g&CR!X(kCEVBNEUPo%gr-m~y2m0P`Kdy0 z=p_}a8CvLzn4;L)Q{(eRPne4*26$`fgHdam&jDik5tD8PV)XRGk$D@0yAQH&tZ-Cf zr%J+bL2sk9H<7`q@3K4c^kLcI-+>_U1Tqh$i9;u9bi(U*rWOOU{_^fq)Rcs7nIz8pWxaFZt+Hn!PS(8zR*xx{y zWY1<6>GIF0BDBk}Sf>Fiwn?XM8(u{Y>*v2fRw0Tn{Bcx0`a;zT$=gUrGmVZNARCAN^ z;yzSTV@?LU)StNviF7yy3bF9*{x=)N)`LF2TH)kp4SYXjeX*iodGuh3a`c?QU=V!C zSI>}QDL!B+f1FB9`@`~A^?bK<#aVz{do+Y8z|G6DErJ&%kt4hOX1aS5!skQM7S|-J z&WrkMxZ?4E^k%G2iL~BUM_BH|g*BrnS7a;RJjqg*1!Y8wH2BpE0z`~|3VJI1StZ!% z=z$;Bc2SFqRiq1xw-bX@`hJ;fpxmAJkSZxc3-3LzxH8ZgKsa_twMoi0G)DwPZ=9?|oivHSP^pY?P z9vLt0E>WSK53Juy&&zBOnz1o^mzvoRl10I`+AK&GZJFN?JGF?eNj~&4k=-nJEWIDn zBV-jk(^P(asyk`$t`za>)v^nCr`@$)lTkL(#}upzO{fOzkRb$E@4aY+44=Jf3PnS# zlseAZ*L!p6s)1#%uDg{R*h0A*Yoi=a)qLYSOTj$%={#>>i$I>7E8blDP71$)rU=ei zy|-IfI#oOwX^|^r&1=G$MKi09&a5Kx!ms!DR`Mfe3%(Gc zz5S5gpS9?ORZ_%e6;5J*MIsL^X^`qg`=Nn`$6rzv6>j<_j_7=jjzhZ?M)6I!de*Zr z9jAvmo2GAyWEf%jRpwK6EymKp%UbUwwlS^da#9YC={I_seU7Q2&~=)7CYH-<`D29! zgY5qEARN|Bx=zH~rMm~HQ*aPi?l=^nUr^Y%Hfoh_HB_EGLtCHr*u?xScyg*LOpF(1 zW{N#{n~N&utuT!I0p!WF5#Hnp;k1mzZ=`J-igworc;*2t#MjR8>AmLo(TJZyB4=c5 z#&Bh%u<3g^3gqT})xtftauU|m?XL@!+s5%$_^cGIU9RFjWUmNM=Vl~A0sz?jZdENK zz1lD7uHSqZTqEWhx#1Jo>^b@cms*kBXP8Yw;~mdwBKPE2w;6V^7>pFv9J}YYmtkrn z%{3QcJRq-Dy9C;oyRp9zOxEd;&vq zKe#%8o+NWlzRA$v2<$(s6|Yf|<;wQk{TDd+6iu0%`9TSr&S6`3K_K%N8$FiA(?Ss@ z7nL=an@M)#WA|C9sY8TFbeo7s;~bOt`NMx}US={ZxZ5stgvQT-7xu*az~75<%u^M7 zI`gpu$#3lUQt~w@sE>^?|6W4LI4baI4$7F#$5Jn^_(xt-T!N{V>y#sO(aL)=tYH7t7itSfjZ=x*w%DB4iv+W0M{`kn+`u> zGZ+BaH7lDhloOfzdJjtOPu}FSDJOLWSU8sSdsqB@cX{8;-)2B%Mhtulhau{2m|?L0 zI_5N1?M;!_o?bp!Y&YI9-5#&(r;F~Hd4YESLenE(+Q{1CUlzCu>Qw0zZiL zE)sBb_zSGD8?{Tu)D>CEC*M%_-p++4adb~HYd~xSd!EbEm_mpTtm@sl#`U6q{dRFu z4XDoRiN@raIGd|xq#qCujwK2-d4C7GKmypMT>gI3cuL|xg(&_^fRy_;zMUXVD6yYP zdKk=N)NJKg0>ACRb`&^SJ@2r_x{QSxETkyK3&Sv-0mVZ!jkl`Ve*s#?xzJdZQ&8Au zxZEfd(*lt9Nsm|kp;mQ962my%3kL62s-V#C@~1QwM3 z&*aI9w@68|&NOEjUL+lG2lb4~n)Cz*OGZ!ihD-ixw0#TinPa;YjS-Uch+tUQz#{f3 zJ?GwCw0;1P4P)+FuKrCu&Ig+NUC+}S9aF+d|K3@Yv^NZD{N@%$R(mP_`tWPa=3))9 z8)pr+&9AHp5paV~HAaGNS*N{NVIL}l(oW)lT6fLFY?LF?VJmK}c{tS4u|(X|NBL-@ zsIs?BQDD{FjPwpzTkxpZIhhPqitYLQev*%+_! zms{|d66pjAP$avFQdCrv3RflsKsv4$pS+xjd9gM%J-@y6p>R01>bD3A zG|fGRnN028TKVuBpJ#ctOl`m#r))^JSKNf#0#(C zqce!qdCd#Z)LIGltzrVO8D*p_U=Yj;b$c{SVpO8qD!-q)m;m^7=QP)*S|6*;#Zin! z-bC&X_>q>|f3$L}{?Z45nACLi`xp)wH*zTefL19 zW#`CxR6g-g!%l5Sa)pI$$R5FS9#3)P=CIy5JBB0d`vGv9SJvK@9-_Svpu)3vhR_{K zPLvP9d7jv$5dYqBk1qgT=B7^S?+W3iiyv7 zid)7_4NWks=&lkvM7SQPcw($X%jqQQ>`E+~vq7>V9O`AQ3$HK}y555Q#%3S<99^PSxC zxH=2)a%&_+113Nw9*Cqf13H(YmUW2{9lxb|CLoSlnx)I${dM8V0F6zJ--TdUEacUJ z;L4);o)6xD{~({XaUb6&DNu#~cylIG>^Z5)>`KrYkgiQsiZ{o6^ODapKSKw#GBdVOUeSvT$1F<%etkGI5XsoJW2JV$vsif~KR5OPasbV52ZiQve~+YZxh`Om(; zasW>*c>%G%&1QYt8n{j{FU~cFa?Mr;NvMRQYI4stf0}jpqB}ReP(9$wF8l_py*!a< z&;1KhKG#REpRcUTt~k!D2x;(Yh!qlPkbl+p9e9J-a7KjbH)p8#UoJey-^awITQ2CX zx6d(YfadquT%0SwywG@#I$Cq9^V2IqeEQYzGtBVOY2`6^t8X4p+3!9bJg*IGV*u&+ zzx|)%Ik)a~-4H%tT(F*PtKKpDt}en+SZqb>X#vn2LxVhUsS&FKCT)#9WY+flKOS@2 zlzlG5*g_)iY7};d1-D*HOS+n{b?92W!ds^>Pq zR^?*ch9P+i%R${!MZ~kN`u-W4I5VJ9gTKKGuQ;^?eG+;Maoq$k@uiAxDkt%y9diL7 zxtpsWg%6p$MBvYm?KNV5^!r`@bO#{0dpxO!^3Y>pa5e{>q#wUmMDowU1b-Hc=+7o$ z`j2=qJblhI0cJ-&ik}P0Jwt^Vm={B_)nVY>G!6bX!mrb7bcRg*^~nRr97syn{4d;M zfxNsC)q(KU_|;jxec_5OL)e$_|&C|Kn8{n5GaG+9` z57UFYLSAC09!6kVgRE@kGiR0deYs1obE$ugyN6ebmrew!n-B7^GORnVJ%=!g->sH9 z0@Lx0?FAHK>jzC`5Xj_hn<2o1#S!?2QDnX!iA&}1X>18#)|ID8fB;gZJc2@Jzrmbni@L60m zx$ZB3ELMTHO*k{JMHmNVHC&JawsyY!HL18DusOobrrSPaGFu@QjYGis*WfDf`}7hh zC%@jesf8TXb3+!oE0L?fp(p0PAG=Y`%J8D@GG;qvTnoF^v(GXA_L%1vVj>Nxh0ANq zk8gTP`BEoRD2nn%1$U{h0aV8g9D+9HgE6p5UI8Tvq^a64ZhwK0@v8Z9N0Lg)fopD@2 zHq6RNjz?V2_WQ|-vl_`UPMTg8^e!Ww7{?Xzj433dvT8#IR%fG}Rk7Y*kWIs_t?te^ zUr5gM_>yPVes8Minwl~J;aQf&F<+jf@Xeua>Xl5@Li7VgzfA|ecF}d28x2K}D>O=i z>hsk}Hpc?Us?KKJjcx@#&D{ENrC&?6jM+mUFN%A(IGNsBNh~ducHaIH0NgH2f&d); z@-e|m9rGV}1zFm1@j45DTDgqbMelP@7#(E4y%}kjk z<3xcG!*xqm{>&$7CTl#JtGL+FWn;+MWDUN*jm37EDyaEuBX-w1ArFw)XPV$~gS#%4 zOZP__CKb^;Y3f(56iNUKJjP__xk8A_GyH@5Qw2w`a=f@j zLCtbA{FnKMF4_{`_9U=IS4El+=vnYenItA#ipp@d1{LuJG}18mm)2zV_JKkrCnUC& z281R>fUtCtDde6{i0?msKS81IduAr5&a{cu2Pt|#!~BH7n`z*FeVAivD#}2Mc*R<% zzH0Bq;55DNfPb$t$l`a60j%|?Pb=>fTNb&*njBa4Ji1R!Z$TZi%dp@g!{6`}Rem?4 zOWc04Nl*uX(AT+qMavR_6xqB_LTq$m464ovG@%rL|8XI2z(0q1uSpT^o0mNq)XfbM z<6Kl<-`tZEit#(0Jh*3_F5dx?Cu?b3U^I=5HLDMsMzA1%N%PASZH(Emc!!qyTK>5y@|* zSqgls9dUPFceKke#)Q}amOps=(2hhlZQ`l+&TDJ)2dL2Hu={%(ox|=6F@+%5D5yp8 z8c3IdyxgfI!w>=qUbi8>qs6)M7E~SMCZlW=4&d4&aG^Ti{q0H$KxfSTk&d?jwxD#^Q(gy+ES|%}o6ad4PC5)ipam++X#-OU zzfcc)&)}ajr2rBp0}9oN2le9X_y;{IYC0kM zy4?^V1(>l*&>8nw+%A^ z-Z^MW@K>EU=l5_i=TZ-=_>#A!Qb!+SypElg9UwEzIuahbw%>M~>7qPt0Ytf$b=ZJ%>rDyY?$$%7%uz1W}qk0MQ&} z*)X-oo*uBgEM)~owbJwt8C!BS)f-#&3v1YJ6nGQ<+5U7dt~JbdI#9a!)Deea3ZhfH z+kMz?UI{=mB8`w~Y5zm_s}G1yRGBheUcW$=T0{G7w3_%O91=@!SYU4H=E_W59;{;YDj*HntRsdc6qOW8= z@?O9FHc}~QwkyO;q~ktcaL|-VOwCzWNe9Yz;hB_pkPw4se3Kww6Vwto1mB*=0kozF zC>(33-CKAv+@Rx|XZFwUz^5Wu@(-6Q&>Pl3ah(i$eZ}Wd`+H`9vT2r1$tszQT#Z@q zV6_4!AdF(ZfOP5qK#)>$YKyyrn~o1`Q3q~_f9L1`c4Ej(1W`VnZJ+O1$ZHo`YJiUR z^bWwIs1j@ZcbZg)zX7Ai;&%tYnu{`|H!rMC$D|{`~#d zEoQ*oKDAi>rzF*1>5>O1p=3}h^AW276S{#pgd10vs{j+|?wU|_kQ2Yn0I+4cc5b#6 z>NnpCgzfExcq_o*scPJdz|d^SI2QV>5^A4@I(5!nxOo*DQV{^SLHC$Lb&7;_$@6#m zWNK>#iowV3zF4R+77IFe&F1=Y4j7*KSt2EW(9hVk!KGb%gJS^lfvJtlBUp#KQ_}98 zS)t0P>dO{FBg%UGa}p_Bms0Re>HqnHgef{gTNHvQ)=IAq9$GD{Dzq z{O_)3m zJ3&h#zB!T)G#^KE>o+OI*NPo*9VFQ1NIs5jQMc7;NSXQEsY(mQ}WIo?v^es&iF?TVO)^YgHx(~S5j62V~27Ggv%x+BxYuACg3*Abt{ttIQOUJ(($30_DDwLYG#uBqBse8Il#_0ByrmAlc^u}(5 z{vzHi3?jf^$%USKR8KAAy8vWtp>gAy!zIX>exM6!a<%bLV6}A2rjFiXO2}H|Mw-g_ z8>Ky#1wzrMp`?z(%V`I#SYI}RwhpaciIhNP!dS5%^>O`weXt|hW=B}%r{R^@jRd{@ ztzL$8nx!hx7}CKUDEbj<>84yzGl~+h(JciXdmYh2_8mUJ7U?z((0Gu}IH(Tgmxd2U zuAs?jwWHGj8yR~N;*Thg8-hU!Vl>vu-bY>Q8e~mX-O?AWK0$hWGU)iI7|?{84sghQ zJhBt;_fI(v)bWy5823ErJS~9vQgg}D=r|~CL9Bczk6!G&9#EP)E_=~`gqmD#+s5th zr@osw=xo0_g76*yv|KlpAW+6TAeM}CdJdQY%$mY^G4H#8-7)maRi`3!4)0dMkkde7 zW??@&2VMMA-d7u-mhL5i9HgB#@Rg{1P`4&SoSa$F5MYWym-<${BK#v{kLzyu9TVq) z5ZQ0C&|r1`{eU@WZrAoouYKPMI(LNU()Y<~tBLxd@Q5nw+$K^wAg^}G{aOHt>wur2z;~BSM4#)$(6RJJOs0V>*AzDEgmyi#_xJfNEUFD$d zAN2dHIcZscdwCoOxF*M~u4M5LmPg@jxKhY~YNZz~Q3$4PB9WWRruYE@*|4;kvjr>Ev@B6vG8QQ7{?>vk@;7*rK}&wNHAkgP9KVYtC!klQP9yScSGJW-yyboBY=$_~s~7 z%~HlcKX6HyqCf-5p7`U}-DG_bU$fS$hm3g+c{zVBZ`v+?KkY1RLHIR%Wwo@of;;NL zrHS!+)b;J0Kp5x6QD{(%@?fOzhwO0EOGV>OfWiC}NFuf9oeP!gEZEw$*&?-y85NB- zA65c`;jZJS>4QM;Yw9W>D=%~ObW*(JHQR&8RI8ir^tVBUzKZ67=j`1qP%0(Tw6owX zEWYLn#pQ5A8z>%nt`mm`A6zRnQFX#1XQk3%XQlogc;^C1}#6Z~!{hIxj}z83gH-tjVW_EX#c7+VWQ z?ij9rdd_*8{4z(DJ+Sd6(}sv_&*kN5Mev>xA09aHCRBjB-hEf6;v|8c1<&MTGnoekOR*@+R z)V%tVgYNVf7;;c9?7FARLZDLV&nO}89wnhc%Q$1BS2LL1H%6WEGDK+;%(3z;JWE?| z&VlmH&XR0W^SME(MHo>ssxNlnkq}XbGP5Py8@)-lWHjj@m=P5s> z>|!`r!dYXq{+Ars$O*;=QC5W-^KHQK8>{NqJp|MttmVyJH6T_}-r)|lexJ-TUe>2S z++8-jmNf?xHKRq2s~TnyGBO+UdU5Jq(g!4GV*~zRwAMTo=qc7ksOd?0dJK1g-o;>s z2t)ws($i;tlhum5$f5eipSAZfJFq=4h$o%rqUZHVHK_<9d%H#+=|;$YAL1`z(AiC$ zULdpRtCRvbc8_~apMBcDZdrkg1lIOhEA;tu;E^j9dfX$d5q&20-iMWHByyq$Jr0(@-4#NEg?7-9j=}-C}@hnl6A9ae-Z~BLLC-0AW|4`q$+|#Rx zp_b#Xj!xU+vKFX0Pp-58bTWk7*UCqG;;)RF7<{$f@VcpDL(3m==qi>@hp_T!*@;h0 z>p>7{7)9ey5PC-2eMU>uiJNss!V^q)GN!RF`?}wxlX{YXSHfI{KvnyNQLO`&?v;ew zr$UN##eFEJX44+cWn=Y~+8{U1U+PNY(w)n1W!#0uS@1>XUl5AD%Lne9jL4S*Z__6e zZy(WIYyd&AvAq4wavdi~2fS8hWY{5~0>e{)Zzn07@~}6a2pk?%V6H2BgwP^^gchm) zjsv@=8+|2I$mS}n7(( z_hnxLo9;hg4iUhl|NBFX{v3P|tp6X4jQUTu+KD6@fSPy!Kr?&c*Q2=-775=*ZWg)$ zU&H~(ga-Dg?t*Nc1oq8HER&kx3Cuy{UY62ON3Q$qkz?Pf< zYX4*a$3#H4R`M&IgolTf(}k0=G`Ya9Seg&qB}vd2J-{(InE?g(0c*7FT`2!T8rFqv z$(TdA?(Er5?1o@I9XN(V9*C+JD;l;9K##ZC>U2AsbcyBfFFxjZh3J#HLJ#C_iLe5L zonq#IL$z~x;O#AwmN^H8-^1J_5odsIQ_umX-I&gwaTnA|z1st|a!>ws;bwwzo<5TG zoJbC(aqZr{O5O0%lm|S7>$7NH63}`6jgI?qT2KMdzB0-{T``A zsE%>~Uf)FE8IsT{9R1?UEql?X+|F(MBDSyO?fQ}a)6euc&3j=qZ+~w)IUL~#H1h(Nv+}!FTHvgyP3{`26^fAI^7G%1YgHIXo|q|=TBfq{WPY@l9iPj zIO*J(c4>b)mHl@2qbqw(C@a94e&YrE-?Q8PL*`e;9V1xs>X_YEcRQZ;6vqw`cS8Wh zngL~Qcen+b{RKS%Xhhg9eBPLw7BM;3iQIF5_Tnvc$mOrnM4#Ny8+>29Zh!nHOQ;}@ z|G5h0-5Fs?=x$$!OlbaKjO0A<44HwsIvVv#PT2w9pjsH}UUL}nJe>so@xoD|do>3d zPu7XrX+$Le|GHsqHP#dwwABfO+m@u(cE*#CCV2qVfjxb#c0&8LBpXPJPaJ|}&rfqM zf{6(U5Uj^Y6hn%r+s;yLC-7Fqwn*&nK<#)Yh}*Cc$=BU66K*KhyL03+^dF#-WEg2k z72qen3w%H^V>XTOIRi#H$bG#9RVNupU+P@d&l*1G)eXR@_>$83@_h)HrTrd&ISg8v zW()4v?G94-;%f(Jk3fUgAU9XRLb(Ra699V=28Xsg>4+~Ztv3LzWNA1JN<~{pf6j|9 z1Twxu-DR)auBXsIw@e1*jsmQgrA^AX+(u&f38>CWLhWy(6rouWsw|UN4@Rqj ziG~(#W8SPCbsv~JLBSsmnd2yna`d&zUF?J>J}GxVeR$9mFmR0mM)u+Q4)f3iM5rot z+MWf!l+&^*Q1LmIgP)9Y7F^#P4^)JvA8a+-z=NR?d7L-k)Atw~veXd%g6qH?W&j1N zNI^UOgAz9;IigUy0`xKNF*nDGiHIzef$At9bRHPhX3v$G4un;%Caz{VS8&XOGihK{ z_`KKme>tNXAL(xQ_a>S49t>7UUs4-(28CSO+l-oyLoQPEcn}a7?c9vQ^#P5eJ2z-3UIH8xgS84xbWQ9stzzl zAsn(=B}1;mZEjLcXsT8z2mpB>K0@|GKo4-~*rBO#U?!Th>aQQfJdX}cFhUQZF-lLG zlze8JKr;n2RgLYgZd1MYnSMKMOQ@;O4easUXXHhK@gxu#l7|RKK)U)t*W^kRcFuMV zvLIY3uYNE8=;l5sH9y2i%zy=i#)lD;kh{$k#rD$`4Ss=>lQ2ty4%v7OQ$Kr$4V`>0 z0>vhYh9VVS{P0F)SocPz4a@@g)H0Sven2|&jst@(v!JehGav4w9QQ-0h1cn#AgQkF z_rWsOyzAItxjZ9?LgD1B9sCN64@Esit}$R1$Rdj1Zs`7bqNk6a0dHH2Ce?G+yFHNA z&X$r{3_p(!r)N}ry}KNSYLd>o@>uGa&zT|K9FaoW%z9SsT4hJxv#R^MfWv?CCWnZW zx0DLG!X?dLxrydU0+fbv*_HR``D{h_a`3_YKi|aktWtJj3*NL48#^s-=_+VGhNW7$ zbP4VAbY#~)=;%z$20W35X;Yw8Ql?Uvi#n6_E_xPNAEFpzPu7IM)HqfVHmcoMTin68 zmL#YxLFAs__2CzdTpDq6=6i!sU9i>;oEgz4$Dl!Wije(JL~zP+rat3Bm~lfjf_ZcU z8Zk!PX1D9oH@YO`^)HZY6#Bq*wE5O`ftV*_C zhG1Fz$g{SrmVee4yrkMTxX)U+W7aTN)rivn#3?;7Q)JvvM^RsOUHY@WVH$k)SJ~E! zCAf+NZ$9HyS7+LXK9XgFXxRzzPn_ClB27PO*hU%Fze>bXEP`*m<55I8a`uGd zs{J4dFj}@LeS4rPLy9DNdY6e2=JO$_Z@Cr3RA=D=p4jll#_G(PaIfxe>Z$kbsaqqI z6Z+h$Z%S(7x?BPToyVz}MRKI-X00K2<+`H*Ep8^dIiGLx!@-zAYcy=~7P3B;S`=(c zWf#W{9Rmin-m9eFU9VedaIR-&S5BG3$%#-G!#@U*@`&ZW}3T-Lmqxp99#6O*(YUNk{a9D{$qR9B1jT z%w3?%9>TKNRfH?k6ww>RYB^s{Z$H=tKS>2SHF6WGObz1wfq}SKXBq_>wa&jM{~Z44 zl428D`5m6R=%j%!>$+;;1hXcd>ub68Uf>#-q?4<|o1F%a0uG;bJ5c(jVk zjctmwGfR53hpmT(H0udp^!A$tbjkGfXIInXy%Y&$uaOm5>tAJ&4%RQ2cS#VBCGqg%e|MwxhcwVmg8K}f*!w+_a(S<%%u9NG za_8sNd-BZUOj`Q{{kvPB5ntqyv7SzK_{b$ihMMZtVyVq|#@*{>A-zL&^6+M`A(_?4 zgT{KE30BwX4et4T$o*B>c)|ppS;_C+Uf}Zn^485Q=E+tmMrcgyJa9z0^5ym(-i)Xq zd85F6lnj~w!yWRuag+!!VKM-LAmEZX`E`HE3?(WHZV*KVoR>@-^}jcOo|^K)ES2H# z&DurCZJc|I%HC}m9=gv&>+hHC2I27`##efr|6qD#&I(-|3!(dY26 zOC@%C;;iX*h&Sn`T5tUN^pCdyXLOE}hpsrH`Rpz>8{AvG zB>DMeR344>Qi4%*cG<%6>_m3v4R7W6+_6^ktB}J7CfW3E%fOmnNMX;7WBSc;| zfILdw_9lUh+P-Pcv?8Y}9W%Sm$v2x|hIOU{zqL_~;?6x?6#9Xt_;FF|x6lA?9ANDb z2cr+TBI&Svr+fq}(=ED?0>jR|J;e+cNXWS_A|KEFDhtsm5?~>JYVh~2%Rk%_Is`6&$p=(Sfoh4 ziQZAn&+uc~8=YhC`#CYr*x|vI<)OE0p|;;9O*_jTG;utAZ*vFc9E>X~m4<8Y_3LOE zP;w!*Zt@^eP8&lFSpye?i9U0P=;?;J_@BYy6IQnX(YMgT$%Bn)O#5W!LH0SK@aNQq zESP)rRiP)ct+D@b;@oQ4%MTfFR_8llKq3oSya`nEm`?=zaFnU4tlvtPRWz5OI@wg8 zrk`yN4cY`nMH|1TheGJUTdP?Dn!{;BY0xa966b=WSwv9)Tk*U7XaDUDK^yHon)sDg z-QR^BxIH(X8@51GS9U`bGynZVx|6ysYKWcvJ^?W{G%XMPSO!T-ogg77w;xf?J zF^3=+`w15i*|3Y&UjKdA1?OX~rwx_1?HI=lytCGEEeLv&z`5o~fFL%=%-BMAzj@FB zi%?}tnlV+{#9^12lgvryJyveA)^2jv9&$Eb@(6-x9o0LkgXkF|+WMyY26~1jh=GBD zp`qbXBTEwtM8}MJ;xuAGMJz2XPoF+*XJ<#HQgtoP9kX)Nv-Q!p4>EB%ZhaQ9bw=#n z5bMh)%`crjdkJy!);jNpTnt7W92{I-UESQ=e0+TT{QN>fLc+qrRIDRZZLX@?L>;1D zQ+K$2_-ulK(-lMK7-N?>qrVc3J=2c+6op)lM*^eIc&8eNq#>@61@6~M zF308v-6*7`JT$*r?~?j9GSw+DGXO2Jxbomsbiswx7w(zQXg9ko!o$Pk;^MAfzaAeS zk6yc(l$4a3ntJQjt*or9+}zysqS||<$qy@T-MMq8q@<+0>Oomq*^3u1vddcTRemgf z*;)EJy`n9eFcb+p?zC7q34(t*@_dXlQ6^YHDt7ZpHpO zf3$z8|J?nyv#04x&->2a*6!}^@87@o_V%`Y9qeYb_KdXs82;GF_{Cr_1_lO3Mn;Cm zXT~RoCZ>nS$HylpCr2lLPtT1`FAV*?GBG_3>4|zFW^zfDUIPXhQlHVtVBsK zWnU0fc@zBbAlczVIP@1c-r9#k&tSuS*+DED`5$k!UrSQtsd})3*nUl~`7qpBG^b8cY^_G}o*7Ph zu;E5X>BMY9UGO_)Zd!|6&Y{C=e%<>{VB#fl57#PEY#_A*bq6je-}{Tyvm0u(@RqPyu~oRnOQB*H4qk^t0#zP1l=DRL0p_Fa zQbe*Ub|Dba`ECLerZ6vS*FgHTohRg>&-PXpoLKYD4_LD<@&s#EG~0_c?B(00| zDvjLF_HEf=wX>^pfhRt&Vnu@Qip~5@ zg4+HOcboav53Xl+ui*7F){CrEFFv^#R36cjqmjKHtaC==P`>5>?;XA?&ZJ4*Y$)Y- zs;$9S-__8BV;ecy8_y|dHn*!vYgG2m3wNH>-yo2Y)S>Z&pyi#x_<-)?FqMzK-N6UZ zUFap^$x@*!cb(`0QZK2>oFN9#ADjf7wTT*LJjUqx#96AX)ke zXDC@$@ftp{YEe(aPHJNhSNk5(`HKk^ajp)OvB>%yf?H*0k)Q@FX+rZE+lDk8R_=Xu z#M_jpIg!LG3B?m6TW*D_MXrQJJZ6)%+iMXcfE$`w`@T!NSH@G6Q+f&RnBFS2{7?qow8IgZr?8jxhhUHkQV#a4n0~>*LY42bz51T5X}F3>kqe) zAz5I(Qm3L2PSBFt2(h5VTmiGcbNkJId#x-(U3A!AQkD2VF0j{aPq zmZpIQds8M4u9}jy{&Qws)1^if-q*06W6Qn5EWZ5el1Sh9;|Utk;ajG^H!WDD=gEh; zcpqY6-Nv7!qBUqq6JIu8v1BLuYkvB>Lr;fV^!)R>x?0hjzed-ip{+NehCA+_Jcr{C z81oc7W@@1Y7VzfcnVDcAXElMk1vXsrYq;`GP84%4e(xq&Qpy*f2rf!&Z?IeDB(EcD z-SIlcLUU3xRr;N9@9=cRXgV#e;0351Sau z&i5rg0$NUy#>S)sOTUexapK=(odY8TrpSZFzdl=WMM2wBlz?IX8LVf>Z~|K?YHW~$ zO_8{394yOQM;t5*zv}9;`eXK6qEL+y7mqj?hp$s1y5gp`pLFtORke9 z31n^Pkxoz){y*q{5)q4pgkqDx{lvFwKT5b3p&Qnn03zyAu z6W-yM8{`GZJDEGl$Q7}L`9yKi3HFhw>(D7ZPlX*TCsg-sIfpN*sd;-E-G@yu5!ru> zgTGifzhI*)5Jh;KtYWh+_ZJw2Rc|1CnH9_me%*2z0YCIFbyz zNdDxMq@YKBf+33}X0|kv5#glCW-aJUBT$4{ljOv#XE<~%2Kbk}=t{6-t}$nnD`8kh zEa<=5cA@A315O454Vh*DG3i zz(caU`k(`EEM`DBzp0Y?)lggIywiOMt3{E$=fea$2jGnUlb-&&8@4U@6 zrV>{msdh)8TT~u%+-TULuqJvnUlo4j2R%-3*yE=tg*j|Vt6y77O*{! zd;#q32IT-_!=D=3M9fwHCh(CF(Mw>@J9&2leQf^(3}0RaU~G;44J>|MWnl4K0$eF4 zs{@1d2^hX)O<=I?W_3%H#0*L>OQb_4#Q>pJ1K{%$m3NJU9^TUD0j~d2>8-(XmQ43+ z=mXs+?%Flz(RpX3ln6KPz|1&2}NA5rPUWcBEO;3~tl^gfb$Lj|$C)|uV z;gh(4)t!uf>D}6JE4!}%BPjD$7be}tT`mG*+_)x1(w-_3jzeOerCo-w0Xa`nhIy$3 z1C;Xp@KG4|PD~ctvpjwq6Aay}?S25=D*|9!q}m5aXNhLenIAj3aGf3Qm_XZ2S`3E% ztyzl>CfND|yg;BYbpkPg7D=^%IJ`TX1r6WybT}E2`aOXO^lD>BI3C~LBKZXf^m`1@ z+Q0m9b&NF-sEhaouxsM^Ab=K$c>_b>EYRA&q|3nv;P^+n$a;YR5MGWBSZP(t9)P>& zXO?q5{u%bvZJ{^fODrF`YA}7@AX=cUDW)kd&vF_Jgtb zT1%RhcMI=g#oT&3RGJ`xkH%ttqJumVk*s)@)u)nJrdP98YuTx*dpFXb2E+P_l57*M zmw*#iyTuatF`DrC!KX*f(R!74&F7=@APK`O$J^k@a0s6Inu3P+^__p${HdzZ@ud09 z_?q`1sggI~6~av!AkQm$ZmG|9$K#D#wv@iC6ym=jo50d->M;h;?Y28C-Qs~>rL@Kq zY~#cKt=lL+aBFvY7SQdTX)KxkyIN83bCu->bt4 z#0-szg+*tc>rX`g-~$#&bF!+j-9P+4*aZ)8QEO-$PNtdn7NjVsn&bFK5)%6B)mNT2 z&e@eM&9cPVLyve(=O&m57L%M&vM?@^beuNF>)`tY`bGQMJ4`kh-_0z zgG7A5(*1F!b=RfxgdUMF`>we(((J>k#T8-GL2@EaY~1s&6KEjWtJZp^suS#ijO{B_r5vXS~XY#_ARK_BS)!)6Rsvqp!9! zII@KY^1^nC_1)_(y)-qRa9JqS(9*(5eSz8X=E|O_TwVsVnVYAzq+DCO)0u!RQtV1c z|EJ^64C0=_W+^-~re?eB2X}^^h9>^*n7Mx!7s`{(`RbjhEE`V8<5%SL0~;SR3Im#zULl<%lyyrSuCqPtNB?;Ql4~>p-dt-9xWuhG z#=5RCQ=`WQ?> zyv6U=)&0B?*AQIyTZ2qF$lGB*)VGoOU{wrpy&-YGE_W~|j*V-BOi}KL2VD{Nl`-Hl$znn>Rm?XEZKEtNk54-iu zcqqXIY;ZsluY<#09o}FoYgIC4afIu1JVSM`POoA8F0L#Qk*wjzRiolh%+Z=PAN538 z9yy8}iaGef-@oT&KTFUx)~lum?4{+dz%hy%vt7N7VsxW$*lu<+2|sI|1Ep|sXOrnh z7h$^)2@)Kz+ZZ*%vTR5}m&7o|;F&c~hSD^(HsfmfCF$4v^^QUcO~f*gdC!_(gGvf{ zv99NdULbQt)5P&E^O#r0TnsMb6n8j8o#$-##hm_ZJ{4^SFdDX zlPm@L8nwYXy;xSpkaEJE1u+B=iB&65y|+?kK*XZ%-%4S{CqXfs-*ip=nG%CO`kxw2 zjAEcj&ers@kNOhzevwm@-7x`@;fTgChTqO8eo*%aroZrDy#2G|=Vi9#(HDgU)!~az?Jw7A_Uog+u-qL|NREbfuVGa=ng$ap z8CVuDYn}xO{=h;9)o=^rCzcS zBK!~pmD*Hs`UI2caP z?SCk+g#xN8dYlT5Rbm8ul0r&Y_!i^GSVY!Mf;u8t)g*PE=!F$mmg?BXD#PV0Y2@pm z@~n0H63K&DqC$^j$FU9*0!~nnZq`7{ob3l${Fs4tSS(Aff_VF}Y^e5}9FoQAa*&e@ zvR1lLGu#M{C1#T!L9CP&xS+LnV%V^WkmLD5mnF?1%fs08+i`Z^)SN-OAy>#Oh2Q|* z!}zZgP&~&m0U8YkymfTkJX6ieXHzE4o{5C%%yU~bcj5p!l z!Q39)`k7>L3ABd%)qgi#z7I!a@3dyxO~s2`<MejD(j6y7$ibTl%0n?W%7JIYRKUOvmdj1|gLZP2(S7R#kGoln#XKK%FUYcJ>`_&uPJmJu~*Z)U3 z%}(b|QAz#n1W zgKg8_ITgrAR^nf@IQVcGr_-wsVO1XL-P$jWYu#Ei{j4_fY@f+F9YH+WNBK8VOOIeD zdV5A1dVqTC`>I+pgo2oC6qe_VTc z^wH?lyZ7_M?Agm58G&;VBbQvyL_@d9A)^(1j5pI06>UVboui|0<>H_c)P7r251O;v z$>k-KP8jeHD>16~!HL-5#=t7S)`j%hJvP~h;rVJrTZA0+Q1!=&?55xQ*4g9PMh@DM zTEhiu>O^}vXOnB7M>A_dz;z4e^VL@P-gUkvTMlWF2 zA;N5O3B>!kzm92ad}JX7yi8V#gQVUoK%OpTYRjeaYqlq6gmZDD-J1*bT ztXVyZwv|C1t%d&_+O_mWZ)h^VrH4G72qU)Nyf1+`um7sZ|GT4igPbQ3e*m$pruM-b$Z<9fBsTr>$;!khcT-IP}1l`VtEAqviACObU6=Jcn#Pi=K>uI6Gn*34eyA z!ooMU+sGV68?Ii|`3#3-&`Qk>$qwKsmzWRXMu3acDiUP$VzGf7>4$3r=X+W*f)0w9 zN2L(E-~dsvNJz^?fMJYj86gJ|D#x&>L5{S+$%kMn$KN>xnXWiR68_}ShH^{zvtheM zm~(k! z-l2BgJu+AW6XA zIfizz-ob@8Pm8reLp;ktks~>98UJ+ALZet+h7^!N%tN7+r-F>3_u-yK5s=o9JaAIx zq*>Kk=Ib}MXx@BF0Wagg#=A^~_=g0d5zUwn7nY(*71_?YPeX0Ul1#$O_$}@FduyKi zaN-|$?T}}c{?n}v-dGxyJ_fHTdR7|m-wICA#W`n72s|6NO13x@_W$zqS(SbCS=6QB zCaJ8iLK$DnUT#dw_F*qk#49l-v8cvbSx;T4ECf>-l zi!sAh?6RT7y@Gr;jBO2dvQ_aAlD@VdA`chiD~DtueeY9nYgFe_FmorB&8q1p31Od4 zf=Y8rwm|1_|NF*cHw=MnL(l)!BR@Y}%-(QhlS|0CzroQN|i!MAG|<3BR5{sbGy&KIxwos?!ZzN^S$$ih{BYAmu=B{+qkUmk6)8= z*&a?mwtbJ_lX?(toxoH3)offvT6woqqmDv!)*;OIGI7)vpDc9Ab z=Ki&g1DD(Ye+>=%@v9zg-N<2XsW@0sMzi+3v-0KM`i@r3%WxL++bK3!GMZ5Kvi|7O z#k(T(Gn(039oE76y*7P*z3%w(>V$0?HjAt6g32vnV))w!c&~2k*m7f}1&%~sj9mwHr+ z?0fa*c-lzxLf@MZXMgi3t*|hhGqXTpj+Y+l+Eh~EyApr7fhw1!h3*&#OF(MnhDms9 w>=O?O?_zidM(_WRU$OtcAGmD}WHL2Zn4^MM)giS0w;G2qu`{K>$tHr4YT z=75V2FMkt(-?VA>_P0NqG4z+fBZoE}{rb!A(l*a?7GBj6u87!1f?q+&3Jh6(&TRW1 z|2%r*_>pU0_kMSwCieD6HkjT5nJ+g$NkT} zT#uW5wS5%@3X(d}(CcKp)bdz-DCu{fzwF;wjI~&#Pb^cK##%02sebpV@5PBs+QIY< zqa<=~XZuFEKLd1GX&bX7d zaIOIj#-g{ZUmXb#DI)&odO~HfvPG&IXFq)R!2dPy|H+6jLi5UjS+xK`{e-J}?%vYt zM7o$6v(PYG@kzdI6nF9uXmd&kj49d0sh|?QuI{MGt4N*Ry zO=sR`(%T{t2Ex9d(1x#K+H`~SUY7|vn)!ZiCSoI%tFBPoGuLR_o%bum>AyedydnCz z{-^cXmh`ocMCLDPkM*?mT#ZbN=xJn{Y$RB}==Oo!8K;mJ&W{S(Su-9Dc%$?5Xc#qz zj)}~dh}t&32;m+dX84a==eHSIS1;5y?iN28{^&O!ESO8y^se$@Idk+4%1)hLMjh5| z`M_y)i}Xvxm(J~$q_5xk+*a?usOI4CZx8?NU%&fYUNk$$Sml>y?6K5zYVH-$=THZ^pA6`0~qrE znc)9S@c+9PxG|HGQJKhem32#R;Rb2P{Oxgf1$zoqA63iTn3P;aC`@|Y`bMOFt<5;D zr2OvOYHqqp_|C~we0&bOc8L0t`E);3XyBUGH=d>Kr0ifm|Ax9~FzFGI2r5NvwYFLP zJNBxlmjco9a8&JpoXTRc)93oR3oc8C#A8#}&G_r%2694Ca za`p7m)f&d~(Lb3Q{=5C_cc0_*Z6y+7`?(IcTU^obyO8Hx8!=0xEIr5cOm0SZWCm*v z?kuzTzV+Rko%j|x+>MU(-`}X^R#rAQU2r!KI9c#|9Chyo-O0N4LPza>rXIPR);`nu z^X*@P23zhw-@jzvZWg@9*)MaW6h~Hl-d9>|nv6up{C6xfoj+b0RBk-k zqYt?Fkg{sgbA6+46HyxYfqe)h{3Hy`Hnb+wx8! zh!FK|C<3>#=ys*=herd+ZJ$XxtpI42cjYpqI7pY`*kbe27BD zluL90Tbj1VrM2$otbXK~lxZHkD~Hi|^wRgN+HAJ+-Ry}>W~(Ntzq7g}daGAq*h%`f z!TB%K)7l5$gBH$QbY0x6ogYna_}`|7uS&*gRZ=jlZDV#~NWr?I*j#}8XJ6ciLv29# z#nN;Tsig70ZHHmDPy+qocyya`w%B;a5*eHqiC?QT&x!l!*Y1noSXfIi#?<}G&xkwjg%w+@t}`(ALE@J(MHyfXG~hIN!J=^J@myh4W?82a2(`UTdro*oeU@QZWyS<@X$ zJ*uvir6WYE&CJ&yFv|bqjqR1(YcEpo+K81X?Kzsb_=#i=w_FULsJa#Ap=fm4fArCv znG^dOW@@_a!|I#-(s4&LGyn6xX)kIULZcrq^=Ek&!V-k;p3aD=@HWlWYsI;rpR($$ z62{v!u~*(aJVKGDH(mOBwkJ+VHc9S8Qm8j&sU8guWL5iqPNY#W^b6)9lCT}G&N=UK1{%}hzeIZd6rBfZZs7D0&JwW;?_zdhQF2b6>h7;oMJ{=tr$n#%|HM_4uiUc|T_?Y3&^JPAtYz8mjZzyZsMZD5W!UNO-%(PP-g{ncAM z&q#IJj>cSbblU&Hj>*05UFa_g+n8hPsOFN+dhkMOUphOL{>QDq*RZ9_7u%J`*MvH^ zF!#)1<#)-jD~mcQR6R#cYyamzYR$KF%HO{mFKAj{oSZFDbkxnw9r6gY3b~lawDbLM zCq}MHQlkZLi~{BJI^|bb?aS<>g>M({s)41%jxe0lZF6Y;&Pr4!t1$DCmD5$0E?reZ+osp}Jf7NrdvJZYVQ{#Y8^LIRcVrF8E6!HHj80DbKY4fv zH9)-dnI&TSzE4p>W-WZSDy%4)c%yT`m;G+35UNe1*nzChNe9ZrNix28rn*F5qPJC@wv{#^) zmr+b?4}WHMv;86MST3u6u{dmtV0AdXxsM?O7fnN941!VI-fX|Rid>&*{#A_hm zwlpeua-fa6awB)yMiNn}^io_t;4~|Dw@QTgQjm6x-GOK?>`1R&c!DMM>%vdZnSb%% zOVzzB9wTKb)FVa2*9B__@p(B&Xc+$Q-KCxL`lz7$X`;KivTo6n_ zOvvIn5@h#=+&rrU0jlw*!+%_qG&ZEaruhj!m)KHL)Y#gv5<}SD}ey_^v%qHggJP3AC8t{%|j3 zT{CNC!ZwTs*!XS1xc_y#P#0KNQeEvPiLzrSXh_HMxGENP;gVN!bBTzO&^44Jb@N`c z=y6?ralBz>+pFOY+=?YcRLLt&KPRv0Lk8!nX9t?51_urV&+#=4r$Y>_;`xH*7v}xCgW?h#eviR zeqM2QLinBu|l;m#G{$z+uSn; z=G(4R#*eFS3Z$pjgj;&zZ-1wDI5HmuM+MX2?K9i4andMMqIP%ZXc(Q-K6CEO*7~LZ zP#k7k=9*#a%*SAG<#D?7(+f0-dj~<4R;n|R6_KM%>pnBHm+rC=~%vLRn z$v%UEwrD1oLcKcbjwZ&d$kNs7w&-6a zyVGJ4n&Z%f#4lTM6BP-!6>IY)GWx&{Bw71uJ?lvLkd^a(%gT;^2iKx8o7@z1f~8N@ zk@6>{jNa<=)a7}XLU6~k$r@xXtB!Y~QY>B_%+BBcpS4(|HIvIySM<7;Ya0We2u@1< z4^_-2L*2r;n6y)e`5)7wWjD^B;gtK0I_>lcqZ8tQ81jA|KH2Z)gI-15c-=5-ga2f>1Sj`DrYhdKv8ZipGmhIk zW-8Wq5yF+hK)S?0U|ad=W-uqUap1|GLz`PMbOA3D3FpiQADy20!&DA{kypo^@8sXGe<0N^PLYQ$0(wbF=xx zy>4uXYcG!PH22oLv5&49Mt+=@^_B)CgJ8a1AX2!CkC=M+$1%O-r+o2@OF;ny6F)F) zC)Ou)&wOXm41wVKmvIjZmvcg8qw1xrce1?t*bOON5xn6ZL#^#Ai7y<)43%|u&YzfO zr}ac>YdGqDTMS8Hq|oz+HwWr+>`Z@pEC%w zx{r_MCG(Ff^z(|GNb|;c1O%5)(DeCZxKBFUzCU`{s&Y5)tnI6RBz9j6P-*}4&SsWS z`4Osg!mi6qcX*oWK-KlENw7FfNeLgOp56^)rAeB^PkA%se{SC1Sn#qmfjn~y#cO2EU9!G-uNQnl1atEMOX6UprDQS47lJi@;0x)@CVNVtVg%&KPuQ z;os#_XnT_|B^CRs3@(nvlIKb=kN_bGu6Q|NL${TM!ZVeB8MOw$gogN!JJv_SzcSQ;MKf?FQ;lSu=@ z^~CxP)coB33d}1u)&%;z%kNuVW)A zxHQ|C_2Ix&s;te#yh7I_Hu6vD`bWiF;{f2ySJrNgG_D_RGc8>`vGyL=^oE-F#E?YM zFf!NXWa5V;N!yB-l55C9&ZAc6F;|lG7824u4sFX~kP=PiI4Of*kHtKn&mTm_sLPBS zvjDsrh+ZJ8*D>_@*^SkZi|cE~oe!MJ;FS4!h5*&2XkK-)D;E9s8mNR0jvV^3d-hG; zG$=*5{JO#IUaNfJ{lwbcp)3f!)DPxbMVT2ow-1CSt8Q5P2&2OAUVJ5FZeiT?#3KEI z{*tDKw5t0=R3U9L^sV~mRZEtxkGo6Oq>CesttmUXt!r17pNqKO92%3n+S$U~*I!*I zIsTxiZT07I9xo{g=>cFJyOd5eqDrbfU%0Vnb@*ei+Gq(avMD>3&Rx=sXPWx+l>urW zlVK6QF@|Uhh+TEIMtZL6J^my}nUI&NOuCogXDp)McWusS%!j zFtDlE;1{_50kas+UzYJxlZf%>%Q1dyd)v&P|M68i{HJs;R30puvxesoji)&pw3_3o zC;nh7GD+nH^x>SqB$Q6Q#u_1vxK7z z++e4CNMCiQ5_Bimu7gImwl%=mZzRSRif-{kr;|MTj&!1)RGff>t@kf3@SJNn3(m%l z@kUQ-+rzcwr~5v#Y80%kZBRtceR@4lP*5yBA{`11q|?E^s_l(o{L!cL`(!(m(Hy(C z3Fe@hF`&*q--e$qM~Rz&K$*_K;JZfbV&#=`05Us=(HOE0z#1sr!Tgr>;S zP;f{vg?Krot2%Na*As-v+24#SpMws*spBzee#HUC&x@Y0Z>OuhpFR{XD@a>nVoa+F zrKyOD(~WOPl`$J9E84<)1N2}7$GD1I69jrK`WGQy8njd?9lo^c!fe~XY?O`fMy#e< z7H_7GY@Ff6h_NwLlOCAG75Z!PdA-qoewb6JV?@KQgk0L`k(3aMj3#AIf-nm#o>;M! zbegWNg)YBTGniuVURpR`FtUW*hnL^Bx;}2A+mPmWl^hB8ekK)m9|**RlozgVcjK2D zZkB}V-ak^iySKV;Gp`h0K>D^EK7nz@?gUpaew-8Tm4{?FVCBz--psziQ@Z;{5f1ig zSM=47onk2JcGMHSOKqy@FDs>ZIf^>^;^Q?#HC;lUJM0{3qDig&O&>mVE22J}Z=r5D z4|CS(tNY9sd;&I_$9pL%w<~RHyEmR13`4Vxt`r`jQ>F87TeLEbj^&uwcPt>fURSb= zjpEKqBckDivutYCPGq8ZpTvJ#?nj!+UHEd*wl1rq;mAceiPwR~X-6(7wLx`w&EUgC z%zjO*OWxRI(*9k`>}}2F_m;nron3PJnykWrq6bh}=c5TyqGm?pQ3=kPTL>l7_F&rW zhqm*Ex$NE#ka-{!D@j-z3NFlN7Q@Ime+v2Hgd<|*aEor8fp|iivzH8$myo8c@uH%( zFg?3XrrWpiW;yBgda1-{6au4VIIqvnb*CF-ltkT{dB6j)J+f`#QVTUrkA95VwSlDw zl;h;d4dc(i9=rO~FrmLqH}plpQPHNSbV)i;ca4ffAJa`Mlcq>zb=3T5%>CacV#RIM zJ-0E=%CoIDV>yh%H3yy`pA1Kci)m4y6pi8j9?`EZ*UeM&)YgJ<&tki{0Y6$;Vf75%S`Osmz^DJ*Xc^Z6gsk(l6q@r$b6x690yqD>C0?hYwh=lQm0^SWf$I?3l)X3bC3x+p(XJ(6vO^JX1{8j;vOoilZ^l9)~1a&_QfJNpw9C zW=6@aY20W~3(~YF1SK$kl%wzR2SFB~_2KwHq_|5aDAQR z3290ib8}6qQeLioyw)$)wNQTmB3kG?3~yPBG7dMcyR@Cv_4|vHS4-4M<85;!QwO_e zR8&YEE2eAgB}Vahs6>0oJ%rz8t=2lPbwH>D{XiDg!*+~>%N5BNd@cvqpHjx)rsr=r z*>PI?XS2tH1S4<+tKxQeZb7IZEsab^IXHVVu>?PPE|{iXpgT;@*os&$t%AmA6Sf8P1lndw&kU_QQW}>Q zTvra0(UOhxs(ZGK8qsH-B1&IbH!je$ec&Dvtu`vv8%l|oW2`_tBqi!oL%2G`x=RZa zu~DPh(~*(c_F!X8Vv152Rt3*m73<2FX|J_$E6-M0s&Z}8Sw*yu2 zp*5R%Par?o7E}X&_^M$AzGAL$sJf^+!~%M{nY6N!su>AlLj*;>4VVVcHp5^|4e{Wq zKu;^WhJE}&ZNBvPqvd0^T^DW_u>@Z0v9o~n8;IB&#I66TiinZ}<3JHfoRjOnCP{iKWfz>*GO8Z<+cEo!BAtxPel zGzYpTCeq*92H}^DD5#yS?FvkWdo{!7LeUECeesBVMZRR~CMmT+aT;ECDaTIvym$1* zgU^+>{FRp>DQU}H6EAp?L+2f7_@U3MyvbTfy%;606-8(~mdaxw!ogu7RH$XVw;%GF-fiRT@fGW6!tlb6Ki1-?457|Z$7PFy3Qpl@<_0*OalX_!X zrF`0YUO&yKz5*EJc2SY!;C?DKcF4=dApG>5)- zaE-5TOpd@TY$ACaegBrB#pVZrkQ*jZ2?P!oiHCTOTr zy>;b8U{2p|ACWR5HLa$>TUFP#9x*^ZH@_&Pzfk?IH!v4Bj@HlAvVUH!ry2r<2(jTV zLOuQ564AE1XoJ6t8dhnUf9H(G2inHI!R%1E7PZO)9UA2LJh(Mu&AftC?4$j^ipC|l(&M>ga5_Z^lQv+_Ov9j`{N2-1e zO7EX9TOa(~Ot4#1I}}Zm;mlxYY{GJ>gF1)|M{85K#baIF#a4pdX~KJDiplL*{tI4c zc4Jjo63qcyMumWY(Fd;vL8(#CYu_jnd{Gci#Bq2 zbTN6FMgKQ$mB8#9u=hKdhE~K)^<|(Jg9&N-rf2S=>cgeX`2G>{>`1FC6Crp5arM6G z?nQbkXzp54!0@C#RuTD#+P%t^)Yrh&19<+`9p5}EdCw{#KrLVRP%s=h6n}=o7x*=> zb1?7)AI4}IQG1(?@eZLC6Y)^3ZAHpYeF&*~%+?;(ZH?s>6*(A zX`EaZB};6}(nqAm$JypfnJMC3E#XwwtDu!;`mF#(r5Xd*c&*8qizczkncZ(F6f0tO zC#$OpckDY2!jr=CQZ7TY&To~m&k-KCn!3Q;nR)s6G5)s7r0(wfPSLeJBl)FflE@0Q zSMtG3N$kbni=+Pt0O`FUBEiz@Hq{Z$i*(RR4_~b6tLR?o=Pto83B@iU!I!#@9qW<1 zn^EeAoCx*v?+YSxXHUq^pFviH2erllBnr9}v!^OX`@?A>dbJp@9T}HxK_2TF2W_xC~&7gDNar}aKxp^CUi?;Z6kMkMpW`6c^wqPC?YSbtV#QN zql=`PvTCH$>KCFKv!siH`_+r-Xn3jJs5z`o%YNKlS-AcJ;7|`fx+mDfvPq0obrlq( zpk=3$DgwH+M_c2BE3}U2Bth+{I|vOYk|tg(-49p&70GM>*M-sXxq+zhd(y25ePHcc zA0yiM$BAkryqH`&8bov8tllWXgRfi{N6h6e7>O@h@_t0C}>iltZ3Neq$t?{_IemZsL>wiRX?x5T(qdLBYo$g=rIiD{6Mo;rW1tE z0QMw1EqG6|V?xGFMrUwM;u(g&YH)N!F?QxMQ&l`T-zi+&@a zH;Rj+HKz2LyXkS1%tle2BzDubgkK0}vkJ1Uv3<5fvk^gD zcGtvSQMhLS=uzv*BF$ihy$F8?*-zoS3Gm<5%U*V7R-&Sjj$n~nA^4%C8+Jw(DPO24 zUf-Tk6pe0n$w!I5AU3aj)pFN)fCQgY*P?>DAJ@m*Rg0(p=IeWkyKdYAp z{}^p^nURgqp)gqrwd^yYY1K?6EA)5m+0O8o5H8^?tatkHn z&hgA|g|biL_NBx{?Cum;9%P*2Hm|FLSH2muiDnQlgP>6;PY#xv5NDWwAE?FS=Ca6+ zfUje4;Hsi4Iqpf)P&#=sKOt+c8xv_MrWs)7z5g^7^9hS;eR3fB?E;|)DApp#Y-ictIO?9pK@~HA8>{6e*|E&tYsau zr^?g6+Y*{|Cg03u_p9ojG=aD+A4q4W$`4mKwU(ENO|iC>1sE$FXnOEmEh@($Xx*t< zjcQK)S8AZPx#eNtLzFRb=y)j8fq3I?V`I3yd!qag0qXmhB*VHCDRE9`M(hhA zK4w2&u;{-cv#cwymMwM{{{mr0?9K=(ZwBAH5Ml1ZY`uA_n*XGUh{t4=0bRBIa0m43 zY|} zWmz3E&-3$bfN3VG!)ME;2_r?Qo;1RQ>Ll8+-mfWqV0Muq&;M)w0z9QB4f7Pd%bZtCOsGMp2%R`;3eYKT=#!|6V7Ofhait5l zB)k!rHk5XKCgbku+_Cbrp}T5jhpb8gF2*U?k&{!m z*Si$*^rRvUCf?`v~cvTUb8 zq&uRn{^hLm<>e$tSxLx3MQKiq#d;06O!s>Dst!UUWfnEi3ZAP6T|6PmHu+G+R0SI% ziRjyDPmn$Lk*HGPv90&^-EuH5QG}M+H0<_BtUofAJ~QhZljqwE0m!%hPqL1N3fwpFZ!V9lhPFJ8VM zCOG8vsnPb87uv{h3rjkNco`9-{I{DVZE$oXO&;YSeFhfFwmty#FDP}L+RewfP5oRQ z#T2=qNT=5CS-J|slO%pj;cS+on?qST2oUZp-;|y{$Fr4BS^=F>oyBG4k{#LfSMFk6 z*8%Q~DKIJDpy$ER%)m=>4CZuY7}_cs5Fu^NAe^#48|7eL(@FXOw31ck<{IW@&Kwa% zBRa8E0(47GQ8b)W5LhpctjnHmh(xZ_8mRQi8hZElgoxfzWIyYMe^k9;C1GYNH2*Xw zT9bg|5Y4 zC#AcHeguRJ?-I}RP7<6Y?fv-)oU2F1e?#g8brOUb#BMDj=VN3_6ZV?9( zl~J74FYHeijFoVwN?!FAH4(H<1H326KqBB?Eu8=qb`L*0loi{>KE1rn&G-ppPtRaZ zeAYrqDmCjh4?hw_(IPMI5Je=svi2{q!B-IlahLXvw+@wZx)yHRfylxGRVe68F>Sac z>r{v;;TYUk8f=UJ3O+!9b}`%CjllSxz<^-hOm5@Z4>W|)jN3V6K&XJ*LhvGN%uSw$ zr*w%6va;vi!tn7_PWt-RYQeLIh{(DrxqG1LOk2nBp=(_4?bRoGyz5b9m30A-&}!?W zlT%h_a^wKRo#TZPoYKr(p1GqwzYn54cJT+(HZMq5_2nZRRzCdKA`Yki=6S2B!B=3T zU9~IdQA(a>o^%sc!IgJwXyf`R!+inxhcSEK$JgqNm>=@9<}gGBAL#^9>?}g45467Rvxy&|quSD?hH$>tR|7!VP zhF_UshtHg;>$9y${+Q*hMuiHk)v!TppB}erRc(j*6mwuLTo9y@ukc@yq$BAm#2)|| z%ZOQPetgQ(Hn)ZsoD!WgAOs;|`ESuk21> zK>+AE(re^auPT94-0H!USm6rbD@CvY{8cFSr-(53YVEEfi~wfO9*lU!7~%~)DJ~C% z!&N!9qEh&*ucVyVBM-ER*3@M9Kb?%#9z=D_9;*mQMz66A^Fzr=pDL^CE)9}O(|>y5 zvi!QBlwLgpz{LfGh1*b=@f00MsQ|sC)6*WQ_m!qJmBT;1Uk;W!w8FDyv+kzm!LU;a zHO`E^yG{M`hsS~P(8D|?8K+Ur+>n(Vfhe?pAWKs~1md#1;#9J#mcXAm?>Gj&p{Tp% zR@mT>-rZLbgI>L$+8$)lRDKh4=}%eZsJTS4VHp)U0S&BB=^{ov?fGL2`4imq$+gB82hpN^(S zH#{G3x;>qKISpssczt)T@mojG>a&?B-dHmcT4aEA)?)aW5Y@dB1w32-4IMK5Ix3n2 zpvAK4faQH0%q5Ba@as*w<9523IB`C%b)!|+U&o_QF8x}$xI-D-EL~w$JMkOBIqQk= z*ppjNxKvdQ7yBj44>V?qDYDh_EIw*ywG_G}9Ljkx_z6}EawZ6FjpfvlEU`0PJ2BVG zYcui>#@a-uK#D4>X(0XGD+%=HU=isGZW?CY1Y~r{keQy|G+}5#LkhX>8X(b$w|{2* zBu{5WE3ye_2GTHGUDhaLYN;`p8^LF9q9qN`Kkm|4D66tW&gA zVZ5^IK*$+B)7MTGT2Kb_odJrj23Sy!QN9LmwynIp3&ig4*bhmA#%Xe9Mh+j-_J!Be zB768pkLC7Z3Ju%bFejMMaP70SuC^n{B#i+t6|wGIQdl%yYegKWT3o*_uyOKwV8>t; z!IEL|WV$0Yl`<6Xj3IcoRGqGscWD3_=a1eeqt!En51@lxHx@uQLl1LGBLSM?GM1Ro zg*)I@?+Y$CjMBswzb0QCl6OUnMx*DEfp5Z`VZD-6~uS!Rs_Laj-X1lfsQ8S0FtLY21XBL3U2} zQm1+F_M8g|)?~}~tiwV%DI85d_%Vu8UTzf#(`RjyrL=>QG-3l9KXZpS95BQikw;-^ zp>+71j4@RSYu2iRT`2IN*?3yA_IX-1>lDvP)Wu(VQa?BJ8i=qZ+Gkqsx50UIADjgZ z5TO)TJ8Re|?1c8=-@+H|Q^u{ZhMD+dYcu9K89QG0cTSUsN=s*+cVuH=rGfA|+{1hb z2sZ^_ZC@b0=%p~M;U>m;>Tjd;)n(nXcJnl&mwIUuz+nZPK>%I$#%c#x$9oejf}KFF z82UJ+v9L5JiN)kChDj75LvqoyS!>erSXgUUlM`MECG_?A5_+|_{LmVHPgJM++q_~2 zY>7R|2`Ysio(KB$qulXF-R#-Anud^&`D?T1$4g&_wvs3A?{;zS9%emELL>`wmwV-Xa5rtvscC&X)?;^_>|5p$lsvFFrL_FV!xR9{-zC2Ud)n>rT^YvFGG#wdouQ3?y7fE^144U&*!_li zS2(Pnn~d^#Y}M3&O4LN*>nf%flqG}GlI>t&Co8kGHL+plPF-3;PGD=f|4rt&gmFjb z2khcwhbRGZ_!s6@$g*zXDv;-9Ew!f@DAbO=-q_Theq6aZ)X#t(^+gO3-%Y+OGkfY1ZA${Dj0 zhs}aq2!P%z1e)z|5E`?#banFs(ASxBI~{nFeJ?TyoA#qQ!xsb6gt#NQeGTQu0$yhH zv1m5z+A`h?x89MsG*VPh3>p`_9#GbnpB6_P)YJ}cSLeiiKQVk5ma@|Y8O&*d1B~!> z2av3TUBxuqe$Wc_Aw)2mSiibR)87gKD=pHfMC8+Dr_TTpc=^q&Y5+E#s@PiyZco3% z7#j>lvSQ+Tgewz0&=?btI)9D&WUpf9V05~4b~LqT3j)I>zp$+YDycwrS3JzH^kWq1 zkE2`PiVax(8h$r#kJC_x7yE>=Yrf0|v*a+*gJWbCwBBc?tL96H$#C{T;3srNr5RE0 zAglZrEe0+67hm11PW-{^=G<&q7!nRpZoUBdrBDaQy?Go=3usOWU<0ySt3w@=H@CY8 zXG+2VgcW9fFwmun28+SH6s7&}LK{TKcU!ZNe1ZDMGKMve5=BfCR$!2%XQ0$V{ar4N z&0mJm@`vykmg2nJfoh;AmqT0FHdjPs~<-XV!uu$Sv<2MZ5t<`7M zc~1z29CtS?G>n#_OkUnr^ty1w9p1pfB8iSB{QA+8|2X^kdqrSIXUBYtK&#BU8(YfMNs!r#I z4^>-wx~9^{^(B9Lr!29qFg3JF@>}&Cv2DP2tWpyIVFr+nGjzTwvdEyMfdI&EM0dW_ zt&js$$N$(11~$yg9ms|glCA?)bh3L0H)WTC;QDtiTtB<@0dNi>ClLNHCU*hQ4OHsx zxzfh!R&5Z>4ubYA!ETc)`jjRX$J+V>O*_!-R5Ryb_pgnAygr@pOqr}cAC)vwZ!t*P z_M;B<>*U>2me9iWklYtFA`xn)w;wzQXEk%w(JQ|NrmuE=@Y%!7|LA`m(6a7{IAQK~ zq&#imLLvg+3W6VS?fvU2BPB0-oyJ+OztV-Xgb?Fn(1KXc-E<=ESoA(8mO08JIS$el ziR+k0lX+p6a4c^{gkTHO6M{D6#c6~~Jz(TuS zvnmjL^TiEDW1BCO9U4rFYz>#!h4OrxfnfhN;V^bJ$JR_FwPZG@5e>1p1@~URW=ML^ zAdU+{{SOBXm8EiJE@4T*iEvEr+XQIDx<3F?NX=@*@ShLU7Qev9y-je0ng|!#qzfk+ zt9@$Ev?%g{CUm(YfrBl;gtg}1!*6`wLu~5vsrEFt@;r^koTK{*)^;S((dxOqjXiwm z+BVxms2lHP7Egn`UT#jPIUh{ZPFhh{g?Ao$XT!Hpzg|}Hyp&6E-@`sGcG#aR2sdK9 z*sHcN92Spsa`DsFens-}l`U@5a)OF^8G+Jqc>^24^K%NQ3dW!HrTBFM`yFz)W znaH6Th;?X~0+L}H)ro;Ic&|D`19RrUG!27DFwB1$ZQl#a@?zbJo+`YiayD|W4i4|8-{BJL%&*ZUbcX7$E?=kjZ&XB!jr7EHJdP| zje{CBD0px?y~Cai5`5VTao1mN7>Vef1kAVRD8s_B9_eX8zLx)J!cv$~kpK-N1JDkO zc6q)4e$qWav6=D_=FhNd#OxZbLZM$sqP5PuBRME8kuW7qGXiC;)RxCI?FbnyldB9=@9^cP7KY#jJ zH@GTfF?)<;-9MK0{*P!H3J$2UwMV13TJf{P#~e6?#0Gh_Rq@5zXV;y+azG9gnHP8o zo~(7{3N+A86I4QkgMDpW1L5Jb8E0|2k!9TsruG0RPEC9aL-uGp7}Wt&;YA@xu`q+2aIf8vh1^55?QNJi2LJ%dA2 zFY*@K?l&l(F$AUH_Hyuje}q0(*59aH*$l=OW+ViMg1inX56LgEY3vi_hKOLnyrSey zksU70j=jwXVjIRGdoEXUGf}13Q^U}bZ?0_|jZ>=G@r5u-(N$+e0= zKM=6RyHz0p{D?C%5*9KQm7X#;JIYJvg(dQt5S)TY;vI_)_SzjoxSY0^+ntGtAuo_> z0*to#{PX){pSaPMcX?r>N@r5m-X#7m&L0D}b`9VUM<7wS8I?v6cMN~$g(BC14{c5I2uZ9(TCRs;2AX?unz<~6hvD-h(F9sXsb=slWv8UI z#$|5^Ltj%~-Zmrv4{@jXy>9UvT@%lO#=?`3INAMU97sxEbzw7nD75!T(=Y%5?tTRn zXBn8*ZkCYi^Nan2X<4ihS6MD{_9lj$$?@F>&9aVq<>p!x$t|At0LTm*V#Dj*>G5w~ z9RN=9_5Em}8HwG&W5C-9*LX+CahGSZ6hnj2YsF02kMv@qtN_d-+;*?e^m0pyXmkqz zYLxhkNvdrz9)!MQ(e<2Hovb{c5SU)rG4U)E>j*mrYq($SisUqN(JFKa`r zghBu)+Pt_&Y1_K|M*Qu3I3VABl|4NtOULl6nQQ$ECmQy_no;@S8sNN~)1i}^-s{gY zWt;ZL#Nw8uI}hjYr6mg!f+;tlh-Usho2GQ=97_s$QHlGP)PW$aUcKcC($T^0g_vU~ zeswi-CZohZESTfRN#}rv=JMx;=7#PzR#nGGbNrTw-p%s9Q6i9E<}7Y|U>hI@Jw2IJ zP8&AvVqTL4S*Ad6-3Oez-`qdXEZ?JCN>W9w{4(V7i3`7H<^tgpW8VIQm9!Cm1^@|}>_(ZzrDb>`UhjjOcR&|a8HR-!YZ2GqlF3*muX1ExD`)C+rP zlpj1vzyY!wZh2t^$#E0K#gu%SF7GrCpLO1G{x=1{_PhMOpbtA~E0&M=7GG&w(E=w1 zE^isb656hnDP|M(t<;4{a$aKyGC9pQU-jBu@EfT07E}-^?IHTo3Raf_&pB=X<6M^T zlh`Ta{7S0v{BdVpv}{yj7l4*uhU@-mei&Z^4drmU z6c^KUQ)}94Iv5M6+xi-SvUH3fpr!uRQVAeK{@G*2p2Fpb(Wik#QUoh(;bVX=g#rhZ zQXtiDCIQU6e&njI0^YPChrd~O-%T$D!S4&XHISHfCRYV*d^@Yg_JHhXE7Vln>flW`QFGi}x zzMancOXP47o2Z&BQ3M)lw~Zn+Zywe1w)t0Ox`})N``{CSBaD0PCulEKwELjenLlcp zbsmsuAR~U6aUq548(_4VuK2Jw++i!A=-=^G@JXrnm;a=JY~sDJ?oF)`K1cw-IOdcl zpCz1zm*y~fX!3!;0QTU3hE`I#e2*zRVeY)8u?iJk?^HhQfOs_=YT*nT|76M*pu^_k#&)YhY+u`CmFe0Jl#oBkh~ z-ZZSKbNwDZtybD2LR*dk%3zNb+M@*|A_OwjV+*z-skMqA1nZC>vqZ=YRjL$4sB&b? zP>Y%(lNgaHg9w611~EWnN`yc{5+GzI2?_7EzxV%%54pIq^X$FvXWeV9dp%HtPR%-! z;mZQ0P(Vd|YHh||Iuhux-~U>sN`JrqM9k^lYKY#D+`6zM00mR+EQAdY0NuRe1|cp& zK0*js0Uu4^B_x{uR?E`wwpFwaZ&T0x^+~^U7iNPU7}TWgz}KFL*2JN$*Xl(l+g!r} zv&b~y#YzO$scze{5**{Q7k#A(Q3$E z40$l{9euS|IMP)+E<3Tb`oKLZDRrr+8UmJEt9)3Ep$}Uxu?lBzEP?QnirJ#N%{xLz zORWzkbgH>w($yY4D|=aGjO%)*v48pLp!`(M?+~)fV5KBmw>{+e4zWe|)NP0P16u3w z$7sML5ZQcg_toZhGSlz4a2?H~BhXlzaD&k9fhXX1;q?1v?)sfE#Pa!$sI9z z=ORz^Ve;ud{JuS`Kvi}_O(|;UK3Pu-cMtT2@gxDPOpVS9 zpy)*Ab^!PM1aHpzD^6VBdNryZhWD(G5KkN^m3U+>kZgYs-q&u(2L|sy_;v5IM|Vy< zkDdATWJrn@|8;iyRWb9$pyw&ptV&6R0D@OaqF3n%L1iws+nnjtowh&cc0RdRhxt#a z%_{;PkM_fEthZyF7`?_-Msmz_!h|{A{v|q1(9?Da1Ixdy-q&u%%_#)q9|8(Q-GE1) zL@|t;BMCnfhL11Y-V>5;{pHfBqXVaB2!+Qp6RG4+o1F%$R}FEYf{v`k^NDOo)*03w zNC-~Wn_9f@tB|5?Xm%gN@ZVa%E>qtoNIR|eEGQZj#X`f%!^V3Xl;YDvXAhI-cKX}I zC#Lo!*}P?9YpZpAtL$u>XoX4i#1VC8gN|2Bq?!&w+_n!2|5K|lDk zwHFxq6GynZH201Sdf@v6FJ5=L=X5Dp^k0Lzu%1GD{m`mE9^xr)taFQP2t*>G4EtA@QVX)pa0;Y zW^Sx34+pLS_jjL9E7vp2!$`K5+TEim2>o!~CuL_`(Ju!(TlD;q`~FYd_sFA-qsHvx zI$e2ti;qhS3Zaib$^hI)2zJf|96sa19@U#x0x=;x{}2KQQTPEUHO@=+8ZXVado-3$ zVxyZ;^2KwBRFHb?Q{M~E4TfW79%0~S%6m;y)=l@X?VM(!n7y;|ARMTvy>qM>ki0^g z&_5;#kL3uOS;LG-NDC!Bk1p zpw}<32&dJAAYKCf&6n2J@3_Vd8vytVsF*YZ&?eCjM&i^sfS&Bw(;M@$~7q|8s6fja=B$$XH03hDX#W{ z$m2|74)U+($p2DAtH=7)|8Q$Y4^n)XG}A#&Lh2572%Es(O1vqK&n~V9HqH$NHJm=C z1<((VW=c4rZ#U>*(aw|A=F$!btF<=;GIO?>u=b<=SgPDK3@WQGZ-2v^0KLnC*gGiy zZt_~apKW+68S)`ay(4i{@6159TVIBnopF0eGhj24F4Yf-Ejf}e5E-Vw$PLFhcqGFE zNtJ+JRHT-~GTQDRrze~~O!XlR%PNtHgwuzimgKydxL7F%xK+QKe`4oPU%q!PPX#T9 z7&n9ZZ7(}|-_|ulQnTx65b$XC{Ow%a)8cFUh8RJz2I7ep1JdI}pW#zxAU>rVN}7A% zi6`EL;RQD<6m1*mVM5A<(Z$5pxBY@lDDh+BKCOxgQ(x+f*FhN`UP!s}d3Q=6UhtXu zgZq)YiRaj=#=21H>%skJiiIHb?kFDVK0`9P?ZqZsbC#<%Slq+6rQSVUe4`gzl6LV!=Sn?GXG`eFU# z!kw5B{lGM!N>^_U8z$cqY)#Yk6$M%-Qr&Ce4YKkkV%ejY(jKurBB# z39TR``~G;Fs!>+Q=iw_p%Ju{{1bBbKW(F!`BrxtwN?%I7 z5Ip*1ub}Lt9)KK|3tR5=7_x%>;HaEG2p7;p{T`X#6x^@(uAX3)T3!%KW>INVm=pEr zPtaHQAiZ%TzfDg+*wLR-f*d@t@M$KUa=QgO4Y+%@#2(0?0PQje3Va>DPFMx#YliG) z6AyqK{%r#POf^7+;*xGGU%N@nEJ=}wvKMY3oEs;L+4sr5l!x#>hJjW>DTu?n&lpou4<9yt4nv&`M-Qz-%1y^gD{7n3pSMLd zj`hcx`s?eo<$lJK+T*2^ljsS3r6gREMp}2no9Tc8p9)W5aTv*m#8Q;!& z%9MY!a2wKkTjsS~yo)Or96a2&-0GQOuWTluYncERN|RnYXWu^$jj~C8*|zLsaI6b` za^JlW7=u#mM7gHwb}@8w)1q5Ww2lk3!(Rd8<7uuz#uPx0{#d->)AadM_+d9tQ^5jr zZsge!dSwf`j{R5Wg+~FUKFoF#yc|u(2sLBN$x-4j`axpPIQX|3;~%2p#Z9!99ER0OCnMESxz?4ABgYJvAUZEE$i0(4wzCQ7B$}&|4rOIX$fmBY<7d&@-qr z0FSi;MZb2^y{&?@I{n^(TkmIoFjMqNYyn`drV#ed9D@%YO=_J59Nu@zbC!qwlV~~6 ztvJAsX0IFp4=^fn*g1;d%C0NtX68N_d>%^)FK_Q4k6f39fa~1reKtV=tIvQ4)#^zb z2Rvow)OGkZPq7WI!GwV%3&mruf-ebRChaX?tPaUR%CktvAjGFFO>J=2^cvg)h+jd) zQ25OAy5X4?0Od@8`ZR(EY=9G?o@?v9Va)ms|8p%Zb^8AO01Ggg*VJa--4<$`^~(U} zec5*HsY?6oeBHozK6{R*s(O{F&iQ+tyvphkX*(xbapIHpmObpwukurbjXsG)d&ViX zA}Li)XsY(mgHCZSuYaE_vl4+}5O9CK|#mUJM!N|DT_=5{braFEW5BQ@rYwrR!v8=mAj zMp>T%ld~{Q{@<$E(V93(&p_35)^Pgq^QVG$K zF8p9o-Wb~158FZCsxF%Qv6mTI*^$$-;3Pi;%L(Zd94aBdW&~&(ad+Rt+#mOJP2f;? zyUOiBXG#4(sr7UN!P7 zpi1JAVCCFz1ANEn+ch06lZT9^^J~`0r!91@`3kK0(`b7(sQF%R!#!VR_kwHe;E4tT zv7QkSxx2|p^ptWlXAeL)p-QU@1}h5QF?c_JH-1gMo%qw_^o;S}fUE-GY}5tQ6&d7o zDlk{#REFJse`(Bcs=AUhBR}cWSg!bVFxGh6&+aq8{5D_{!es{^mrXW!U$09A za7`!rQfdP{mQJ!wxVs)F)&m#!=4-oUgi`;P2Usr5-zr_6jit5QwWqT{P4U@4#>oU% z!Tt}el3YqnLN0#xE_MdPVNLtqq`tm5TzvnXJ#m}AOWRC}HV)Whqa?#6$zZtfHWP9{ zKzS~B*c?wXeG^z7c421r&4=|k+WE~>tUHH+x$b5-N?4Yaklo^}TCIjTmg>w60L z(T<&j5W&lYg*U5X9b5Br_B|B_H39>p9nS{nZF^wg{+Zc{9!v6wKO&mu6VvMHjue0d z;H)3>cRz6o-)$kznj%&oKk$W}DhavwbGmbRxZ34$WK3FO0<Pfmzuec|R36!q+h@d0LCLgwexW++in%d&U7X+ruc2>!XHXLE6QMQ3e#kS~hd1GGP?d2F*K5I$QwJdp zmwSt~{k;9Ul%@Cn&d?El6PV-KGxCUYCGHTNTwLF5uhV}D@b8BMn+2O=5#)`71XHJ< zyg0t^RERmP2nhMzx9v!MLW?2!R#b*`YguZ_i>MY*Lm3*NH2pU2`~KgX zc*avFIPyONU;eg(|n^Ltwo;@kzn}%6BsA6{}u~? zGWxUc@@|X}?W4~JQu*q;eu$C|pAx^^Mp~ZXB@A3p&FmdHE72Oa{Y4Z&&iLP0a>F|y z{Gp#X6-Ib-XeHU&SGQA|kOECN@y&U#gM*GHk^U|R zJ3f(vSAqEAE@;;Y)Fv=oRhbui?3s+bp4GjwTrneX9eWZ|F`nRl zPkqkvTEBioB#bItd8?Y#ABF-$5oHJH=5Dhfi%R$D?7&2+F?1;Ezsz~*KNVBC#9VWG zMMZ&}fiQjHd)NhbYwfsDUIFRXU!_I#nl&%<*CJi5-U#R_4=c?Pf|4Xu0>@hW#`egc z0nU-`p^fRk9sEwCud>xdn2jzukdmoxd1n5p>a$Powl>9H-%Z*=%+LtE%s-eHaJB{( z%Bd?R1NJ*Dr+MElPLpOzN-aAwaRn3jrZfDFYEpqdb$SN zGGqO_Y{-F1`%RXOiX*>In;X)ffT9!DXwT-(+^-Ie=!_B8gh%yF_Kl8oQ)o3j3NeSg zfEF%=iwKCvq^uN={1kLQ9FyNgkT)n|2tRP3?elH$pwFsKZBy>g*%00ATbR~B9W|3v6d|D<3Qu=g_XVzg#^l*v3=1A z+RLy>Zbx)sS&vVl2`)alC7KT-DyDR96BXl7Z5S(#Z8JIDF9dzQeUdW%r-4-dG&$gw z_2!O^i{F*j09{Jm!~|(C!vaPKBZ#a2WMEsP0+8WpjmBlnzRVyz;RmSV!6K`r706y83ZzA}nL*NEnVRJ>SacFg;Mpuew&yw)}+f<>D`X;cn-zC7!)p zoTc;pc+=}m<+U=IO_A?V1WL(fxn{g3E*Ldl24pKB9mL|mK z;!Nz|t}WciT%v9O zE!Wcamg_gGCIl9M9c&Y~_4=|^7MG7kr;pCQ``k1I#Z3*8&-qKG1=#01*Opw1zwY%} z__R^~_75-U{9_bqZwN$ZrkU!MsD+2V-$OuaaZ}OrT{Sgpr|Vth1&20N5RKT^*nJLx zHDHEJSVrDspoV=KpYeZ_JD0Je7*K{AW-4RmpQjA!0q=i+^CK*A(%XAN$# z5^wjs99~-b^HxcY1LtT?va1Gt9YFHIJX*I)bFFJr{+IEZYIL@>Nb7q6gCy2k$Osmr zYFC>&7K1z4!^f}OZfngqId%ZlP~%v{NQ3re5QRlv-RZ3IpyOKiSm4=YF-e4$Xu|= zE?A2&v4+i|80&59b1fnPADf_v&y--(?L&$R9>^lO8S%pDJijAKO~xXbE0f>ReC|%8 zd?n{Mna}(|JRq&d$|jFUed62aOKF0E2Hmu^M7uAl$4RlU6dQ4CAkJ~A<9ji^en0=7 z=_V!))_MJI?BIHTvBku%7CPHRq6Oy%3>qwo!(4g$A1Ogasp3BBhhv4?zpU<<{?WGF z4)@OGq!NOnBtAf1#r#czzFcdaOu7?k5Bhr7$cpkcXDoP3Dh)~s8+ zL(FZwSK>nn$%jXAwoj4pkW4FX;f@m~JpWu1d@&iJhDT0G2kbWDP|YA4rHSao7@~v$ zsT-hV=^j1)N6~RoJ3c(3boqtQMtw)N!KYciuW$I$4ME@QoO)6IN2KlJ1VI&uS}^eXXl z-+X~E1o+x~>y(+BCu)Y5#m#|v-*F$z)tdA2s!T(d!HY%0ZiZCL5{Xt_6BRTLF<-dM z>6wkisx6A^KKvh=y_}bY1o4)rCExCZ2kHbp_W`rwvw)EFO(g7lWxs^nNvG zOaao4VO=hdRkhzS3?_6vBM+_)J}hSOoX0D|qt*^A3MajilfrVAli`Vem2N)ObXY6z zK?XwQW%+{#l{f}}5&O#biZOm`T?;nH(xR;^RzDrygZWhl88ADOHHW=@fMJt3AB;%x zHDppd#E&N1)`>1Poe2+LJUrE7yM8t@RVk||T=_%P(Nr2d@B}+j2-;DJ2ySnR#d~6A z|FCBX-j=z__vW87!6zniK4rJrufrV2lOB;PmiblbV#UAyu8g&|poiYV%MHZ>K{&^R>R$lv-6Yzo-9^FRGV)Ia7uPw-*5`iV z#;q1FfOkPQ`H6DSC~vwbq{%*wl6vMqQZTOzljhD-yZKb;nI&bkP(@Abn)oD!>tpiC z+1ols0DI6jU@gnp(9n*m?&ncuq3eXH`N8dIJ<4}3Dd2xCZA9&}+#HMT#n0SU{po*aoV>9%Gd;xj!(cch%DQ4afCLEtO>0F z#&4H0a}|8rWJ*5Kw~?=$s^99w*O2x~yDaiqrTo_lSO0>VF#W(X#UfKEEbFO|2%&4_ zA@;L(Wl3|XnaxBRr{&7Hqc*UiUZIfCEg6o(XUi3m9L?PGkX*l<7-?#364gehGPzR# z_((r{;=)iaE8(HU9M2cGdeq&pNzJy(RRb5yJ3T3+nwCk!4)Q}Y;`hZ7< zrLOyk**#d5*;*y;5y(iwWWKUzIu_5N_4wP)%qAfhu;$f0=6r(5DI8^wC*lkd6c}b%d0{_E&bGh@ z5FZ~5^uVZx6(bQ8U7Y8Now2Lmznp|ejinuz7;AHL859f zs&_E69N%4M+?}J~t$o-j3YZ{>m)=mS%d6U(rl8|7{RkdKzz`~_iAf`E=9Mq!$lS@J zQ|A7|iQLz<;E1V`(Q`2g@Jms&V-Q+87u_Bm)2R3;6ZRG5z@b35CQH*C?K$ru*Zh`{ zubRle+>*R?)4%rqFCVM)hAV1Bn6g&)Cekzkfiif76m!*vE)iy;43a)d8q(kC0amv1 zN(~YdAM2!1YI)RYN{8=S+$5hW71B6o9_fj#!Ue%as2+n>bUl%Mv8D^6TkU8$+T0~h z*^+LwpTDsX`S}l%c_N2(@bAr?>l3wj%|abnvwXLvVtY}O za+3{o3*#N9|C3}xqf#D~o-$T+-hmEXJqZytP8*#hft-vi6`llyg!}qV(FdO+{0yEK!Y=M z;8WdsWY(N3uwygq7}rMpWJM|`lbYV#CYH-xDcn1I_?-i*z4KOf-xUyjJ&CG!Dg_=}8lkkxTzT5P1R?upcsRl^H z`O#cbN41yg*UL3uYp{7lEHXcd-zHAKVEw~6fHu%tP6#Pv4DF^+Ec*-F_QVtCdbk!u z&}Z?{FZ!S2vI)xDc)%&Y;=7+{MRp}X$OvpHuyHTOE#B!dk?$h;83LYMZjZ&D4;Ukb zM}@|^E^c~K=wdMhvEn)4>eYYxY7Gk`#l*=#XuifmvG&t{F^eP0eVoo?HbO}d%iGH; z0e}u2AhM=yoyk#KB?3BW(SKbR??G3#*eYo&5%NnX!97rkHxxR#;Ln9SfRO zf}|u?eVO;-p&MNvUiXEj&Lv*BzQ;WU_|vsIKu4T{0fTXpp~#SYf+jx2cQVC=UpyxB z{no;%VZUO_dCOFdr}p)aT-!QOVerY6U+(OpGFr2!M+)KLs9xsFZ_Lw0uKvDh95ukO zV`fM8+ZdtaLq%)zk7?dZ<-B1(_bLB)MGYc-sexad(Z_okow+igJh>5_C;X@8l@TOe zHAL1-25@yv?X{#;1(^Pee~?sZusdF9CC8wdD||HJdYCKr%xUgM&rg#DUz3lKxdP?v&iGp z)dw_vxEeVSB4tCMe=V)@dUtf`cQV6QL7B~CkAQ!Fyky~gD_JdKmu?AQm_;!V`cu;T z_#{@X#9tG`N`c{54Y;*x#1zRoH4TFQcJkbx+PkCu+a#0$4JriavZAloebvjzl<2Zl zrxXck*}>TW3eG<#bzF39@FpZPsz_y}bpL~{a8Uax*1ON>EK$hPhm0iG#qXO15W>R{ z<80YY*GTMf&raTdgdn~4^({JRL18(_!B#S7fa%>f_y z2L=KupGzZhLjd+sSzk?63X*shcrZLAMZh-wetPB4(BjyDO2pp3_JP<7!#rhGcIj#1 z!M>*9rT=x7M*r?4h`1k$Ns*t;6)Vr7rZ`QqlT_LPO@er6!ne^@RVp|Wv#J6I+IbgY zV;#+4CO>p=(sXt3e8z2VCkM8Mn@#4Ad8Z$1i*@wsKjQhn()<}tYtrX6N*E(VG>n@! z6L6hwG4P-F*O!#2!xPX`S7LqBmP}6an-8}y6o<#B&~^_O_UJo4M%d1GdyN5`-Wawh z)g=FwvEMv%6QOY{X-=);{dj*nKKsy~F3R!!ObA-{K&V1A$x%b3K+#-p%;wsLuQdV$A_vvHm z=oCp)k5a)}w#!C-z7tTbrcW^rd6r*Lm^&?y+i;ibx`@M`#BI37aT92hWLCG*}%mQh3S76?i zX&O}HczRaJ?vXtsya7t7Z3bdB4P}{4%R9xbU^n~{pQ^uwkb1+w zC~f4RlB2HgTpP0~ysGg_B1p_W3F%pzd;_YR76N^|oXDs^*sCymD^Rh7R%%(Q9SM^N z80G;|b(NKN{d&?q4^AtsP;tFnf6$?VcQ*9@RWcNJVHf{TQ++9_-;F$1gxbJcN?b$&4?EuE z7_dSJYaIt*=0x(^^3sPjhwN1%kYXyhEeDX6Yz~m9vs3ZwU=-390WWRR%qclbx6*lWuKelx z&KS7U)xj|>#$jkQNXA;B{2X$}ivl<*Lo!&olFXDB(OlVRtT#8Vu6AI4Ti3pRTC!AU zU=y0y)44g1qVVIYE>siCA~HwABvrx^inr8;c2vJxmA8v-%T1@*wN`He7tq@`$&}&t zNjGSM@cFr2}M`V!NRK)OV<5wD8sFt%YC^yrnBV@yKKfQwTM}Or@i=Q6?Q>j}N)-9|+3)t$DxmIAJEh_* z<@xb2_sgwt<&A@*8(fEy;8LC?vtPd7uMcpIPN$hm3pK`%;}&o{;KLas+Hl`Fvpg$ga%Qi(@O{Q5E8zSudL5;tP(yLnA1(5+;b8zfwEM>x9Z7*PtMb*XnF%X((s2I}LT*T&89Zk%GI} zxmTH3g|aFo8AZS(yG=y2qOC$f++6G=2pi5;xV^F4v>A;-l!P_gM^axJwZz0#S+t&QcFqh6Rb(6c1uOa!E#O8oko#W8g6Rk7zR2h7Hgl3xR;zGN3 zXjD!70jI@Mf!jjFj7)f^E^v0Rw5kX3zqXnHI&A|`Le*ikA~VaZgK9i86#^^iefTi2 z3a`6di0F1xWNOK1<@ogNjZY-4ylc!YszS&Kx;@MydkM5v)V8R^{OJ`8HWyC%!INc-fo-g$(hpgewPt{ZHtgpl}5I~ zVT#{s#uxZONkS)Ww=z9_w0_m#Wu)_c`LI@LDFAV98o+o2y$&7u#3Jv^K&1H79Ohu# ziXVE3ZPSm95T8vsqRu*hbn%P#?kuZTMsRUZs7FSQAKWIW+$Kotgwd3>joH&H=L#07 zW(}TI@l;*9*}cv}+rt#~Z$naf4@!U*tA9{edw`=C5BW(CSszWK`xXRyu|J`YyHL!x?&(d`;h`UE?%c2WWVU;(KwL9se?Y?= zr)6ndV{f#<+3^D2=x{eh@K?bQK3vqwN-#%RR(LVFw@dq{4@+~bRsA1O1sA>9SUn;G zwF1Deui@`$P6ug<&35;WgW#iv+@ z&z@9t=fE5zX_8Z7?UN)Q_gQSksTlp=U?>p^%u7|A&y$Pj3ex+)T2Zx<^?Di~%aTIz zRfa?c-7(fLyZA&sPd(}+lO2=I#cLLJ5M_A1Q{;zRGamX}WptlCs$Xxc^UriI_0cgj z)h>!W((n89(~EP{icPw^G!_(64=HVM_y9zcAOekiEbmdyJ)8TL(VYk*DFD$Xi2+-) zRfI};yq-E^@QUCfU&vTXhG7I4*d@z)od9fiToIYO3N^e2AlAR%X|XZ~{iC{I;Kc{j zCjQ3Ua(98VW7*ZYteepDtSkA9SgV=~j`HSDk2qPXPmVyNpce$!Xs(jH$!|EESV##; zy{lxccHW0gJSO{t!k*S&h_cS+T6oik(_J$Dv}nU2N;C(Y6V%^;)@Lt|t>)M)deZwE z04(RTPj-80yn3T1Mutja6bq%&lFefMEjkk9|5B?iVDaze0r&yEu)XwKLc8wj^`(t^ z0f*TYpUcqTz;Dd1g&Gp3PC-UkuQ8lU2W(cai~*hM%0v#|Sl{Z*2Zob`}h zM~oqc!!;u?Jf}=dJ{IV`7ZqSF>3sk;!0-$|x`bF>EhKJPs@g%17E(du?qAto z`bzqX@oh_r1W$nCH9PhFQTy43-X7n8R@y$Boap46)|g71oc5`1d)aZ_Q>zo9q$KHe zSKYaNzMEn=nuBVR3buG27Q%1JN^JAbiBW^-9OLk=lEQs9+Ta;1Oa5d_qO0Z4xfe5* zCY90uMyQW}f{QRfm_PG3%ww>kB#lcW*$_Y>rGs%~U0sht#NvR$hzu#~4=;@iF%qJ2 z2)j>&-{`u;KJisOVqbzevF6703TXo_9&uPbzWWOietZ^33~08^s*~!v2&5&0x#K=zRShV$|gq4OTLLn@@Gi&OfcM-fe3EwZ__n}*%n^+cq8ajJTis`CB5KT6vfLDj^HCslBzLfVt+(U4 z57K*~BY1y~npw_u##@FwCwY6DC3Eu+$;`aj08m+nKCU4*1igWRH~%rXp=bJMMUVF! zaWsyOcFP_XXqtf7@k1t_t{N<37b{{_~zF0I@8U`8X+= zu5d84m|-4lPgV1GW^RD7x6Zt-`Ks$RZan`Zj^p>an(?{f1Kw2 zAXzv2i#fx)0t4nPgWaZI2hVG6gZ~eZv*1U%mN=Fsd{#G$XxH?2eTcvHyvmK&T|+!4 zm1gQ9xPUEX;l&UmPw#XU9EtM4l=$q!?n%ot{5U4>eKu5}x{X~bi9)(m!)@S#%+s3C zTChVtliFMz`X=F#$ z;!?U#SKb&I#NUX zGaTD9IolH#59wb;U_F0;Cx1KjRcw`fa)+118w7a=bszxLxdYCAs9!u1Dj*1Ggj^nT z=04iwJ76dV@34Hfb`;gzaJO0{slqfxgD%2nz3vz^-7>tWgbuIkA z*x#a>_Ox~xkRZTKF#h?!1X0^x)ZdS5fIl;#kiNE_!+i3rvb#z)R}~>A0l_;5p$fCt z_^g2(^-dUsKGVLcskP)mP|L5ipwJx7DHa&I4g1N`Dz1-+9**cho9*McS@3H@AMo7% zLI0W?x-w!@NRu8KXBnde;p0@nZ-wQA+jKyAq;>_1S1C6oiRatFioX?k+2svePh}Ca z0>oQ0u8@X;dmM(x+mTSCAqE0?V)LkqOz%+rN)agv6b~e#`ua#g(9DnFsW53Xd9No_ zL-BL}EA_WVM} z3g8Vmw-wE4jZz8azGD{%dHJ-jxq)>?$;9?1ZU{79JXM%^coPw+8lfqbFo)n`rc-pr zG5-P$Y4x45aqV}>osZBS(AH@!R=BPfOLa(!xS*8PNh*GN-;mr2ue5eG`!Fa*gl07f9FBDQxBAcS|rmI~C-VnY!~Y6S=Yb%W6V zcc5XZF~c=g*snZ%7|3(bA;E*%x}P=W(Eoyc%v3UowI7Qd8JOW;0q`(%ul$S&?w(R6KnNa9*!v|{)t&k}%#7^H${)~&9VULbU1jjHrUW+HwaTAKy8S*0 zBo!{g|B!30x5f}!K|lqA`n~WTjj0>~kAQ;R5;`lGc+B5u>yjlv0aatal8g!S;mQe- z@jt#m!U7jdK%o_hGlL8$6>tnUDcjb%UJy=*_ox*A*w~|g>?`KvTN(MC3*{YqxwXFa zwrSYKd#jpbFQg~eh+Bq})_UINrfC+#FO6+`z51Z9yUMoIrO62V0V2&`v%6EI2pJCm z{(2V4QX$sq?17Vq>^ijiCEGfKrDH8tr`#HF`!QHTNwj!Z$x>Hm|Bx9WZ+57fIjds8 zC@}|j$l$M+O3kMA)2wV2*p{2utj)j)DK*jriLKOO0}fTr zdj9{i0JdP`_?4P9>6%^2wIurYxbd_u>$|vnjRl#6*=JIRTk-T~BW@8d++8KlHoL=< z#JRuP7WV9VW6a1Pc1kQ7o#XfQU7T&JR^FK$_m(kY2~J3buU!e=>izO?k`?#oVD(s- zo_dH152#>Elh*!9Kyk9&?ZzvMjbT`FHe1Fk*ZG6Ctq+-EzFOS3C|2x(rNZ7zy4GOh4aqRvc zcf3vi?#UvIErX{=tg9c)Fb>d7E<0fTX&DTa;>S*{j6OQ*YMJyWyU9$t zHfTM;+8HYxt8&}aybsPsw6A18n|qO1E%t@*`PQZU%gWCHp_F+F`z39@j?rvXUeF4r zkAIPgf~3SNlBebDti|u3WW#dq^4UmrJqbbw%h6Zu{G4e?^cj`$1o_M!E?9kh#mTJ0@ z6sRT&2Zm=wza>@?_1zlN8)e! zv*!mMV=L$+v&8;(7BoQ{wIq`ZqtsQ2j^=K|pTnTxL0oJ?s{PxUkO~I&Ess(ihhwfN zNWhUKn2NMBDG^5%Z@xqn#)^$-jV6J3RNsiI4%JUzfbbh1D{E*5y&>`BN&JPNJbc2( zVtuu25u)J@cCT=9BufB+mStGa!Y;qq#_yVhdEHfRtDR$G|Ky9-0{-NaY_XQn2zV-V zZ4uu6`1ir~pnt7=VYq9NZp#6=_d6^leG2dU-J`?x*zwiTXF2rM9sRp2qlNK&7GM>7;SAco`k& z?9wWV=d<>qDL`MwY(oQF-QM&6aM@apoN|x9U^eiA;S$~pC-HB9n2_B*3|2;L3#g(f z*}wa)4iSU@9WnV8JK~j}Kb%~K$OQB+gWZ7oZzqXFo(}{6<{G0Z*~ooam_G}-l`dq7 zZvrPeltLPz*-{Y(C>c+?*43D4uP?W+yl#u^*Q@Y7irT`eFU#JUC+9?1Y8>Ddct;(c zNy9`BJp;3pmhs$CS)KRyZ;QHt%-B$651Mq!(pPHLGYtR*IODZ2cn~-^${U zsr0Iqvlc>R`^e2ZIcqmba$chR%>`GqgT^)1rlod8v@#SlK$-yHt>iP!iI3Z=Ke^%G zN)uDOeUpeYC#l|232udVvCWj@4M!+sfKvG#b6c2G??lD#8|fh1E}IFh__Cg|Q6x`X zuDav$@(SHEAqd%F05iFdGV@XL9cZheo3x+`$5@6%p?a-$y^`8LbZ!=_nVtWS64LDeKa1W(a!Zk|( zm85dxHV8L4kfD9%44g{Ts50exHwRXS$D60K&t8VS@@^KWA)x!H7~%gWenubn=}Kn0 zNDuZYohFpZv#c)xG=ang zEL1tdrO&ROR8>n8w!$h8&~vOE@C16|7Py|g#w#j~g#uBhLBD#81e8gB@d2zuWy)$e zNvy;I)(*#5D57BKNB!9nm={gxLoGif&nj3Ay91;82 z0E1Te`EEj2aP)QOhP#hB{>xc?Gl%ZuETfuIZ17tZAIS|3yD;{S2`P;U18O}pQDGly zmgL6=6>{mxsgV7v4I+gBX8#s9f`U0H%PHnP8-?f%vs`C_VU=fmu5(kggWykr+nIn07G%RPX{`(E;8&KVUJb zt+Yo4H6jK`sKMH?M3T9b?78lZi71KO9c zi4zLs=8Sd;5Z@fNcj@L=4L)l8{p31Omt_#1Jq;Y(54GIsFN^bkob5y8KpL=t6Oui)i|Ni6 zpYJ{1{s=Y_>Q92w`X8$6)LjYWv3C+HE87DnelR-Bz@l~eVWIp%Nnw(_z|;fy@EDHh z%K(nLqPD9foA*vSpJEw9(Y^V_36rAP>U&m{#8lsd>tkRSWo7k!pg*l zx%>2)+elEHwLiOlxO@Ob7*t6W(@s>l%4hbT!gfn{TJGN>QI7;K3Cuy{6R900%I z0Ulq-)IaE)Oady^7Nr+HgKvB+SK{UWB$R)c{d5Ipgb~{N*CTN-tuyiJYf9e@`8Q)E z)zCKM+(OGBHMXx2;Dc|rdJl76k0y^KEEw)f(7Sll0)8&DiFqSrUuhs&JCSrVyUuSY zH5t(?5(t*osC%3ABohXjK-Lv!D!!r=rXOUP|E9Y%A))gZ*`^=XKji z%_ZJYwCe;lXB*f4f}z7b8o$3`DukIG0R6dWdX4!S&cUbRR5kM9S6_X9%|l3{wpXzM>ZK7J>cGut-b4Hy&` z-*v1f>nW;P8utGHuYu}DS8GeY;0`S`cV zlRH)fij>S19SV-;TZ#JKFCCJN{ASI>DFJWulSCY}B`VbIhF?7h15EbQE*Q!Q&-5+Y z#yP#9Wj|2ZsC_o}FoZBg;q(Ij_OMfO*L#VnYgyugbaCub7GS9PMDRo_kbhATn-1V&E+Z#Svmw0vQPIrM<gHz!kI!QId)p=5A5{e-NywL(SD?M?1={qJ7pt%u`(Qs^m zMY{L+%h7EnXrVfBbXd|NWe#^zVPC_J8za2udpXh6*R6|LhPkdJ^2Q~B?cE3It2djl z0~3n{#GY%n&Wv%tx1+uxiTWj%{8OWM`HaG5>B1{@RMt8n4_Gr)nsA>rn?TGBId5xSYdaN3>z1l1&n ztiAs_ytIr2RK?hfu{8a1FUW;(`B&b$Xw{z|(9J<{=}^bPIQz35Wl8-rUspFtlOL&y z6U_4?&KKYHoWSil{&568bJI-KK~yDiV!SPIXBgsjE(qYVU%4=fc3MOcTZ$*4Q{$cC ztkpg&BF|nC>tin=Z2#V9pY{{_Bx{?Jkbi zM3^2izusO;;hDpA_{k8UT4?ZiLGkY4eUE(#gUUBIJmV(28$mw2Ky=phsiWP~>a&i$ zPEp56-eA`MntQ$$Lj*VQh#>tB?}o}PCP)d85An^82uG3aQx*O#pnv^po>#d8hR92x zJoN`5%!?-NEmLJaC5~1!;B7A}L&&yIP9DB-&XxY+df{>?ZgXyN>B(HMq5tK4uX6mr zY}-35x@XG1I{XrfkMDheAMg#bEMfsxC~~}6djoJKvlbdfe~WJMvt@L>e|7b=pb>*p zL3F>8ckuPIi%ps%3IWv-U|udT^A+C&&XCimkDsR+TwflRp0QA?Z82$S->fG_W3rF=C{_ND8LrkxC}6dr zBh~~^C>U$$fpe6DTNxGr4r@%a(-Rm3pm7zgTzafaX|JTh-p7YtAbGTiW}HDl-Fioe zW-?Uk$8_rw2RjU6Qqeh{`n&Y~8FDZL+EfPklUr||o9^-YK|(tQ9p;{lA|zty5F)@x z**U}pX<<+RHcr;K*nBtS<&>-qiwG%kV-(eb2+&dNBK8bG1k5Goc5f@p{svAWsgUO5rR4&1hj`24Qys^cw z>&y{tNwIdv5s`e7ii#e7Rot*5Oy8S1ZPG4qwwe#auNV2KdMe~l?{!1Ii?d$oxo48YIrg9Tb>b5bAP385+gz5fnP=|CF$2yPrm&pCWO!gFH=G1T@)b z)jXXlbe5@_ch)yaE#HOc9mHlW7^J90RMdlg9fn*Gd;`U^#1<)l`{O^jzJPM1SRF<_ zVsVO++J6|lPpC7Yx0t^GEIg*izw2~F;t~rWI#17aQ-Fos{rQ?lx(l<&Bo?^-;8V>h z9A#bj4?bcR(CKzP+Y^@?)9tOM|bRGmcxHO zB8gPb(D#mWF{du37KK5XYcBjLor65{PAQB=F z&7_TCh(|DJ2aA@Ebew>a%V76uf0*mHW%0viM(1wITHd^S^UgB4y*gLM5KTeRiethc zMA9;j^ByWiIDQdGY7WKyp_!95(|IYD9qGwWv8as;b)vMN0T9k)an3~G4 zzLf;~Ky$NawMz*WKN-H_F3t6v@-?F)@a^yFab!{fBhxzOI1AO|wP^~&AjBe~|Ko@g zm<25bI?S&HencA}+W~_Xmz9@xx3o=xKB0R9ri1wm%aZqv3kO@j_?Nu+VeI4^RYL&I>0*d)m5-k(#1tJ^G`awG7qnsOmoN$yU_-NZt&M=9 zBkEMro9YuJOE1T>z5GhnQ*0ooh!W6YzIABb2vHLA8Z5=LP_#O# zBvyXFhE+1eGpgt$uY(cot^?i)soqqX1|BzlQ01iiPDae<~NLl;W$}1Y}`rwgsQ;w_!4ou9?1K`b+hZ4VFRp zBmXF0xv1nt0M-0^X7u8wneRaoREmVnaEWf33)Qxk@&Z8?@7FXSkUlsR@qb3<#FzEC zR}KUqT;1yO0zwPapVQ}As`EVED&4P07KEvjCDr;dbfEzFv4vb7zmu*_`VfLGpQ=Js zBf+@so5a^kYeAA0&$A==6$~wOA=!8%gGi|??xm?JmH;O4(Y;GoUi3GojeP8NgI~`o zuZK}qs3hyq9MMFuxc0xil$LeX^)@6qBHRA(>2TlvDB$MP?#^_CDBEB6jIwG)$bbw5;hS4T`?G zY~;cfw`@6e(GZFQ0xEBA6X1NkGO!}EXU@0GWBP2JwomvD_AYUF!(udd-A(o9AT|tP zqX|3M7$4$cpgH`t@Vl^re)G}pxoJG~P{lSUb|dCCzvvuStxbOJH)z@?X`|7DX|&Zo zx+6SDi+vak90&IR(wSOWZCwnJa538lyit?A%~~h{nVPaDVfI1wR;NhdG`Z{__;YBN z%N+C~H6NZ%A|FBDge?P{fLqW|(F|Y!cfLS)pyuHx-EYN#wLh!G*vu7i=_{toD z@b2Y`fx*1Fg_Bv^spF0xOoH-t5=O3`g^D6@dZmY<+-AgO^*JZNw9ZWeqI&pBy~v1X z0G6#UD3ORIL31RcuUC3==|~yae24A;Lfpldtvltmf3NdL9(jry2@3G2^YEZI>r;yj zvzn5id$mIwNXajSlGr$PbAjBMG9o6N_Xf(M{fOe5*PxoI*>#ob8M!1-Ct##2Sa$)3 z4`xJ(*BJ!%nQEkK_n+#^+<88~dnUF8RVUgJ2AYTBf^8`kL{ON`#F|DpnCtw^ z-8mmSL}vb)m(`i6{J$l~%*+Z)?~ z-P~PeD&04}(v-=_*k1i1%#wWQe_)8bC7~K`3o0q`kp1iy-23iic4OJKEb;x2?+b@q zQ^Fuz?kGUYRIJMMZZ(-c8&ek#YOx7_U4g;cjNS?Am(@A6uen^+^Zw#vLR(dPKp5Yb z7H}0MRxOUrx9-L^(cB{xJS-c`#0UxETc!F6hK;54i-4IE#bqR1v#w<66vVItP_F#=6=a1;e zBH78|`fE@K4s>x8$0F=<=8YP|HLAVS%?@!t1R<|B8%9oDg!W=5ahR7Hp_{^TN3@>q zSrTGCG~yjf*hoKEaPTm9D2!W_p^P_=u1zi0J--ah*dO-dm22{^{$u|?Gec2f8oDNtv3$y$kWAB*o9>F zKTQqV?KI1lXjLvq}XJ2=8xh@wz<|*6Q>M>O*C~eK{YW@8f@`u@$9P>TYW8p zU1G6j`HcKeiroo1AR-&L)7QMh9_`!#>nQD1Sb_TS(_eFKK&{_rBQ8bjrjN^d7lr>) z4?AC6UUllSaQyymDr^HaoQCP>o`+maevNc<-ATE`y%dmeo~EMM=R034mckTqR&g0k zN!v9LDiRsa55#FkmEWX4)%OxNDvDVQae)fsoSW|)$k&xMtJ{~(%FEozR-k_4R_T*4 zn@vYhiR2*zoRR$V14F54jU&Z_ivntKCx#9N8WpGv-obyr#w-G0=Z^~`4AIwRo*Tyv zFGZu7_T64*t2LAQ_s0#`02FreDWVzCD5?(%RHRm5K?)EyJ3*7$VtAHcX=6>Hw3!e* z&W1NsO|@+HY{|JFnyx#yGQj0sVMzcwf)Js=t1JaTA;6*p`!R_@^aZ4--*b$ z_r{$?dEBPsuZqNdYcvaQ#7zO0YB#U&2bZ%(Ys zXRcPcCW&;5wk4s$E-cbHHGH1k#$U1-p=vQ*>ORLK7>xaZ#8~(ktOkpj=mn z)H%}?T+U1YTid;Kc|$Bp`F{-DuuM;QK}9(b`b6EUxuRKyfal`T z-=mi{r7;xxF5{)vK$F8SJ^W-SBoa!nl~C^Pp&R#k1+(UBEwnx~nXZcTIb%4k?GJZl z)n)WjY2O4Lxnll7ff8B{I^CS_-FSB0k_85LE>e~TCf)g?0ARoeJ~y(k(Oz2yaI(-{ zjbm-b7K01lX)NL|YWU6tHPD!2CjBWl{j%E*BAb;Tmsxk*P{xZ)1r*VDUQ4fXa7hLL zgjS@y_|HH|aLSbxf%_%w)ImWpFU62DokJ-Ahlr)Z*FpOa(8W)lU%E@`9}QN}ayHf&8ISQCGa+3gul(}lwKk{ZR zBiyp|!Z7y5^o!o(aVMWy?w#qMC>&k>wyhf$vEQF4nqkkpqZb?BOi|~%M}Z=?GrW&ow1&X$5 z%YpWHPOZ|Oc2RhGzpW2&&ZqSgJI+)Y4xKD z*r7E(WpdhAWL()G^_rgxW>)TWPB7S@#L}9VCNy_J+gP5U2(%35Y6!ATOK!KsH2CzC zn#{YnWZ=|L*vVs0L`A zw5PSbsL5L1RSaq7*#~ghcq%!2M3u;Gap4D4cxd^;lOOo+NRVu9)jfx+lTi` zy>n)Ug9~h^m#>1-i(3aDQN+|!DO-zK7UA3O+z)bueg6Cwcfl{o=;UPOU?wQUCaN~+ zB?fAw{_kkLI7wCX2W>Y`Qw1qXshmn2pD^ym2A)$Hd$Ffdl7%hj6|n@Mf5-49ykjs< zPmyM~hiGV}CGvXPr$hnpl?LoU;?wI1(}dTD2+Q!JBfeZ>AHXP8z#b)bDy zUPHM>MOcT^l^4GQVZ3!))ra5e?LuqV>aPu5w!~u5w08As@I1mG-}a!#8hU!p?%Ud z9cSMwNAzHRt%ko z4Y|+%>jbpJV%1SUNf{4p>6{wv3JRpPhlkF>W@(j5{%dnk00@H`?|cADH%F_DeoI{Z zg0X-G(wM{oX>zue;ryAD+`I&yP;Y3_HS?ooA85Dj;e4{r_@5v!fLO6*T=#N)L$dro z6iosO6=A0It6nSW3E2&6-01kJ@p1m;>F`kdY~i2P$Lvwhb^Cd1HVKI-yX$Q`WFOq2 zCk(&ujQPn8-)Wen9Hw;)8+IgEr9$SodVG|ks`D!gg_e~7I95!fF?ODm*Pv~g9O3x( z04RN~dY`N?glrIu zInUM}luxEx59l7ouCW>-GJo*K8+hY-4pmH`G{_%_>C^B?!7Qrm`PXo9#*2Iki2ogO-y9-fe9~DG*1Dfivp9I*| zjVvK=?X*k43~-~mW>h)^?u8)+b7cVfwM+1iXd!S;_j}%o}D?AoU>;5RN_7dkffFB}^NkU7I~(c6Fv0 z?r(@p2Xf(MXP$o4vkK~fP<63_;l50MN}_&jc*S#;tBH0>pDEo62=^g$`QSWAtROrC z3dRARFZmyy@3Z;FK7#owLt~&)cIrX3T>xx-1{PL6&|%O#` zqz^Hg-)zVkLC7O{s9o4%;8Z1qnr5DwUrA8XjOnRpd05I~594w9hR3^h>3$hak78T^({TDY=L)u2dUX zbCA4%Hx1))x@JdM)H!mGxmD@9i6&C~0MZ43j4FicO)0gy)crTfh@0Dda_a<;RDQ8M zc-y~%7_@tTUTMooxXce6UY$)!mPj7N0+MK$p3^!p^=#2JFCfnM43S^K6kRPtzC}a; zVW$$vj6R4ZSfOuYXW6N`M4^6}A6;%o=;y;q8p_S=1?>e2-4#`Z(qv(iD1{y9dveRQIuf`@gkJC)Q{>goS)Qk3K`uPK2tb-P>gm1 z#78UcNspQyHjDhaxtT z(Bga0p;yIp+sN;)eKM$##NIfNc>0%HtQ**(sES&N^RgGXfRrV_y$Z3 z4|t3E@9A8KB6UggJW14}$d+mw4Ss$DR5e-)4lom3#yHpxc0aMDzCJi^cRL zhwkGM5Ju2zPELa&%X}qr@i|V zmc`%5y*oWR+*{jnH=Tvl4|%Y#XmxW0Ahs5#2f$D$Ox+zeXm$#yTRS6p$8}KQncF3@ zq(I%PQ~J>rPfB%OkYO%CEd^>ple2w7Z}i*d=P4!)wpbuA=3Y+GFRgro$wU~l!}AhXV2&%#!<#!yALONzh`u`C{ip zRWkhY+bCLbkVftlHR&g2f>7FyZheQ$W)Y+>iI7p^Ta4m&-U)b8no(PPnSotnbr#fR z=m+c4`$3HKnP7`H(l#Oj3L$eQqUG2IgASr_<_aHG1XgGz4i4FN7bsD9>Iu~Hc3S>h z2vc~(_B}IUl2b$7@o9Cu4rv8V?%mWb0uVGUgji>ikB8ZC!FfmqI} zQ#BVT%rExF;0sBco^6Of_!HeEbj2cQ)+nt@N z_v?kP>vjLeS!%k&i_|MkRR#&jm_t%T@XB?T8GU!{%@Ih^q-p`f9}~z_H-%u_)kpaH^Q^x<4?)~=a=ihyK`|Ewr_CDM@{4hb~fBiP{%gn;P ztFPbQ|7-c$1AqMc;+?}keEscs&p`VhD|a^j*s!mutM9KR%aXpzVLvHOuQuw45q)P= zbv$Fie1UnxNmi4L#>~bHuk9#1?fhwXjynDYYGG?dgA zNU9*k?ZBU3Lrr##hK=7z;xB#~#x-8sL`LSfH2CsBDrbDlM2Gr`t0>{JhUXa#6Fkvf zz?Q(p?Z)K^Axl$FoIkWne1cA{qVU#5Mvo_ORrj6i3fYD^mT$U6?{P3l(*D)EoIi~_ z_9LPAR{aa+5q7`lAxBqFfH@T7X617jLKC0PF|RP z9|IyEr@-k?!nB5dc8-e3(A!JgWqZzYYrKfpguBnD?k*Y@Xddl^^tm&O=(~W%hjjk& zt>XL*nW$Aw!u8$PHdGaqaP-QJPuh@Y)4?c>sm?Vi-gGz!g)j1>ams=zgSDB4EmKDDI)P3Bq{3(S~^^Sbmkd>gUXp;0Va=`ZZt;tm;5 z;lf7fE|g{yi`xsUPN)I(h2#w#83qOqL(Oqo`)84F_h+T0ET|gpxAls66VTeCIHKtm z-C`(gAwwPxsq(8~znz3@7AE>9hW!G;C)PBHKhe+B$DOdf5!;JVklf~^6OLC^{oeP~ za7G1oTupTod@p=d;z;X#ocMqwx8+p@U0>Q~;z8KD<%@$chiW!HoL9ra+(O@I_Oi?7 zAJbP>iFpAwOFA6ib)ib{aieYT7x_LDZtMjm>-8)nJIhetus$uKs$(E&dapy8Uwut- z0E$eFN`WJdafQA?`(X(M!@13Y5Y^WQmWT_fNl9EZ^0n!x44XAAV6+qZ)@$FS^B;06 z7$vg*kOtSmQ+Bi$~h5r1hlbczpkvwe@%QE{>($GnCcn!W>u5@UNr+vFOg=Xozx1g}U5H5l%Hb@Qa@P*vu5nZ8aK|Kji=*iL z?8sWN0mGJx;afl7ay_si?cgUaPpDU~)Q>6S_#S-g+vdiT79cW_4 zXrt=Ftm|4l@byU%Ne1Fq6zlkCWq%B%$)Rj<*|GV^x!$!SM+lu1u@Premx;=EqKxa! z%QHSEL9e&>+w@&)&)&#Q5EE~DOq;&yo6fU)MO1$V>CbDQb?cBof}STY0n6pk=0Da3 zb{DoZe}wMeR}U(JKZxrEPh{=WJcRTW$#Ro{mHWEVH$C5eItt(913p3nfB4O|yDc(_ zUNR=Fwuj?#>?YYJIDNh>$gycd8HhF}Lrq}r2CwGXjy7b{e}erXJ`m zT47}TbmSfufB08SW!lOe&jYvHYxQ_9-pwg2fWK%|aqY15?g# zL2)xbMn$^Hn-=bKVj@On&iG)>-;ROS%%YtaZ#}(Mu^_41Pq`}Ui{S=lrcUIUuAqFB z(z~?*UKD8k?7k{sgg0`oe{ZTk;%2-@ALobWAbep_t#0C8SbY}mdP+4$r({O2P@iqO z17`=;OTy41I>%D&6jhtoEJ<|);9cFPFD<+xk@^J9mMWXRoKr^o$_l0jVr$R{ufF$v zQdv$vu!Ob@q`dC^B57q)O-|mjb7*sCegKL`tZSjfo7r%BljA3(d-b)E_XxXo zdfyq_(MVB~biz-@3AP<#;ml{#>-*jeiih@UY7zMIVyOPuO0980f@c#y)_H}G2y zbJ!4H%1O$2^kWCUk}sFN471G==zq||B2JK;R#YCYo)p16ldvU8R`wBpY=-Sthd?Tm z=~@Qqm=kClC$PDIU>-@~hn@rF$qdVro>`}kxK-c+hY}U8N*h@%i*(2>Y z_?&&wq_5hVW|*#ZX#w>Q(J1so`}gN*p61<9WJWdf$Mg}%A6b2?YYA?t*Qx1e9j%VJ z)M~Hhh45{({-JXFf3B1|E0O#SI>1+L_p+_qo<1Tzip=kQQYmhnEIZ)EopqW1kpj=> zCcDC6=Hay?2B+soCiA#GMJg9_^5N&$b5da!?Nm6QoGqLPPS6^sh7x%RDh8hcdvTIa38^ zgFWx+eV#d*Vec*ObD%NA8?PN&^{;8!|JC1ChC+nYk66|?Mt>uifNXz=dJR@L1+4vZ zY{$Jzp{}W4FbbgkFWRL&LnrUF36nA!Sh)Fnd7_O$EYUqrPqc&*L9XA#FY_i&Y(^oj z0`Z)E*Lm!a_AWGqAxb#Erl|&GUjN56f4drTIgK<%u;qODqtpiWTTyyE*1mY`{zFNi> z1rOW(U##IC zc(~U)3g;M$vq!>@u8W7>lVR}Ln( z-mLpc6qo6C2eJNZ_&LGK>&ztM5kGjQ;IU#rE{#4g@+68yyx})=;BV0$|F@Eyhdgk! z94ZMH9hD7~lr_cS<6Pi6rFVgkhL8N1u1Lf7s{Nb!S4+Friuu4=ew+ z_C{aVSH(;bc|ptOG?nupCL);E8rv0%V1EB4togd*4+fd#n;EU#mmGx1xS{c;@Jy*_5dx z2Y_+#jb2S|1f-}3PUTiC<1^=_%%;z%>})L%9J?yF1gL3NUR-&a|HJRI!QsC#JnA-1 z2eI4Z0C+WxfFh;u@`ll`;`vt^7Nc!7Izu$Fx{Q|(oB&xLlkOT8i~kB@q#Xpn9yZl# zY@MpGO#DD0DAcS{+`vIn7Ql7k%8TP>l+%pCieg%^y2*dXrMU$YXz^p z=%y2O2N`Okr4=`54M1+Uly*Pcl==LYdxeuuF z%hkR|V`wGF*P0`!mCOcuSxi#ISu#39+IO4(w=8<)HWGfrnF@xbmw=D;Fa}5Rbe*0l ziB){GI+lKwPs|5Kbt|dm;d|pZG}SL;xf{EEETgg0uUt&);Q94qhS-p?>U07gIEyIP z%6<(~LmqXC%aTHsh^79%L-_=R&udAZ_Dz_jcpS3S@Mie&&%MgSStXBe6-AQ&Mvmmv z{|H`P4blKm-%3HAO(IKccKU)L>!`D zEr_9#Gz*i>=~(b|RY1K0Qe`6ZTOH3}U;DjRAL}9*f$ld+ucE6-HAYd7uiv!0lCo+8 zH^Dj+hEzt!fq}L9)fannd*7%69~Am!A3K@&oBmo$$`M>@NTS;y~`09U0pMDEe9*T&^{YaM>hgrZK^1peSn0v?#1@3lUC(T3-(#8 z*Q)dSJ^=6OPyLA`$5|FZ*<&gGBwqv1oSlDI0}3_|ZPtkDaxIn>73qR+%iQv%e^m9q z>5JJUx@X^4WP7}HRpWgvHWg8wd+gjvhdDoK_VlnhAi56Lgq-jCM8NY{5TwVCEB;@=#{|S3lr*l*}9C> zWSz>GaDDdJA+-n+3>W@uG^YP*OM^cB){p<*u<>Qf#L(5D)Hl+B^0+3({d9qIBFp4I z)Pg&i`l>J9-3U9Uu`aoLcewMGg(MFHk= z4t5OfHA@Fm0Dm%qB&3Ms59L5Ki2`D~)Na3psr*x;K0r;Oa=h$2M%frX`{cpyBbhs&Z)6uinZTUt_7r$BxWn6YC*UY3?D`byH>7TzBwECMbFDCl ze_3meI%F(Ohml#Hyg_t~`VTg-mJbEetbt+1a_(d_2!Bgg4?B+j*n#a4 zR}PU>$yG52_dWlAy#SUOKq+Cpae8Z1rn;wri>T^{q6*Mh`zw`o21#;m*?#TJ%lp?# zw&6}c#T(?mBnP+rv z6m8&IgeJGooh^Nn<)8>6E1Sj(7U(ib7L zUm)7M?D2PPzcFFF+8evki&vGNk&-=vZ`o^DG*dNgAQ0ch|6GJM-Q@3FL5<_IFIYSC z*;7?8aToh;9AfAGwzq841)|d)FGJ-iNI>dT74brRGz?CP=qs$9FvgI#^w6kETGzG% z=T6pZKch5TyP4FS`4#OI_lC|c^!GJhYdVs}t*z)tdf)Aj80<*6jPVC7>w){@>2loA zidiWvg3J9W%Hopjh)W!=#|e`bs!d@nQpMUthg7g{2ku3xp&`i!9i_1uSwT}W9O@|rn37o~x%2RgM#ahw?IS-+>i>X&D3)klrws>$} z<=LJFR5!a>u35bfaiQjbpc>N2Ktq``tNm-H6L>#Q(h`ZYG4fpIwqe0YBzCMb-lG~A z`0+|4@tf8_jn^cUaQ=tW8uu}2znx&g7RQLIYaqSs6Nnf;K^8yIwGg_MQ+DMCMFEM)=RP%MWcfRqD z_L*DgiEs>@Y~-@!OWfleFXQ@Ws4g!^yZXdMi?e4T$KUkg?ZBD_D_u8Xqxtn0qT5<9S#Wb!t&6w3JV_CNJ`sRkl^;AU zR4RYMue+p$Zy+X21JMmeMQgFZFiB= z$se1bM)T*_(S00MJ52RM>R7^_xo6Jx`_Fdf(O#?|IUS)F^GB`#&oRB5QBgCL^=h+G z;G6AV-`;nmrEVH|L*2_hK6L(H0V|(Y(7nR2;4z(Dqzjcji41UgSmaS1UmC0_?0{>b zO>=Ltk=d13p4S@sYp?s|ip?>XqgOnOGInY%1ks$htBEGRbk37*Vr8#+@u4loqOi%$ zG^okEB%gBV$V++8M|ceb%Q>1vT`=*3)y6RDMqaGIsKh?2CG`WrZx(97Wask&5r?)e zS~9RsImcS#X_St5%$LJk52vjD2>BZFTLGN1bAJFbfA%}sAq?qc==9af`n1hYK1$TS zP6!>FIz9V10PU@jMDlA;ebWICYZz8*O7ua>B@BA_}%NH%~YB4a%8{eK<+iqT>o2wA z1R8e7T1Xtxow1aZV?OHq3r@6&V)#R*yQMT=A;9Srar(rI`-rt-kzxoqV)q(GcBap$ z;jWiIQBKy3RWk#oGkK2@{oTwh&*eGwOI8tltE=?uE}1mWQl3-)O}*in|MUJ}`=i0d z>PziRo}t8E@06;u_G7^{s0nFdyhl881IgNV(O4cCf`urJ8t_7SWF&w1)nEf@tjPc$ zqwL5jNDa4_p>Ff5fO0LBBJRU&OpF-SzbMXO4HMR%=#}N+0Aq!CT+A_=ehfNkH$7nx zD`6Xk^d4V)T>7=Nsxt6KKjI)SPQtDrzVGS0(7rIy{?H4|l=wuP72_BBJcxave`FwQg^onfI7x`oQ9Qxo>!)8mPre zeXvYyS#f3Ww*S6UlNVz$J%<_B~8L-KnC$&vIIj^zXi+txGHZHk?7-?i(4{6}t4#c;?a24|-KNt&6^~7ed zfKeM^&`K)*5bQn7dCQG^NMRwplSRC+?Hl35zvm)6nG*Ge?*jVEqpJ3^ejee?f#8{@ zgxPgmPVlZM^-cQH7wsQkN&6pO;P}o+w#V5GlwsmG0f340Zwl_b5A{zzq^I)FAewg$ z*NAZzn3vDE5BNO|zJMhsG$RZ?XK+iup^@@twL)BH8>_UJ4tl6QWO zIPQ1qZ zQ6f457tsnqn7df~+Psv$^_Tjo-@Am3rRX5r;86;a(@69e&S%S8I?M(z# zu&#JZjeoTm3WJ`LoEIwxW7-7Wk-pJ;PJ&M$@58Vsq9FP6jh@}tP*4sI39Q~Y0Cmja zXaE1ZMpS7j{gbFE=ad&ZOQ`lrj!ECFPCz+QM|^|9>NsZfi1c0_5dDN-dIn)`UM=WY zd2Lfc2^8mvx$EqY_A)jNF}5`qiwA*>qpU_x{Mh!X2|#v#ge1#-a%DlzzFNY#Vo-HxqThF~6$iL&e z(<~HlIO`u31=j#)-M?!Mf<<1=s4`BmqCas6_*Td1FUs8~Arm7OQIIe=oaCc@;bSxakt3-+SzPNJ&52_)H!76ha?+ zH}t=cY;ev!+=4m(-%a^WTu8MxFx@9b$ztT3T_>~dLjEC7fe!$^U|e3M{TKKM13bz7PWJz?_3m*= zpKbj3^Q@KITDsPnrKT&l+-7M$Mv4lonYqoBnkAm;(G`XzDUk{SHMh*vthqGLmCF+% zkrEy_)Kb(`$OJrtCp>_HCqO~q_i<~__xJj~zW?+`>dlAybKlo}-S5M7+3?LuDgb2f z{$Afq-WSL?v@jR;CeQ8sadykJssG&855}x$OZMiRPXFh7*dgdZ2Q!)l|4aY|fPJ$Y zgZaBshb1OPi(+0M*~29@YU_MzL%-6-0L(?aJzy&Ls4Z2L4_#+Z>)W!QvXpE7zTf zkF4aEyJahU=+Zu87=pp`iPFAl)WA$1l<)JuwLfU6yf0;bV*l72Y6RM9Z$NW68rLnw z2zmaSNM=uGIF%_FVVRgiU60-!q)l`A&Xnh*a>dLiMwBHwMp9RWn3O9J$pyed44AXianiCj=4?tMe0QHn}6zm%I0TE^qurCu(p` zKu?VeXPM^m%`$7IvzMRLTQddpLu^KZ4R=+m+bX0+e`GRVO0Xrx0CnuhS9P6aMMZ#V z!lW*9823{QktPsD#u=4S*X&%OEjb5UtmCHWFs5;-r=cHC9xu^9)pC|sN==L8wH0L| zCqcYx-Pz7S??tYXP4wB>ToP*0T=PEbdmsiI=uOxp%90w{#I5f2%sye7%uY~C5?$M- z4}dhksW>Z?5aaI5<34pq6)j%1`7aY=q9J*g<=sB09BbP7AHB=sbc+p%j699{c#VO= zou$CJ)6Dh3<-Dzg6qz#5m8%7!^@^G49<8}ShBVz%!3@6S(LxnBoU|SdJas2oU!fvx zUe52OnO-@28q#5_2OUUfTE_h@s%78KE0Y8YF$wkZ@5g;ksF;a(8742TyG2=ik5xM8 z8*$1&jX|m<$*!vKC{+tDDMjG=OuB|R^pT@$QRm(%@hfY)ZB8mL9q5_q7$Gmw;|98m)*5+w=3*G>B@O5lW?IfR zm%d>V4Tz%1WZ51q@@vz8X~9j&U%H~>(F~)rFe8)PIg22ULMmv+Gb&Gm&^bjuXKIC~ z=vGRNTJl8Ej+7+?G?8CAsJb}(0(#wT?ENm!HobQVb8_Sjvroq=D<@6W!BJKS?{G=- zg7W2V(J532p}i!zy#m<{e4`_CCw-1Q`#w2VSJkl{&>xrwSm+vsFWpK!2;H2SP>Mwf z3O`v*bZsFUd`TK3^H0*0QV_8^|0LU3TnfhMixZKydAT_L&q(zX=&CVsWMUdvTsx4F z5$kb74p4QYFPv;D%l->jUGU)X+bI+_L(offi((v|AJRs#bGp9tOH<{RUySl&ii%1V=Z1sB!Aj5$oS*M`*Rgo88%7t5Z=NU5Mwa zV($?{XMTn+L~?Q6Zgt**to)Pqjd6SgQydWrTU##mFjz{L69dTWT5|7*CC^M{x3U@p zK;Gw6#J<^PQx?XHxt@<)7tV5Z%Vh0}1$k=Bd6O4I+Ss$PfI9-N5hiAoceJ%*RBA&7 z>)blqRAAT2pNHNoq-mZEDsF`(kMX%b=l^`e#8n5V*A7`eEEhpy(t9Pb>^co4)I-`VD}AUzZ52DbA?56cFafx(2ffs(|ST93yGS&fp0n z>ab*kLoMf5sey{b>JnAPZ=a)-oM5BSq+!Bgx-mo?fCkrh69Xal z(Fp9MybXJ4wyliGA(haPtv)n z=pgIujN^vV#`Qk(mk&B9U+ zs9*fvqg0TdCeX>-wmg}PMV@CAB&XMH84Of5O7|6de`5Qvuq+M> zrn5X^=PBm5no?ST)tc-NC9w_W^NVFZne(Xmu-BRLq4-6CTV#9 znK63l$~$>V%h-Kw2?_&Z8UarI#s%E zV68VbBOfn3F&g2d^%a;w3T(x-X4o*wu#jzfGmC7}yOtmmwa)7iFzq4|yg2UBwxU?&zUamy$&`q%BG#h=N|4JkRig?1X2EQoTSR_A(}+oOH|35b z$Kq>=w`K^gma-QTAR+{3U&zY z;bOUtm#!w4J}+E)mqqDk#c!7o%>LkgtjcN53yG~IwT{RUiSLgjf@D)ESAct2#%HnP zkbFyPO4;X@1OL65`?xfm5B0G=gSlv@p7JpypohF`2brPkvC!3$X7Uao#F%#Hmo|@O zOj0#Qt$x5^0l$%p&KSnS8}0=KoQ5l(mKK3=;O#)GmFh1@cYR=Z!5Y7A8W5qRZg%_Q zVRv~DJgp71_owU>L2m0ON|*_&RL<(!90~KI%t$haEU& z@b30t?9MAIm%5#ch|Fqi()=15kv$mOpPw`YU~WLo&(-zKo4{_V*UtHuedjNjEGR3? zXp)HcqwJDObeRrtSgfn^K-4sjFPuyH`&P^>dd`9`Bv~f6bwTrhYe`HwpHn=x4o+SF zk&2&o9|BK_1`*vg5MAP-BPZu>*u0lpwmXz~q_i=m2PzASNB!96APwO?@PH&N@Ps#$ z!(H>F4I4MZzi48^nBf;rVn8%{S$WsH?P+#X>^cC#W*E2rwp=3oxy#JD_azbJ1YE`P z&mTL2b4@t%a>C;lmHXb+vej-M_i4U?0yOk#TDc<#?gqI3jeI}c6F?kRYK23Dt#SDF zo@+I7>WJmiqa(uB%bL@}P@d?Ky>nUs)ddIk0^VuXCl&3(`*(>z&*=Er&pLIPs*H?0 zx#Di3K$uyzd+3c}#t}m;;h}+*`4{*w^DZ8hRPjI!eJ5LKcSR?9*%+GBywelQ(>z9K zhx-lJp#0+~i&N|ZKy|v6=i~P9)amHrl-7{G=^I_8KjZT!Zlb^l~1c zv^HiUEZ~7QjefJVp|kmT7EV=~u9jF0?J#_O^@dthGP)qnCOy7q76Lr)Z|3%>j-KJ8 z2|}3z!r8?yYxOyFfBH5@*45Zea?cv8B*W5Wp19gxS-mCF znGOOcL^B*~t*-nZFyk_2^#S{;>2$P80?|=-Qc^K-;aocCjxPr?SyfdQSL?fH27N#~ zv-P;EPpd5RQrwO^1r};QD>e28Ne(cV!`|Qt@k*YnQZhMnw5zO-17u?xc+utAcUhh+ z7|XjoB1?9Qs=yRCSjEaR32kRkfCO)JQcZEIKtwBmj3y+TbJn&pt?%Cb9|{ExxOMSS zM6^4uMR-2K_NQ)L4>UVzT|7vktJBi;xQ!_$zLN((E3q5iE4xB-k8LgUjL}UOiPN1$ z`EJuQRd91d=2-9o1-H66Fur@_4&6Irm1-T9xco@H^H2JDnwe%bE2K0@SV71yDOUZx z7Ty5&>TC%Jk0=5yR7P^>iFM&U{Twz~_D%Bk+h1>7fhd&iCzIw>1H?B5uN8 zW-OGU(pxATM_Xl8EU02QP=Cp=@o*Tyj)f9@zCK#UpjA|td)YLCUZdnQfyFpFsD7yh z9+8GTR9EFaeeGU=`C%R=?!ccrmY)cB3qq5lpL8}x#bzPYI}w7n*v926@4(rxAUt^C zjlnl!o&`fu!7jSlgQzU+1(k?U8z;6SzBuh}{p?8L9ZG4_63-E46KQ(|-CD+(Ka&Ne zHvv+xzm|Je0?=A6Pe~K^Gi|qZH43RF+d^8xC72{tIyE(PNL9KO%1bX%~MSkR;hkXI`x5vPUQ?5vouEha*s^hkl z=diFQARAliU^_4q7B7+%rE6WN0N9E*?268)G8y&F?F3Z2GEhkY_^LhAgf`C)`H$@` zWb8?m5MilDF6bHyVrI~~6i_isDnJzM~&w>MqN z%(nZN`<=&HXd{7c)(8u3nMoRi({9#wMp8S^Fel!I508Hl|Z-H?s;U2Ne?taPUiyPfJMsaCM~;mRxz>|w)`$|JG{5U zqBNbY0d%e^lC~KRxZ$NKx+a>wY1;f3&zl7A)31kvYi4;Wb&9YkAxpNnH?THWt1#iLdFl;ox!q?6kz| zULL;yP@na(G5MzkzlF*knkAL)VOR=G<)7)^P7C@UQX6mBh?MU+-YDHRxpEC25%*`e zXSC)zraNhAbxtibDC&H%?&lk=Ixh`x0JQV*?+6U*+-B$I2G80Nn0QfL>k_wTn=2J; zSH!aNa#Bx?Z-)~#fa3QUMbcjs2@L*W!8ffp!(}%`fv{U@+p#Z@Zt{}zc7_L5@yd9B zhnYW!k`NEqD!+Wz_E(gbGyq(ZKpI9iYHJrG;J5SnpyT#^yKWbK@iC>?B^ft~-ILro zaltP7qvFBco{II&Wj!}Q&ju!YURH&yjRoWFp0?4jB(-=YV?o@~XsJ7ys--iHv!`h0 zKT+2KRhn!2$X1sU;9bn^SbbCUoC-7Pu$*{2(mSv}`nI$72&{EY(ov}c#pEW;A?yA>@#d;NA> zqpY)vE?E?huGF|IG#~XeO?IgdOaB64k*poTh9a+mNUF<>AbxyFON?ZbZ;J5b6GFft z8tA<(?pN*PNCr`OhI0N_U1+R@79KHw3(#<05&$ew`KK3uyxp*==RTqWab?p~UVR?A z7lVX6@_1rH*B4u%(enhnW+dL331uu{BTL(PRdqJ+zw}3oiqsp2`igZ2mFUF zPRWK&7Waon->BYOqWJL=dL$!-&Hp_xEYck2VYf;csY9wqvY#Muc-3Z_X75#gX2-mD z7h1CVP}h(*{MYL(f&H6o99~)mKA>rLpzGCJ;Px^kGTDIdQqM5sEKq06P;rKvz&Kfp z{(pnX{1EY+3rJM$<;cO zHb-0F<`_kbk9PyInyT(|rVc=-{CsHa-Jnua0*|@A-fRMs5@Yb+OoXj3v(ytJ46L3f ze$~CJds3Nhja)$}jdK(p@vmE|l(je~Edmm&)DF?n%a?*9lG(D%3g3h6HR3QrenVO> zRQY}!Po83`Xts|hYYGYXn9{i_K&^F+O1VHx$eV&o`2ZLp3OK7?b7tO>eG@H^iA%Y1 zIX4?=up8BE>d{QAS8Oyt>;OH?9Xr?r=4Q!#+cp7G{PE^bn6yOz+)q7V8^83(+aa{V zj*g2?a?c%1*R~2NjH}y63 zSL8;DTkEDo0>5Nb25LUy5H4nr8#-R)z@)k3CdKl!zu+sj?V{il&q0R;UGX* z*nR3XFf+(D&bS^jJH?u+vm@!N>nf5Q+<`V&pi>fC9}tjj;&}60eF61-Nz)l}gB++& z1F5PLdi^BeI&sh1eE#gN&3D+>!4V){AjPcahOJEaqE2{Arrd1i>}%Eo4HbkNKP=ZL zo(Jpm%Cgz7tTROYVdlr$qWz18*`uO79c>X!n+?UVmYAFgH|hIcvbHOa@9lv68@ruD zZ?s98U4}TMqZ>ANl? zIj;amXD_yAT<(Q;dw`3Ev-98ELD*;cLkEmRJU^8hU#}3S^9`5VdwWvyjyFyUoYur|L&<< zuMF8+R7$ujSs>0G42n+4;D&1L&7RIptea^D99dQan%@c=-uzyu+6Kdc9DnKUgUs#_ z_187pv=F&7(Ffyho}vs+b}j0jZ_ijd+b0a}MM3GrA{b~g4=oop z_$C|pABzIhT>Ailo>-!0MwVLL4b2Nxi2HK})6p$Ta>CS(`S)quf}MT%iHaD7D=CCa zjQj+7)%c1#ep^$a8O;7(F^`)>AP%dC00MEf4HmN82eC!vQ6ahGe+HPi;cq*D0fhv<*OVuy7H3+E3+*%9!;OOMzc zlot*ti^fNcd*Z>s9`?bLCq$XqwBo6Ke$=(EuW~@I`%50B=;glAdwxmm$jJkWwAQ50?*)1~CgX%% zMHDTacng|8Tn&?EzzK(kj5?=tN`AdNi&<(6fYS8a_ z-t)6ucw{%_S0mz^X!phIcL@x?<#|_J<)Nu{4(t)6qD6EVy2Q+jC%j6Z57|R+ zyg3a}Z}#+k+g<2jcL*TmwvZ;t=Ro>Lu~cYM$?RS4*ljCcN$-1fCTlzVSp9-e0ds+8 zZ?K`u0SN=CH4bTgh)8M-4XwyC8v{ImH1n0C_R?LqMUjBb59wzrNsco(TuFHLeh~3xxoh)EeUiBM07*G9y&RqovaEg%f>~0iUUoeW%~oTkVzz* ztKSsDzmlCW>B#qJuQmbJSYwzLQnek~LIXMy5F+B$ha)e@ZmBZGxZA3H?0L)InrIjS@1t)RX?FQoOd<4Q|?Q)ftCo$EmL6c#Qu%Z+x7Cf#wRlyt- zTfw=Fkk@}wgQh(xB#2JbE|t?H4d2-jXj7Cky(x0kZH6PFHyDQLyM-aJVh4QOPBz(DS7Zr#i#Cvtl zNyeX#&XnCB-i)e~S0YezTPod3@JoIaL#C+N0V_w>bhA>lkIfHYRBrqDM4fFvWdo*= zc1~7Oz)N{FB*u`SObgGZ6HYnO_)U$Kd=Ic+WHAnVs#qOM!hJSap(}Re*cz3cVC9g_ z3Zy+>;XvcF2uHR=Fjqy-D#8ifYv^0(SH!9)t@%@DTd?LQWr^r-y#kSpenlOx@+`Q{ z1Vs~m>)m=d&Og#TrQ&vzt%jt@Km{@49GTdp6#BhPpde#F#pisH32KHwnfJ_++O0Qs04mv`<|0sot|LT!2LW5wWzp7#ye(Wakz%;1wvmiZ;HMm% zMhg1U9lf-94_6Dlbia>P&0Uftv)2jwJw1hNG)q5$-=3b$ub_u95KDY+(9 zlhf<0nnTMZneNg&)qgpro!Q#oq=ToN4PruhUX=Dn*y2j1Bdk$ZZGZJ%>F{0Tp4ENE zykhdCvvj#oKUad9BNUR>&N#EbSR7nND)o{x^a~_|39(oawvx73sVOBITfAnSDf6Vx34* zkCd{)4X#1Wf9eowH^(-8!E^(jCc8cEhq_k5sbcI8#RPOkhHSVqY&<5G5|)WT_dxF1 z&(NQhzU+`4yW(V+6y+ke)~=pG*86$^C9H21+gGFwH^t1)-&)ReD)wW@Cyyob1Nn7d zFrBKmcXk3Ik9q$C*%eUqq}V4ZSJx4?15p3g%(^l6%Xf^0%!Dj4b?S88>=(XW`>u10E zWbESSX1R42z=!2Eg_h~lzwMw3Y)A=H`wI9DsK&muxiMTT!+7;3A&!F-2*SfJ$d1+P zI$sD_;jzYs_Uj2r;WFWmIeCR7xoCUYDU2a<1>Ie8S={MQ#*U-s!}tRlZfkZ>X(bmF z6$G;ADp)pDZO5o7WXhvy>}*@M7AlCHLI<%JJiQMlTSEJm zw(|D%XLSIW8@A3jG zIC-GD&h3i5oM*Pg7hbKEx!qU1Km23AL(_IOx+XOtrqi0~JKfotFTGV~%Fs08Bw{wl z;c{m-5|l?;M|BrV+81U+A|iEAXN*RP`KpAvM(6q8xAA-Am>;fe%x=fhNHxdrQ-sKVG|nfdvq z<{;kAw2Hznd@FJb=%AC4G%zR#V$oHHfc&RhosM?eYh+6}4hv6VMrQ?CU$P!HT`Ukh zf2=pVr0!N<7j@-4DnCwU^W-a?Io1lq^64U@4Djt=ynUf|ryFPz`vAJe|IZfDfVa8i zzLiThr4e!rh)x$bFe3m2kHx*i&Yl_YtZ-pS5ZwTP($leE_DYn%U#uBq-1>4;~ zOs95Ecmf{BFXj7XHK{d6lF!DGMT#4jua>il8aV+!Zkmpi-4d$@J0*3sac?DLabTb$ zZoS0Wu@e?zOyhR$DwpXwa2ILhsXKX zVoujW-ILj3AGxOLS!6QgAAD~X0RJ;Pa*$2r@{;@n-TuDtgTp<0f*~#x4$ne_V%MY# zNBSmL0F~rNy3eNa3lCdfLMy*{J($@MA$rcp{tNV%Rjxf}-jIYJ^P79h>@O&IODx=X z7%l!cW)2c~5Co*2lhDf&*ySmnwuMrVkfo*^3^J1rH;|%ZAEgjZI+B-7uw4Z)_1~Ly zfV-^LsGY`{c?7@T$^(1~6PqA9T+aWk%#<-_de})C`3pU~@{Yv%k=86(wOvuusyMWR^tLX;3#ceSM%wo)wG zr5esNRL43`199h{3Aysl@E!o~g!!ZhBhU`nzNMjbQsd5X?m3(}dq`^VuO%X|uYh=O z^ZA=UzD<5Ye<=#M;<{8vBjNfki%__au(yeeLz@7rWs%i}c;s(+>%UbNXo(#!5I)lE zBeb~6aB@aL7dO}dSJ|x=YO?@+-xmQ{~OyZp0p^TU=RL}0DQYGb9~3x^+7ksb3CUelM^SN|u3`$qM#%A%g_ z{fZfs1t^jjJ3Y7{a8E(>e@_+0GE5y~`NM!_$hW)GS}-AW6ay}+wJjsd6-_Hz4mXb!^S>B@>>LjWCm zGV>c-{;rF)ak|%Qm6q!Mj1;l(+JSm3wE-QZ=ARCWkfy2M4(aXzXmJ0Hh*aIGyZSzY zli;g$u!`M>9aU3iQxxLb3kndF{NlT7NA_u+76aU=9r$Dbj2(Vi)ZTelu|sr|kB$iF z{-Wj?WTF0QRa@;_?d=n~WGoQ-vU?XkYnemzEgx9Qd+pwF$qs;2XekP4*fdB z9vUiYDD9Yqm_X;!(su>998WI%#98#(kPll%@kyvF*m>N+^SO|q&{$tX1y`q9y{&R5 z>Xrco$7&mlgJw4}$KFpdVoN=V%H>jNX*zQ(+t3qcT&V!WP1o&KulM@GbUn)vEBmzF zr%Zn9EN=NTZ9YR~RH}}Ilk$_u3ZLQoDd?^+`}08X`p#?DhhBB@3M!~vz&K}jC949X zd;!Mq4=^!|j@;quzNrmXqu=2W{F>)Wf_ITsLTpsyJ)@dqD(WEJ7lE*7rGAhj2aKHF zIR(~%(V`QaL7Vj+x!cU$sgG49uWQD`+*!)zv@L?4_0P?qmvw$*#WdV*ebmgZ-Jp90 zyN-~o@q0ay$>+%XC7RM-P-Y7yTGsT+-RzXfl`QFM7V1s&=JC*BeOv!=$+>;&2kFMJ zCwk8}uDzmN${2y%&agYP&@%R_{R0<&o64(?QYSmC!??fj??>tzq~pTh!urhq>`?3l zsxbT&Dw!qES%K}cnX!mKNt0H$? zSDNNKL>ATu0yq$EmZpW;#X7r`y+aJBaB0s)wKJUPkqeDMihdO8-4n_@;0v0EUO6ac1$Y9mTXAaOzG^%@P> z^yz^2?3gI)%d0mFj$rD_y5&36sgB&HbS4_1FJ%k6N@i;O1pvYE_P|tbS8aP8USG~^ zw2Eaua9wDcY?t|f#MQ;aHFpznTn(*!5vY&=>a7QApJaI!^$&i1qgUEsZ=i!?O?) zz$+c`pL#J6-bbESpD#^M5-NP{&G>Fn**m%8uk)Bp;<3Y`4$RwhlmUbhUsZmX>Rwf> z#gtp=a#v5~jtYb=d}3;Wx;tapYvC$HySaDY;y*P<__hi18bzX0GEiH@#@*m+lajaG zx#1|^h)Xot`>b||tEyge=u@`yNF5jl`iwQ4sQ}gX-7lb58s7uBLdQ+kvjt#=?&gRW zpnn{V08l*P-x#|pyB&?x3ihNUE4ZSWEDps2}#uJP?>cg%HIS@)<%u|6W$^PJ7$Vqqg6gr zT0YtfD3|sBg1Z2Uw&h?S3BpC_0GemPRySZmpSjU!o5B<5q5a_5dNf2bVuKnj~*!` zPNE{oAYBGpL`9?DI(+~K8dG8?KZd6&X_AcMG`L~1ib2CQ>Rwe5K9KkI0(8w_YI$V?0B3%&%7vSoQq#dHHXiKY;L zcz)VuP4gL#`}WkS1w?D+9upPAFpZYCLY8cx$%S>@{U7m16TBj=`zG{4rxDSVNK zE>;&N=Iq-a9e<>LaXXF1K0kL{^fLgr*sH=B3%uU4PXYPe-z>2HU8mybJ%)YGZ^~TO z07FutHqT?-*ToR5`-{FdPRKndZNXPc-N%xK?S=u-*pHjOOk4Q!>PJ>VIE${A6qY+f zrrravf|%+CIc86(ev3>&XA%b9im%Fm()wRoP3+Z_TmXWxN98oMy>sqD6>Io|o`^T0 zJLY>>i^Gl}Fl$3}bm4TcZSh7m3VYi{aR$1Te>V^w7jcn_Th&#R0Qd*(|0IOV#s%|P zh&@vtxCh4oGFTl7sHc_gmC}jf#V5z2 zP_+$W(F=%=g3yC-9*+DwISK}%TPq7z4RlE#-}A*I(5GWUX29^7to2)U`yc)HQwkkC z6DbUFJXg8=%RjXMR5d%(j2n*IYrAr~FTE@HjofY<*;85P6r|lpCoT@w6+t>5QpCaY z$5>u!|L*@qCLrq;60(zMLNm9%NmkvfPJdP4(iw~M3sDi|h?z3)7Kol30n z=NC0)+f=IFAL@Uzk>^Nm09q*{5cuN8l197Kn*N%qOWh3xenrcoYgi5lABsf+5MBy^ zApD_P6P&e)^7d&x64HvFeTZ$654j6eJ*c3=x5nJZoRcEN1S?p#p$7#5Q|1dVkW9$1@iNmwV}E$pcY#6;RMl3 zP$ClD?GU*RND{I1O<7gDJu_`0?Er1Ey1l9nPMBc^!3ntX!JXpXq{kz}e-DX&hwYk) zVH0LjeTmWF!!1*1r-i-25$u(yhjnR{#-oc1gQ06-;~B_9zT1K}HM>OR0!V@8%qHLB z@YzVZ6Q&^MU3ZpD&sRGB<622jcJ9vE(R_U42FxWT?qTuaTpAkwdw z;SoRyu|q3^Kh_OCiHsFlWuQBVqbs47YJaL%6Hm84@=bVkH`G)57y9xId^A@djRsr= zT~D@HVG#wLR83hek%dyH$J8+L;&GR|tpf>wdYQNL2ye206)6`_wr5rC$g|f1G9Z$A zSD@l&)L0_uMqo5MsVZpXtq$!F{JFjiPv%07964)^|r}_5_;_u#1!-F(|ezms&b~{Bk7Fx=#ta}AJ^pBd4 zS$s{~c2H|!m23NYwO!>T1odSnYLqrW4Ylwr*W0hz?%XCI-i`$OUHqs=$dOxXe)WykasJHnf1P6{jl_jyaHL?0?lWQ`R zFV^4lOfxK80rIGe!H0R5KM~xx#JPnadQ}ckLJ2QAQj=E7?ot9ckj&zN67fG?)m$Kp zXk+Ms9-Lx*C#0U{I^?&fzljyD5Z`X-U;;l`2I!+5+c@#buOIW)&)tcP3$Et^#eU{4 z0>yrauaIxb!qik0V653VUGFV}1QtMjQ40Wy@ zX=}Fz7`VcIIw)*^5K`D31UPBp8WxLu`~!Z$?sw_rpldQLs?!ke;x7&sR1q$#`u@H( zhQqFx>7$n>nZrm4;)Hm@sT^r5bokRBR@50e^`I!GoAq6m(dz)ZcAB)g?9|J{`58yv z8R~Be9tn&xP$aUsS!2hd7*i9J1(y8ZS@a^mQ5|`7`l;F4q(jB@dy3KmWlup-r8H$9 z^stwB6u`CW9t5`>>-zfRp@r|Tm|KGNPpWFMqb_|TyxO5iK^-8F%;nVz=&u_^<9yJBvmV!z|k?SO; zRoP*fVI=lg1rxQ2f6x;DH>IP+3BQOaz~O2!{J1$w7fWX;rc$u+po{`SO+Y{k0jQ5C zJgfZI(m-$)E7A+7XhRs#TSfMIWP|=31eB%_4yOA`vu`uTYxU-E%%G7woVv(NGd;EjXx81z<$#)MwiMqG%yX(Ild-3D34^IF7=!ebk9zDD3Pt3PJ{i`G7(afE) z$)bnGR`K)mNt#!5h z$jcUgK85qldI+=hx#v$eRVeqgV~_Ln5VRnDWw9vFrLINx>=1e>!9PJQyctG%H&Hof z@7$QMqS%`G+y*n@@tqgp^W&NOU6yb4*wedqAXHs7>1SYRfgnH5#(16PHZA7DW%$%? zPYSN&-t?Nl#(!ytLoNoxvVq)(+@yEOzIYb3M|qA@u{ATw@?yy*#lFe?ahZ_^ZNoWi z$Fy+v;AF6$txN9u&Zoo9o=-N$bl{s$Hr{++y`Iw;kItlyHKwEB@#v+>LdxB=zW)T2 z;FIy-snxlo9NN|owsIqgiw>q9`>wz0AL>fOO!~tp4#l;8{oO z>6?~-}Q%vz=$qb3!>4)?+<(5*SBqU9fbN5bQ}TP?YNy?o=I_EJ-(;%-=P zpkVpLl4A)NkJ(v~W>^%f`F8^26$1|Rpo=u&PsqNzUJbzLJHO^td>McEe*f38(jogs zr>}RWzqscd5LaVq-zJ=WQCIFn4^QdBo9^1JA0GSlH?{epzEo?^@8Wbd zjMalRn%o?sD_>1Hle0{HoEvOzg~K;a;V(z46aM}#4yL!C^Z}Ob4i&(}YBn}iUF}eD zeh-@tB|JNXkLlP+fr2%?ouIyqi5_g{pzfW(t-q;{e20v-da23>5tlyh+qJcV%M}l0NW!ty}XuKqj@S4+z{Ls4W6deB%O3 zB$*m;R1c&EbCNRrwgGJLASaRIvAnYTWoJ=8gE3|7T5Pj}l|Ztgx*7X`7Totou-{#} zude(*iq1oKIFfY>$H{swI9mmSBG`W$zq zN8bG`DyelUGW<9DBe%?FCo>L`HlA(ck4G!Gn*yiNK{?YH!P+PXljt*bd2)8Feq6E!)P4VSK<1R#cq-ia z-NW_Q87(nU#lb^2DCeCej5(i-;}F~B;7|qTzh#y2edEub+*o<#th( zGj*3D`=)JD1fgxAF7=w~#qF58N85ireU#c^*@oSLx~%xu$2qj~pQwhva1t*E4j26@ z3AZS>6=W3z^Qs(p!uqIsuvtKq=4!4aGU=fHr{UhuDp66;>o(IBs? z>T}ku=@Hr-n@)(}ey9@bXf~8BV?~}Yh5Pa#SxE`=_BYZTm^`5@DHGjIx#0!g-508f zX+2w&ms3&_>Retz%v_8SitabrpejLa6t~)v`yqHSAO*NWp_g3>hA(u5I?^~?D}c+ z7CJbRO=ncQRXF)(fe0?XnY&yO&EFy#JlI58WgCK+k+W;P(W>tzbV7)NMI|LH76f@bg-)sIHK}Mcq5DUys)w>HKvt*u0S$6MyWzHt0ZEg}-@sm)gADD_SAy zj5ml|JE-Z6ap?5?)b!K~>Dy6u?o(B?x>(w)?rNihfkX);i!#X>vO5ea~NCb$CrgW&{65tCe*i2o61&UPalJEJHcLrqg>| z)%=eta>Er-{JYr#aQY6FsL1UxJfN0>{>?Xw)oP{{EAD#e@#|-DlC|#y7T)Q*v9rvn zLfoZZxCz4HlZCR7UW82?^>K;2KQW3Yep(uz@Ui_7)$9(p^3qT*cQ?W*L3o^KsA5Sr z07ouXJG4zwpS~mvzlv3X@%mAbgE&LcglE~3eh|UuPf>!h>k|Is7U0jDdu*cxVJC#U zfTFif|iHRRtd-Fcw&loQeY6k@*gY4{4&N)guyHzHgyRvh03e==jQK%sjdc z%T4#WAlwPOA9atRYPQ@}crGXNQr<2XH%qj+Wlh5T!_x7W9UhB9E9%3}`zg1p^6Sp) z8=>`qc=UiJJCvoHtlXY6JvVps02cvRCk~gC0o67VqE`;ql`uYi<_~GCXie%h%1YWr zfw8TG+{kA5cVoA?oqoCezJ`SZjtD3Kp#f06j>97lRu+6^sw%y;kmGN%CN zWplt~qFUfJF*w9wB=S$Wwk0|ra;iTPe<;cMxZ+#c01e$z>>bh7fSw%3nkOf8XwkI~ z<#lA|<6(X0><(*c=|#dJ2hh^Ocod^TS7SX9nEgyXc5ODx_w00BAQ`vhHYFQGq;1jE#;9p7W-j8n!_6Z_8>6=crt?IWSX5qS5iys&sc&T^MIzJ0i{ zlOv}-hDVMQvarP~?M9w1)Ir;D)1{$S8eFOl`tU{-@?5hDd$8GYe(ol4Qa|}mJS54v z)(UtjD{%v_nZPVv#K z_>AefAZK)pi()pbE^^{4NI11GwnwX#vR|ssnebMZwR;5qwIJ60W!V=FYVjhPH~P95 zriW~r#`7JU3tY*9g|y-Ku0&`>L~lJs+I9U5Gq(Xr@-3ycbeFrDGWnmYw%T>byZ zI{UDs&;IXUTUU8)nXX)EX1J~%T=OY1QW9`mn_inw+f4BRv81#lMPVeM=$b1tpDLG+ z2x~6QP>75a1I^TTmOcU&2#&3( z|DCyVGrm9`)zRQ5>fFM3^Xw%5lmI?<$Sn*A?p}4it!}!1A!AfTjPA_pRU75E)<(`y zO;55N@Wz}@f1gk`*W<5a80#6BF0SRn3;5M!Z8RDcya zfWZv}mnX39%M%KM0<5d)c2&it9CXirlsx~TaO>=F2`|D1SyO_sCYx-Wq(t1CD8`%k zU@dgx$sbY-k+F-=O2FY`?nD_AzEJi`8f&2FKvBh`$s!bmgzEf2EL=FNv+;N1gh5A1 z2@BsdODXY3Vv;D7w%awzy}O-o6VAodzWxvf?PyoIGD5SrLNaLlc-x;_;GYYA6;M|G zY>baJ1zOTQlZp5STd)HeZ!|#^@$S%p#t#4Pp(dF(R{$M#rN)}Rw@lRKkA)Q$SMZ?} z-op2SNIlQ3Y1CYdAnV5Ts*6NK6F-EhRI9_a4nF)RN8u3t!pR`22n5=Zkwb#^#@G|Ys{>;DQqN;h()>+ma3vaH?EA!MXcuoLwYGQI3Po5l``A?9Wnhx)H<4Eez+i};E)q|eRN zX;d~3KE+7q$u$q__5WapkB8zIS+n(!urBUM{e36;Lte&8Q_|1Mhb8Yrk$3&Id@Xs`En%S)&P2ut&wUoMPUZA%wy; zgB0f9*^!E0j$m`*eZ1~E*$#!X1BK$xzriR&`)-dQBI9U>A(hz#nUfxPFGZ; zUC4b;gdMY;-=$YHnI1G8XY0FBpcYe?@rR-+v?~llPUvuUia%VFJ!s9K3Ddx(T(0(wcD9goTnI=k3T@#j2Q;FECk4`SjEV-F<}oMm#*IDH@Wrem4{MH*QutVJq7er z8!g3x@!81=d(28_r}Au%W@)oL6t`q3%P71L%KpH5clV3R3G${`vaH#k|t=l|xP#k|t6f z2@anNiKmH&a>t&op0s!STuPlLWG}V=PExs&4)+WL(6jj2VDg$iCi5NL<_rGjx5g@= zQgV-Kn`cv7@=V%r+R^}HZ2(d-0*u7!(gx0vy70OkeVGJPU0ZLldO(_E8z3bpX3?S3qe9kPN~&eK!hNwgo^O8j7> zJJl&~=D)UW{+r_315_@KoNVNE&pNlxIiCily{V@A09`GlB+*}NjG}Q{+&^n4I-Ybg zPGc7Tb`T6rLVnGj?z>TYz%wXFWC~z3+ZWZe+|A;4?X9m+Fczu9h&P1|AX&S9igWz+qi`m-044VRnpvp>GCdmZobl_OF$A1F_hve;Gd7kPs^N{bVGCG8 zP^P)JP%Qc`3e@^KbE(}CL?+3*zN;Y5HJ$w{diGaahyNC3U*DWYjv3S1jHD%F%!ZKz z6f;k16(7u>a4mi43`>73&GwZ3U-=-aY#*y0hUH1S=z}r(>SKg`efsG)!3oOnX z{AV_t{PHyD@%YAI>)PP#L~tgBG_u99N%_6}`WPqbGCY%1H!!T6_j8?(5|!5*V}Ax6 zM5rIuqVUkANH+I&@_QC*ds6NUWs+?xE!!(0#C3NtQ=>;NcFDXw4Z`DL>|(lZp%Z*P z8_4tRnH_p0e7QfMuJeGjxxHgH7HT4IzgXmn zf$>xQGoKC-Y%b$p)g3!pV6olea~1G~rHM8}!$}Y`+hM2y|t<5M1$Ti!3xmij2H`QZNZNm_SB2|WKN#kWPS5b z!F9#`8NzV+%jF%vBfp?|@tY21H$Ht-IKy8P;s!ihm%CG=QKHeF{k9g$V#?-5CbaZ= z|99quf6PyhO&6Pfm@VEho?b`@gnfzv#uIdK_{Bq_v7||OSoCId7k-_K%oy*{2!U=e z0xw!|CljI^FMpPOvGR1+;MK;~wW;jQiK=$~_7NTGW9+P7iOok|n>=c3N4HL27dlH5 zyO(t@7w1HUd|&@D-T)?m%m+@tM=+-b0~(cG%%3p zz$_jFuT=Y@JB~NT>r$i7&i!&Y_x8Tt=T~D%I5&CumhPf>_Nx>GNpzQ;BC6< z9VRZN+H|c^yu{bdm9(xdeV;9r^tT6wY5S=C`gw870FW~h)xCC*22$&<*3g@IXzJ7@ zEBBR$``Rj>Jq&hBk!6Jzg&4|_bnNdXyp(8nV3d*ukO2kea&H@VKfu~IL$S5m>bF~^ z;QYK^8$uP`!F*PpAN|ABSJVO!s5;~B)EZ)?k2?k=lI{7PI(%Klvr{RA72x^Sw`Uz> zu_+n;9X*-r^K6Bar?Dk+Ss_STUIoee2BbzYJ&G!%ffy4{SegOZyv14V%B7{Pio+atGAX9IxfGQ-PdZ^r~b}^ zoPPVNbQj;CLOA_A`NFnkcJ}XV#LqAU1wMDX&_Ov@-1rw?QY+^BKPl>i*AeH2+9Q4R z5zg4d7_{wkrw$Tc0gro+^-YS%x9zEz-)^LWafV)Q0P7vHmNvzl8h!P}roE#xI$zACRe*^}u_5+p(9VucN$~N_ha4~ zr%tv|O?@>8V$-H|GumbO&-Mnou`W7sJo(B;SMJC`VL{X9>TeJ0!W!+}liew=b4Akj zNZQTr0b2xebW5rd)Z6dV68&i|kExP!Wy#BmnwW}~ZuT(iC%p=5!LUGm$Lq9R# zs&n#uzhteOG1g3v>uv5s&NP2PC!2cgf^@YhHXcEN`9=DGV@aLdxZt_4XnMxlf!60o zW_}&n>wN}itsk#%&RzKBO%;=P3|bE~A#`w=&qKrPpUOkUYs(7vLoLWd9u?{ zc5chi1()sB~Nn11!=_I3gwws=BaO#k2NB&Sz>{!H1uB`*f(5J)|57ON{h(s zn;@|C;qDnuFPod}cqx?8gq*$J!R%^zTSs-QapJWMa~};RQ_{}U4ZovZ(L2x{rY57{ zR8zTqjROQ)E&9&D_xiJ5zx+2P?gQ$M=!$Vb@>G@`w7RFTJj89@shac( z%N?11FS3pNu`OtxDYQa4aQ3cW!RtchYWGbiE+_eY5L!0xZgWd#eQDm|HeAmYBHLwe-%_j?eGS6S~Ini^^lO)fp?R=-7_Y=Sku@uEEXbPUGk#3nzHF(o4|*kpRiP;C93v3(7@XdF>}*I%O;8{ zD0&il#}E)A><|8;bz`N~XMKm{eyZ{()i+`s(59{3gKo$()VnInRfV50W`A?aFB!eHR%zGh~m{Y_r-5);atSOG7o0SxR0ME;2#%*(+My(iByq?{GK)> zn?JcjAE>PA4J?)k@{6!bWQlB`brTD~;y z*$VZWJhdKutx~9#Qh9IgvQDh09Jci>h#{;wSTl%*#N!#z=XISO&z=fzsD7HS7p%cD z-)kKNrDR~K?j}%kazm%kghdJWwO;@Z2Pl6^NL;s9TFv$5=E<*UZ#56Tb4hzTdNipA z{8S9QEV80NADm9uvd@@~J!k5S6q&y7g8ZnTa26v-*on3&nfg2&vy=ugpYiX4JU#X^ z>!2QPiEvtWLKt$|3G{i|)z+T%^~F|eSVl&h58*{r`1|Fd-+Ufx7(c40=@|_dT+`=u zz|S|H``G+C<`U$Re)ThOM%MU;?b$0McGQtrN`ese&k$?B{orlc`;L_0&ZqpUVGvcr ziqUpV%T{qzH0}MHrhmY7KNi~i^k*7!V_@ssx5<}>uH`=3II+WVebI}5Uz4ur;hZDM z+pp0wzo?#8txc!48ay10po8LX-4`O%jB!=W7b70~mC9G;D8(&^=@;UxWDDDOLd85n zq_jNlcDz3awZz@$SlF#a3hI|h&us=J^YMVF24uZGt_U=PK$1VTdz>I36fsJ%b)bxn zt|-W(W|79*1Dey>-5k#J>~|pe;%x}q&?{w?*0JLFf3<=SM|^Fri>J{NF}9~$pP=d* zG~ronx)(Voq`gi-aw%>OH?Qd$kRmcH$0k@-r+&9DHlQ-&nw45XT;9Qu?q2G?+guF4 z0fnaQ(jGeRxQt(Zd(`RQNoVJpyp|L1?Qs)DdAbS+;rmeIzsPbehhP0^(J(n-IKv<+ z_o!oRNA3nj*PH_WTY<#?G*gc9F0U(UIH^3M(E}TAC(+ug1(rlP>)BH`HY#n1?gN>h5EeUY6P8$VNH1qM-SkqJAjvHR!BJfefM^M^Bqn!=z zT!gf#Bk>$OFxR;ni7gP%k>2?v>xGf{4wEk0!kjl%Vuur8^xG{rKJ~?N+#bn~r+z8b zj)44zS}s21?U}7DZ8k$;P*S}P>q>yYTe}U5lwY3p1Ul$gK0FJ+gBwEkXiY%5lXNwt z+S)V}c44SbGEmdE3{s;N!*8-K3Dz14Qmx-@L}FEUPb){qR{JjBoEU39nbN=t!qtzD z>^>;QcM~u_>vFh#xuG*DPZ#b!JGxl9Fo(55gWZqmt(T)=-*j%q<-$ZupZf9662*(i zwUJI@G}mubSk@jIg8{4suq-R<>YO4bCyX$wkqqX})E`KbEki5HdFXnwKLdjKSu}tY zK=>(haW~{pJr( z|FrMzr;HsVkz0@!1+w&O(=Eu>eemO1B`A!6c9#P?wJXFwA4oc<6%D@0RgKwTAQptM zd_epeAUyONE7M1~`zF!Wo{zoitvQ0xo9p(f^Ht}1#38+!`=aLZ-anPp6vj}la=nc( zjCb#lRp@1V83}fN0o_U5vyR za0G9>2SFC9sR@)KCpa%6c?=N0s8@fq?7aT*XR(^txv;zK!47!abM;zJ1MPmx_=xE_ z!9OS(Bkv0ncn!S@&I_-%hZTE~O`Sl2q}>|YHU4$g_}LJG^DqjCja@P0=L_}_5af&jRJ;AN5GRhtO|W!v`pC~l_&AEcvJZm3k9 z^_+D5_|gfzZpzw89cEQcCq?-uIwy78wm*v-x6gf6Y~1R5KzQgvlFdHTiO`v23+2@A zD8zCfb~-&lRNum?xsR-AEJ3ZP1Z_K|c9sM>7ZAMk6SXx*6tTfxdy8<7U$MzLLN#Z# z97#iTf}ghXP6?Kt0zJ*F;ez}kzsVutm@fDuN?|*M022}9nXx*3xUhb} ze~1fYK_ZT^lt*qF@Hh6$U(~5NVeHTg>u|!8Fqdk!M;niqMBQE$X6!2VM;UYW4xTPV zhu~Pg1?6>)XC^Jp7lvL%`^`miN|jvG!fxOulN^(iM$9O{rn~mrnG_NVMChp3ziWII zf{O->*tEK_8L@XRsJY#Z`VOvCK_}q(2Ca}d=rJtu3;HRUlsW%o*h}@ zWvFS+3L+DXENZBqsNIPLAR5>I{O57tF3GpGDF-?w>u?yviBz9v}B0@1nt3{iBz-8Q0suc>N+<2jq_<#@yD&bLx6EbEedhg)&)|Tg=zxp%$X2;0h zXAc%4Jb`vxb~u+{TqXh7s@^`SOMFpO!8ygD9oQ!BH%fY=8X2$@SSiUkN4pSR2?YP- z9+p6;dWa>HD;DmStWHK@h~|e_6}(`mI5<$`nzY^j|NZywAoDPt19WApn{W=ILyWPq znQw>F)&V+DTDm;W>VTXXYW6~OQ>-NvQKzT!44eN-3d1N|t}l{=@1s+oOL=3pDbeP) z4cBs23ft0uVrhX90p+<{{6SbWf27nbqomVXgFfwqPXiYnoui=9Np^_{{?_qgp}9a zKcdzIbkuf|zAxhTou@gBqFqzeiJ(?m@0+YKwTneGHfTGWLg`m51L>a_ZNS7-(V8s2 zp4D6Kfwe-|HuzDvlmwPD*)^TL5}zp`piXzxtH%x%8|t0K3wR?FnbkoIkDqXs?rBa* zc?w$K^lDuWvJ0kXb(ixHJp3+yv^ARsVrMgcG8(~SOUDYtm={v&YQymFAmIEAUbkz6?2)w9fs8XoTifzpXn$Q;+WCu>7)Q{Oo*9lSKJ})jH`LZK=2cxW|UBM}0c(Kkd|b4Ld}O`Z}ZRP{!IUW>9dnKj1ALigIn~_^xZYw$qE3Q`56-*4#(v zYrdsUOV9-|)ags6dqMQ#At3;W7#I5VYKv+F)s&o}YXCHA6}EHdpr}g9-2_w-Y0s)7 zL)ggE^lFex+RG4zvYdKcn$g#Aq?MAUST3uIh&lV|`Ga7pJfW)YLSESXm%ye*r#c6* z&~%3sZeJ8cZ~C<)E;@jYc8K9cFjM^9vm?u?9meDbx1EXs0EuMoYmEK5lpFfAxh8nD z-p&#$1Ns%Jny24N%7;)Tr4D=wp9q<|v*o&M*~t%R)WnoI@-mVO8*HEXbV@RE7DwMc zyPvvY0A;}xpRuGZITvUSE1R$r9mLum-8~fw9htUKHd7SEw7!1Z;okn!Nj*Q5a9^<< zcoUVbVT6?U3bg`vJK~$ke+y@0j~=Ztx73^o2`?)|ZY7 zBB^6<#pd6o%YZJA1}0pnHU0mJkRvHvI6C2Yv5#LN>#YNvMy~{xT}oL)WO7Mn(D8?(_={NESn zx{PpIv-lQ@L)&u1t#MqBJoc~s2{xVPQz!(<{YtVlcmmJDKBV@k$8Oy7^etI?DSHz8 z=v8o?sRz2Z=DL?F8Q3m!{);mU2d=J`={o{?=6~V%Z0Kh9hLq@aSTsaqA|_28O$yd) z_9E%43!O6^+(PllDVfUSN{{)&s=u$_y__XXD;JJ=KhlOA^s9#u1Wi~`i2sm%)2U;Y zpvH$gvoL`IxX?KpI71xcie{hWb!aZM2qji7-p4X6bW+-@)#a@c#y}oZi4qL0F7K{l z!}yWOmh@AC)!hKl1G)9qBEX6xAB||QxgMS&ik;2rHq2^9xp{z&dh^b1B;#w0MYZxP zIMB9rz%L*MOMI$lkys40d@8r(^kqkmPOF=`UsGrRw!i@ipsUS&(W2S>^haci)w1hl zKK`QRc_#%U4TA5}^zA{q2m}vLLQNL!50TDN7%!(gr}6`Z+EXr>=-!P4`WTr%+)}#r zrtE>@2qZXv4fPAe5QfI$-$*!Y9w@1v7nIQHVZrp`p3n_smy`XYzyzwUvIxS_0URS_ zrAzfPdiC)Z3&EBUX=`n{{sFDaqnO=TZGl@`{q*~I?%;X| z2W1^OD|{&!h)Nt!=nHAr+>}IxA{RS9xSEv{e|d+CTJs6A0hw_8x_eDRN&3K58;k{z z#9kf>2o%+^@m*0|7ziMAoUdDGkN5&$;+$qg&?$~WT33e#xEW~&GYcBC&6D?A@Lje0 z6x^~wTYBlKW5%Ah#H(NZ@p2pY-q$GvJ|z~2=Hwy6xiZdW!7LX*fg?qVD6yQWj3kMJdT4*eAG3l_7*}?((>@Bf((04=}TbK96wOck@6H z&A}f)4#T=+)aW1ZMU9C8!^ONK2~cNsmRClh|4by_Dx6hh?+NBjQCo#p8t6wDc=yd(;dmFAsXNR?8k*5KVvCQzHuO@`CL39!8TOEN2068Sh-+TZy7p z4!6ISa$ZT+MHC>Wqf-)wo;U5)%b2xZ#I92SAB#EtrE3oGqTYW-Kzt(X!_rE*3sq;e zEYmJFg3R@$8||O%Aw~oTpkfLK5%NlB>mfVb(CFAu-s`iJ_)tc9So#mqRv;gQ+P|l$|~O&GQgSY7IYp`ua)~5ZfLR~ zJs~c*VI({Cvqg7xdtPYYLj%kopmk$qAyRGa>dh(%R0D(&IAepKZfYRXZ|;F)cVkRK zTb*9kY2(S53w8EPQBQ97P1=E@!B)8GW1&>j8TV`yH5LdBZXVLL?Yy0oleHzV1$7&8c4BgBEgI;}nui@s5BeKP z8`hO7zoELg7g;Ayu*&=xE2G`Rr3e@BQ7s)idmDd_buB1GCrKK;Vktz31>;3RH_FFv zhTzTv?o@67*0AQ3Ux1IFy9GN)+HAAvC9Kl}ep6YM-aNSwizd!hubwH4^bji`x4jw7 zp0gTz{nWLvE(9sSAt|!E_OP7){QMU6r(jF}I&qeMw6C+n$=4?-;qkP~vU&2b6VVl& zFfOWBRy;ykpcH@Nx>+zD)ERJA9eMD7La;ZIkQ!UD)>2O)Lo947sv3jMy?2zDcX|U; z5zm0G0NkE&;g7gzhT!!LecQ-i^m60F>=;*L-$NzZ945WVZHgtXqX{cxm%#!-H?sz@ zxHKi3<89LcdH%Zl?EcB^0Uz%T%YL%wALBb(9Qfo8T2+ucgOYF~+P|;}XvAeY&QM2{ z3sKerq5kdhV04e4-gWuxxXCtz9poM}6F@Z6(HX{CreN#^I4DL<&j1pc1LE}8Gs+^~ ziWV`-yVp)JYqWF#Nqxyla;4()qO-~VI9Elv9jBTOTV|aGfdZKNPZUnb%LTZJT}

zPDH4yb+wzK@-2Ys9S~0j(x|&?u5%xSj=fxowk=Kkt+RWpY->0(ouE@bzhN9*dh&`> zU4Y6*7a+9Au5=dLV=`YE89OrGH}(srPq@H*r32OJY(lJ0-j_C;7vzRZcQM^OO~T{> zaU^RvG8hM6`!lBUlXvl^xasx%ed?0JMAOgvBc$RWw^EwW>U&%!UuqlcLWrvglxYsf ze+)ExHPd#)(Utum4Zi+x+>RC^Hx}B8uj>q~Pr+9|iry&4@BjS;dPk5|Rta#te}4Q* zff9)Q4PlnmP$Wp%JU{lo;X&k#OR~1J>|q-xqqu=~!E0?In0@)phQ`TfZwr7*PQz_g)FJkv{=;?Rd^R)g=-A)yVqx8P_?KU}g|ghCuXb~c4ka~(4F7o{ zpI$~tfv&H`T<%bRK9sv2lf@ z^&W8T(z!3Lhe%)cWRCgtv7i7Mb3zhJD z?qxe*%WyYC82X(xP8>2tJ5ig6nS-Asq&cKqz5V$IGruO#XlRs0x&9q2{swY*^lFaB zaJY{}Rz(;gfmJW69Xx4TdN_R-w|4&8m9f<3^}}Kma5wfH%wW)ty4Fa{O!G01u7Xoi$?8aDm zK2Z6V8%!15J&0roZa61Vi&6{tF!ZBx;LUZktLf(BujY>Ts74~+dCk_v2e>Yqf`gpH z)TfFLhNU&0xSPApKm8i*$s##@@3Sy)Iw*b==n5JzQF}?Z0Ee&E-CjJ=_vn>VuzsS= z*^@|6zpWZ4Xk#Y6N7}Q}$DG;Xhw4Nx#TVPYyX@-q>9N+i&krY|6dxBt9_>jCVQY9t zU~m?x!@1x>+WX32u(}Tk)7l}a&K88E{LWxY3DsCy+IzETyVLwo7L>C#PpZrnC%CTs z#D<1TXtIZ|Py3_u$LfIEP;vawuDEx;u9k_B-3`DYPTj=>fyV9YfeuB8JE_xM^)*0# zSx(DB`laJJ00A@BE=HI*Du7s(&H`Lz{1QO3&ZyFXIl4)_S$gtSJH&8&CLqcN?{H67 zZTH)hz}8f|05<8Ry76-1Vw1XHA0VLxTQ&-&60_qG^JVRuypw7%V`fn#-T8pJs&;go zrp}~U14L(oIKq}cvNd}X*~6@Df~B(n2^8lwUnYeOO~!fdnXp`P(kDkVtq&P=orkRD=r7P^z?u0QUJ7XViW>Y*?HhsC_i{%Z!UV_ zPt_(FG|Ox?GxZm!fKG>+aV}K71KOde%mA;@oODaP0n9$kNQx?vQ&n&(p=o$++9`1@ z{mTAe%9|pQy?K+4ZTDGM`&cnnHBMr&ev^@1YMO(FV=Ffsu2|5q4u#bIgCJxNP3ty5l!Xw5E*Zl1%c5=Y)^B z%E#X8yK|EtIsS`qoAN4zetdmAtzvK}Zf%QyegvQT;-gzO+Zc{8U~27O*95PhCk?MC zJ<(^DJ}E7Fr3ZLij(ggo^~S8V`lA~>>$Lv%>&__E$Lfyh9RQ!Xv#_vm2M9YQaL@y_ zE8=ZY%KP-9H$YR+WrOCzzMvjj_~!OncuNWZg3=8KAFQEOHlAe+1{hPdnRg>*zFgt3 z%>T1#xf_Sr1Q#EVEyc{wEz#5t+Hjxi!D(-MhT4-^C{Dfond7DvL`!e>{WD!GwBIZJ&^+oAqlz0c$D z`#+~UjM5LcipyRQ5F8$Yo3pcFTsR_6pEhV|MW?&ITUTUEDXvGo(}k(=URT$EH~ozOJggFtEqAD2kB6hdB1ub?3-p zOpih}l`fSpdC*f6syu7ninP+5x0c z?(FXG8b8@50W9JRcsJ~eBnOm*GDuvEHWx@l=Ruy&Z=*vL{}Eh^@~MUU453ls65y^? zhTqz81$ItWX!7jIf1wJtsy!2fKIB6Tf*C4KC?wy_lBs>AxZ&xU!|puuT$?M7EHPfo zb&LyY?m|jkR#JW)nfffFVoZo(1CVi0fPgEJnAuW`xmEc_mgDN#Ny*l6 z6EH`U0S5mZNt&kgh@HvYSP>(CLwo(i;LJOZW8P!haYLvR{q3)a!Ar;J$geI!K>HT$ zyE5dwTZSupa8mM{`#!C9v!pXE4Sj-aNQRmc z?pS0;;e~zPSYR-%UTryf<&SpZ{_B7~KYa2^wLtdl1At}Yxz>j#g`2*g>V%G4lo$O& zG#E<@?@3e6gE;3iwuroLFQ5D{M*r^T)#;CX`Y%m`o!sMMlgVjg!0Sc1bj3mc_2Oo2 z#z^A+v5)h&=H+0tZr-lxSVQJ!)kmsq>h@3`*`Yskqxf2+2{+M@#8whMrs|>h z-KYq^wi^1uTJ`dP`PmUS0QHnHuQ&3?T-EV6RugwhFQKnZi|3X+s^iC}qdS1ih#uH+ zjk+|rl^N=zIO-b{OMvnaSl)G1e1bgw+Na;`>Ge(z!C1fe%1lS-2hu9M6gPS>58!tc zxw1$_Z|>6X3H<%P8dMZW=HUEaKjT)K5%&ds`q=4&vPYHpt=qpRZE+C%n^BM52+t(|L-B68qw>5c|G~I$@!Tlsa>81z zQyjcB6M)yeQ%%R%O6`X@$8!TE=|v!`IEI<_b*n;q2I1Fqi?DNG9EvZKpyJY>L z^fT zl}33YTg@`D%^s(p-Mnb4tdxAL<$nueHj6*(NrTeX#2*=JZRuR?N2Qd)inp&$x0jPT zgi)!N(!XlAUbgWZ=OqJCDt6UjVsq!AAlN6#6~9xkl{%xv8tv2#?Z2?_Af%5=eid4NzlGci_!tgzRWbHw$H1u-#a|3mpO z#p~qjtV?$lFFIytC$fyI;d#x=CtFy|5~rZd!XJkq<+z6HfhZ+w#C<_qii38m!g@Bt z27~*nmjoxmu*eV_7HR9LlIoJ1Omgj|lfBBfNt8 zoOg-l<#o?6gEs8>P-N|x={SN@o)u&W${PrKP|4uc)1bLqst74XzEo@h35xR+Oa!J1 zIy@j1^h+UyF>^N-pNSVnrjDT@vnL&glkf=J0Cd}IaR4Ibb)Q;w=v8(vY#UHRq`nT+ z4^h-PQFQq0*pVTMXgGV8x0PXSkbG$C-ST0NXVXvdnJcs0^UAkhXB86(=^0-gP;`23 z(Vv=X7}lNvIU2r#`7H(9bVtk*$FfMqH|AyBxyhVD2I%t5?S+)`QsCqdf?)`JkA}vf zg}eUsO@X~IsT1zSd~ZDE3DCMQB*WBCfuel7uWcQ1?HsF2XcQOFZ5rO zwbyiqF6$vZdS1SZZLgbumI|9C1ChevQQ=#4ApAPdu`V|wqrjK$G=t7eZmI3qdaaTF zushnRSpchv6sLY7y&dnfGN8Uz#Ktz#)kd!xybtr&cC}<4Qh)8jnlKMO!>cy0Vy@s( zOn%+isRk?hsrb&uxOGFN&#xWj?6aa*_ny7|R}=RSP#hce|MbTZ?-pZHotQfZZ?z2_ z1M^D}QNMI@-HPe`gFwY;aFS@@4Gl-ncv#FojNWvfDbiZa0tLZ9Ai0H{HYxP_S_(GO z&I1`C;;kxil)npBE*l-QFLD}xTc@^RlCj$yE=z4o@1{e%vKRO0zp7$#O5yPE6<`Hs zeP2*YeSD;vjWTrn*Kg-&ro|G)W8>yEhEwJ5ej4&ih=x~}-S%URbUs$J@RA-8Qb7b0 zHL(|Ymqs-?QDP^jlu^L`;$M{R%U=p)O|hmA8rcqMhtSwAzz0AVg4>bbAghqHG2i`m zf%?CNAdO(l>OJO0voJXAzLEBm)VoZ(TtJjNxJY9}Io`pEa@x19fAkZZZ z1aO;u@TttJqAzlM_72vC-jJtnYu_y?g^tvEH2To`KFL+d3P$cd+Y=WpSpGleISpF~ z8SDDxgAfr#ik$ufXkWZp_IN@VDXI;%c2Ak>yXE-X1pvelwOPI-`D`J4LhUl1?Ri0{ zI#QgX%K<~`?Gk&g7KKku1*EB>is9OXNa~);n-(iUbnja}3gR{3@=OFoL?Yp_0nr86 zA2y||&dw(J<7~szO`8yO%-OlK$EQC^gpJ84e*ii(#V*9-sVB6lSy+GH*OI>0H+Y(l zf5`;!I4ml@;IFZy|6cv|=GBey$}N(4i*UNfaTbMO#1pE4`6@dCKz=dMrMklir=Bv% zQ?^H)QwyL%9JT$3cbL}T1=V#&e+dYtmlF^~XuUD2*IPjZYNVCn)?$+7mFdX~f$4@# zSt?mKa8|_I3U8L_RkbshguOK&*nD0{!++&B zKmZ$GT|E;7xIwu}JeUI#V#f9W z19$n(hv1HJ^UdBT^5>eJHO6Ewz#fAGA35ZEIjMd;$2%)yZgymj77EqqWJko2b2m5| z1z+ylhHu<-9csApoWWRIU*#^CL;z+df6mL{Bm*`JWB(&D4MIl%KQe0}#xmsPBD5fvSX=F5Kr#`8gL7JOv)%HUO!G@_O?h8VTiMO2t4~eb>lr>_ zMj*`>_bwa&poo>pHc=b*?q|Jm0vjAOvvt~Ak*Pn9Qj)t6%*k1S7n+&UbFIio--e1d z);c{cxSpy1Pu`Fh+{-?IFT#Lza|>J`E2=~rP0*w1)3}})Rp)_e17+z?ws-RA*m8PT zQxIU4Oec%DNjnM+{g_c82l`_PP#-0Aq$WfX$pcjhFB_EQ%p=rYXVyaYN}DlQ8jt@U7`3|S_q zllqjnoZc)x449sr)yQW>oeh3W++3g9xj?Rr2u9Hxg#AE$2EUHx|o9wV?L>-w_d1A{tz4fnjYx`two#}~fz$hg21nIr^f zow8ZJ5FXpJ1+bO?^rL`EFiF14Q-lq5FGwv$a02;t`?N0LbQ4hc;ELYP6yq3skO9_< zeSa=C8OeDerDAu#!iZb48fnK-f~>R z8@g??*Orb#N=!i40Nni{Hl2cBZrMayqKvbAnk5X}Q8HN-UFB_+UzUX!a!JS6(?$t@}A=<;w>Me0p(?qMgrHC8LLt>1!WK$ z;qbHxS>SMjc@D<;Ld*R-RqWM38Ys2b)-F5)e9E%Vy#H0CqIruQsyI@}y=1tIR{d50 zE2%O{W1)$Aq;hR92S!O7Ao!o{!w=FRY(;Sb^K2D%aQ4HV&bGh|1wzAAIBmlTAO?RM z2932^mUb%Chp6ka+)&Atbi$V7gAwu@yw!_`1*@;ou?PLOqn=a@?Ri_eDY!=<%CwI|5C{c44d75_d^MtwasNu(Bz7XSaT@#r&TQQ{PefDUnR}i=lneL3S2o zKbc%feS$ZeTjJx1p`07#SB|pMF~mHJ9_-KvRjVYz+WF9I}n&^76PrEx4QAn(*-?k{7l3{PA}OsOx> z|4c%sBAILegP0;B^AD*l`jZh?J!%M0XCz|#J7s;)JN@T)vIm-a9p1;|dtWY*ngOOx3Hh$q$9lVjG5cn)m zro4k$H%Yaq!}Cj3g<0-PN1o2xBO!ud_0E@7QWF+w34Q}4U?$DWiLHlMaLSg6z7V7n zFp?HpT~hHQTm>oMeo)>UUAcMMURn>A)!&MdN9_-=jTj)Nb$y>p+`Oy4IoIGubKmbt$dRgXD8yzbCRwY+MzDOj6v|>D zikUr!+oPc#SG4JD+e9V&d(p+w$_>Sl|I@t_v<9MV7aCnr*zZn?)By&4Z^J2Sn< zv9O9uRPW*+G13_Iy<@K%qSaafJZAX7r0F}r6~%t+HVE$?MP_p>&O5sXn^$_JfgSt7 zPhN8%E9^>Em>9HyATU;;NT|&3?a~J3p)q0ExuBc(fQTn7lagM;#Q1f@Ae3eX-vN)BbB5s@hZf3saCd6|ez7p|I;Md=EYFpDw+_PN z;GX;&!#YY{1;FZ-7GTY;

5pNgHLG2GX04f@dE_fzhrfD)Cb*raeoCa+P z_P-*sm|-)wlK|Z0@i;D!S6_r(&|$gq(TbXA zdL;YADw(FP0z5QiGGeO{n-2V)Y_(fZ#rlVG7xQqGtn`*|>(%Qy+)8*JWYD7f2ivRH z)ENVRaHZLRN^&?Gt)TuG9yDi@v9y|QVi7!|zyVkFe50*rr9wUAIMyjKaii3Z?^0gZ zcv07Zaxb2z!_)0%QI)TxdqfCG7$Aa+w0x!D&#?{Kz)3jtTqw{Go$ET=yoxW_lI6Gq zm`X+NaCS7fX9oP*+Ka7m%A8pxz_ebnyrnCX=VSl_P^O}T@)OyQ(|Nmb;^I2qNb0^_ z8TFHd8xmCHyZrJ|bfU6ssXDD2%cib~WxUyk%$p}rzXOf31|{iowSGXUQYOKAC6fll*MIpFKy_86a4S5|4(_Dv&*I3DH+#5ZS=`AJh$z=%3A@f h(PMGq5^}3($B9ps?bW3FzXHdxKc{}G_*3TP{{UpXM-Tu2 literal 23323 zcmeFZWn2|s)ITc6qomR;-O^Gj-Q9>tNjFG0NJ%%+-Q6kONC?smA{}z*2Jb%pp8vhC z@7sGHKgKxBoU>5k&Ul4joR#ZMjS z>2Yx!N(53qQ1DxYQt88oH@v3fIpXmQBz?WqLJ;s<8FGHEK9<3MPAe$=@32@5jaJuc znV3{+5|_9~$kC6GsmX;f@;N}n@`WGDFli?5hc ztYYPCafYohi;IibcwXCoXmKv*G@lS_cK-8{-{a!z(`Q5hf&SJ{ydJK%jpu8OUpek5 zy*c|SYRw_Ie-WFR{1T}xxcz)a>tyWngR1kvoU*@Jt;vs#x=Dq&wVohZ8y4O_T#t;| zb6Q)qA5Js>(xdK8mr7#FSF?O)71u+K4N@1Am6bK_4nRH`q|2n|JKvv8v{`PJ*4NLr znyV64uh3@DYP5-GP%V%$HqK9T+e$`evwvTJys^1C=!-~N)EXqvg$>5 zx$Kh3X*H)r>Uku5PH4$?-G^0tfB7?Xr#A#U7vespEIC-|eO_u2VLe-+^UCAG>Uy^0 zfhLvPx`bb!G?^RHxZ-ZPaMJK*-FmU1`1zwDA7?anC)AB?37YdJrO=&;d|BherEj4# z(sb$6iMsCQ&+K=SNnMug?C11@1~2|BS{|4};q%5vh+Z7WFbgSyh$|M8N}}kG>)#Y^ z>z7wy&j?gg1V6Xi-@dQZWxl??p7`cqI{*3aeZFKAY4zar<>l(&&tv z@9$2>rZ&g+HPb*A+?_r;(zsbtTs4eFR zAfgduCGnm>3?@bji%-J|wyFlcO9JMLpAd3Pr);)e6LC8mmwfWVP;?-Y#CWO6&M$15aK&w# z#0^Z@c+1`JAo;|P-rvv&Ur`gK%PhRtbrX*##Fo{N$0U}U!q(tBpHlV1eKGoIt^Ic> zqs3G;hkTAT>&USoI%Zi>QBllv$KU%;Tne8-d`Vt*wYcx*C+4hHvpelg?ObNwADB*y zaq8UV(4h@V?1)VY4#0(Dk6h&<+Wo1Y zZ8o`Gau_SteL-6tDfr+@6O18z)~V}xEI#egEgqP!zVjg`5pi663?E+xw$fIL9Cb<^ zN2eIM6_GFa-EgJV&B7Bu$1fxhBApTa49{C2;r*63%Jutk1PC@!N>e>mZIHE$YK zeBDBUYbNcUG%JG07%a&!QrWog^)=6`XYL+Cj^hwRVJ}CQswdyp)v*|HCkiH;XjGf= zaKhdIYIn0<7o`3z!palxI}EmlC>pn&kZx4r*V}0hIf6|#f}Ag7h6SLjsTGOi zK%y;NFXm0-$+Lu4JWqd2yVqc-jcl#sKTIkL;&O^DccyQ5xvP~~wr-_ZLJcdC?r+Xj zbHYf+N-Nt-mikxk4_)@U`@FS#uObb{4V^Alsy-qfME#-BPs(~%sy@ULOueMiNP&3J zV+$Snk{vncQO36<|2;ET`IPP7ey4c=6dWE%g88Vt) zhw$r17JQp@-Er8wpTn@*5d*u^?u>$Tc;A|QT$_g)9LZO7^D z8Khp%kZFXu(`IgyHf!hlm!G82yy0UON9Kc_h<%@V{QzdIhAG<+OxTN6c^c-(2zkK2zxN-x5{eLA(UAyNBb`py=W$pCFddK@RE3;KcdWa)1IWCuge8e@Is3+vgayXv z9Vu_XgAgz6wJu|5o-}^k#s}r}4Cilt!bB%riPiO{6DAj?4`ntRb#013x)M`l<~AE2 zh(H*vRxy36t!?ABZZOqmpnYe9VAyL*xD3&Dg36WE*(@(GOHY|>e<^3ZAp3l${BTw% zSWJOB>rWL^oEMRZ_*;G&`@pWnP=5BY`}mIAEDg0m2K~popOkvBV~%WnV|6;-KUf_P z`Lq>DZ1wm1i`KEcERKDnsZlhI(hOqh+g7$`9#7pK?P|jk_s}0j&O(rRelj3yTEcmj2 zoX}BRnCvuPK6DIYr(2s98?hr-$L};A2q0Cr6sqgO{XxI90^<49TJ;qmCX za3?|BY?cQ}1Tl|-YcQUuX(i7Z0^vgOANxpAcmDczv+>-%E0Y|bdj-4Ku+~#(92>@j zco<$W4X;Ln{|aBfdb*$yxD}?NwEKf^USN)8EcE+hs*4CoVUn-t#UE-#a|~8CSlu~l zgM2fOEk1_y_)_;Vtto~hRhUa!d(YqxnkW}J+TYa%k0?GUF8sjrLQ9aG-crCXqwgdO ze8P4d_`ycbM~@J{pCp|kzHW5=tl`gjfc>uq!!moJN^HZmq_2}bNOOPBCKXGO`K(f( z3;!}rk8PyoIH}BYji$Oe8a7G9j!|qm7!ZA%o-vxUrpXoA*?u}Z$^<3yyuV?i#IT*q}XhA zEO4Gjt?kNl$-mOXebTe+@OB4T_N^Npx(4 zHo0CyZo;r(c0xa&5cDP4C?CW)J%m;VPfW!zw_m=9Q{LgI1|&uWkD#03v!&*$}DtD?f!1(Lbv^3QGet1I3k-Uaht%o$D}zMQ;0E6kYdb&-=mWaJNT6F@%qGU37OE!2YCO$;|7Bh(T#!OfI?O=?37cAhz4fRYb=nmditqo> zM2zUdwAOM+B2)xYzN+=JJb_Qmg4G(NvTFTNWR>pJ1U*w6`$-x^Tozv~$NIx`G{{1A z!OcQP)0S&mYWjoKrj3T*=@n2~k;q8FfB5(FRX?)#P9q($9JBUG}cOyi{Y}myB_V{uj;M z=$I^_d_Hn{ut9>`+0M8{AOZe$$-B}i=3q^s@n1g;dqk7Z2{5zP^@(?Og>inq9?v>& zyL$Z;ea(lhSBpA=FHJW7NC%OmQqZaOVagJ3ZAG|g3F1EAan;8<#r8z|&DnGIfN?JS zAY9T*#IC4kZ&zKnr+4k_at>HqkNk*6JJEv<+o+zo$L|#H_w5At*wddajHh;A6+YiF z7q&_lR4UFB7YI2}Fy-Gp^(%G2^x|ZoS~GcwRN{z05T^H)(#_Afn{o!CUWp)K9iOLg zYCTFtMMdNVbu=dA%a<<`O?K{r0uUi>ZeHxT^D}$K?MMhq z>Wk3*&3t_IK?Xmrirl^>MDYGBPDp5+YVK3VeV(xY)AokM{umzykOEbyMbo03S1;#H z$-2m%aP~$}1c(;~2UbnUj<`Hs*cfRv$64f^Tw&YD}Tamj~6`$^OD1bBDW^ zy<^yEpG6@?r}VV|*D!4xu#UQXX*?w;NK`9Y6vwu^bJ1~e*u=Q^y2{Gg zy5DEZKGd4M;OUkIqy6QM?sxnA*zNWy2RIY70&Rw_(1r^J}=GlWU$6^mIY30#P6IR%&Rs#?qW4Q z&2-;mn7;J{1?N|@_Uo-wnQ#E0?7r<5q~;7*ue5$3;mh)?jV=toFL z)|m)qh&Mk{G19V_KQ_ZlROsk4o+Wb2nX(u-*OuXVBK_vL7dzhtwvu6qZdf|TcN*?4 zGM#Li@nQXS@cz;_hfM(5VnD1Sw+{pY4z5q)m>2oTEvKQ;H|ra$`h2`lk?h;whuh5z zkHZ*QmTzJqi*DQLbcX%mA@X}SBzl^sWKlB)N&oU=!4*d@DkKWX1Sei z&GWi#jFjD%{l0XzPhE1cE^UmZQTU=u=bpx4I;zJ1sc991lZn;OwTmXGlX4_e@FS`B zl|CT=DrY;>lJXeKpJ62SSD2E+-u&(*eP_doUUZ-2Gije#FG{yb$QwU&!=M)e_ZzGE ztJy))Ef*wTk63hSq*l`3h`JyA(TskmGmB|9Cvf@9b`|C0a6!^WCn)H} zK+<5aV{mtMY+rWeJtE#w6`Lqa zbl<-?Q_79;;Bki4exzRYH_YWY@tPgAe{=mk<0PnbbnyGNYb-z1R*N0tk>lZdbMQZ7A|;keYybxwEI-|6B~88$ox^rg^PQyWhqwz0^7YbckpzE}hWJtmVJ>UsTh3Oz z8+)kJ7wMlqr9R zp2Y_*Y+>Q!=}k$1*l%ht0+r!4EWp_1O+=vdIgqp$_2`BQp6yn z$WRrr^L;ieg1>p?q*^cIVtf>lp)z9D_8jJ=ij_zy;t&QbHkO>t&CNa1GayHmE@G?J z70wLS%Z7`ucz<-XN-d|Mq1m%8@ZQ$k@9%jmo%I|V9AdXQ^r^!S0Z8q zXf+8Oqpx$HZ@KY)WvS*-C@z@LzJCz=t2W$sMy(g?gNeBeD#;~KN=y{1(p~qEJ!Bmk zdI9auc<3ub38Diij8f~~q~PoPrbo#oPAPr%iIYpy)R;ZZC!s~nx{qgV3 z>_mgLmT`X)yP?s;-Sx><>L;1EVmK_-%r>;v<>JE|6x4di2vn5KCO?SGf$pOwqWeQy{MOc>)M43Tip@kc~Y_|$$aq3eBZoXl;VGFAFs zG2~^!8w$OG6}6*Nk0>RHW>|qm%5}642{b&Io;1`Q+@|5{?MzkzvM*-Nhf5#WL`#G+f`i9*Gz-7eRxM`7Y` zO=zgAn?ku<24TCXr%~03%|@A%6<{n6P#`K38$5{|E2dgKv+~#P5)ti83VxcL1X2K6 zYvydpf{|tPBHAz>DL@I-PHoPAG@TYpRy{K51LYfNyGEC(^`3!}JFTQgHD#ILAZsWBT%-EszXAIvgJi)54)iFUpiR_R zM48-eN8Hjh5@vz}Kee=fNlVjR{-+g|REW@y_!Mm-fnohsZT4kI%UtY}vm(L~jJbE! zvit|n#To#I;lzl zoisiC^Im^%z>BYpsN4IoYd%jgT<=!9HBtJ$GCF>NtnXQRutnnQMNnLnWHz{G_i|E4 z>p-%xltE2Q+>c{!>CB3jkq&LeLi!T?be`ryb9`6I6nob3Yo=T5BP6Jg)_O!Nj)%4g4^VEANggM7CWO7o-`gaN`WF#J1f&|hDJa<^WGu*&Ko|7WCr9|PW z1uJ5k6E^zBkwaFwcLm9U1Y`vXB$@iu-Anv|Yzwo}#-~GS)W2LH{o*){w{YmC*=WQ3 zjF@{w>KY`P#SRn{6wmt&wcxiewK#Rx4R5nw8xiL7-;5wMFq=RZ?2KByibWhC=Di(%4joohM< z&;DkOg1ZUEJ#W#f%r5$0wn#}#EL4d4U`GOy3C(aKYa%cj?9fwXF8t^n@c`b7@QvgO zIWx=V@2@^$9ihY1OPhzw?qp$9I0@<}h8rj%dlcSC)nBVW9k&@dlYU1;}evAtL( zP>BbarK)}{8Db(kx+Il#2oL{}CLpM80Q?p+7)Mt+Rv@1`MB=hULBi`?))MdG(0RKe ze`ys#*vLbbs%=nM&V9$0T*0^{386*WNcj$RE7NV$Y`?$IGM}wTKZC7)WOmJbZI=VU zP!|y2GtrkW0TL{}T|q@f^=g|MqSf;Hc+AN*1r0wFqsZEEGLW7Gi53bI49XG!CK-F+ zM;UIrTuH6w%AGHf52njtvGJF+iYuQlQOrmL^NVc)+iN|7C$FYPMIwr{9Ew9XpxVH$ z)nT*z7GCea_b8J^1c4EHwRY6vvtU%}^vw5ZP=ZfP2EDspiwjIWPGGd*6_%8dvlrq&|_PcQUUruWV6E6*!inu4ZhIOybEul1w-K)`#` zqXrV*2~1(+ad+1QMENMk4-XD1<1?`=WIbu>ZK4_uBu$rZcv_xb#kWSKrzYkftk?o; z7-{eEYV4XJZ@^7pNCOE4d2jh&!G%q}&4N`G35;6`@$>&ms~1b*vHO6a@^V;5pZp!|v9=0sBs(%WCU$zmkPbd*m zkpe)7JA|B<@>*edq_RL4WFYl47#9DEnL+i|_WY)%*XF5A57m3}NYdCG!Xl9TP2)ZG zaAfQ!j&v(WVJ#;$xFU=>@Km_4x5-jWEAK46;ALO^W2R4k(#?UgKhVw$ajfk7MS4s& zj&iE@Z}P>IjvKmE$D!E2kGs>g`WzXAejhJGHf zV@Ain`^>cx&Ery~wJbT&C8CAMLCP5)P3J{@NYmdQP4^>xshb+k^Eu_YV~9NVa$M&B zWVCc=hY?e1mmrn*9)iP0Kz`P-1m_LW1V;f#QN@VaZk(^)C;|x7{j?IJr-) z$AON(uI7GuXnlr5pjx+PonX6aUOHZ4YC`=>7Gk~|;te-8B^K&9&l~rnT2HpY8p?5w zPOjdr;|`%ociKbDF~?^=e%49hG^g}``s`KY01O?ydiO^vJo!<8ey^AbBK9tz5-U`yAQ(SiJG#(sJ#DXbCi>Os#Ir$k1}RDyJ4W3n%eg& z{hp;!+@jZQt}6-g5Dg1s|8idoY9={)B=F3Fw?~pW;AXRlTGKJ1p2;zWFZ+is|H_AD zGmWNBEH>I4P@ly~l6i6Ne_D}sk^e8Yn)f5FwA3;E{G4J}PJvWW}ztB`Srv4k_ z(+97N`d(nA*u=pT9CEe;9kK?%Zz*{>Rn$nIy9FUQqD-yF4=N8iT#G~kSkc(nSk(M}WhJ;-toC(*|FpTc8hif` zsd-%a^WG(D-%fzgBuc=d50KbnmwEtSeu)71g7Oc2woy#MqULJ{)#XNLP<1D$hy8C$ zkpkjP!9yz{H_~UEf@6X3&n7LDvD0nV4esBvJ})Vyl+7){VmcGbwWd;W_-N79YOKaS z2EbSIkot09y-4u$gM1A0`tTtc2NxIF>incfO|6~Vp8eDFsVC{>-JG9hv;kQdUp^Uh z(+V_yu+}UP?ODcsX$%l55}V>qB(VN28^y9{{e!k*-lXpoF-nMDY--m8g!}EXdbr1L zVLEO!E+}lmIOI-*{D{&bS2p||#I>|I(|^mtzubFEYVm*$;F|iuA9>{$ALW>YU&Eox zzgpupD__Ff*H8!@NI=PTT(9x5WU+K1zF5jly*u;swlH2=BNz?HTJh2Oje(Y$W7Z3??M_~Uv0k)0d-+f{EV8u#5 znKO)vXE*HcedD#9yNflOo~`wq+s>&r(~dft0n#t#*cXaxKS1JA)VDUP>rs9KymPs~ zSap0^?A*VfFlXs@s~$Unt_cjw4CoTL*?{dF6hT(T#3YRx}*3W|(h@0$w0=PYyg&1MRZ}Et?oX zZkHBf>)X@N(G`w9y zh^Ql|5YVCFVMRd>nu%hoF~&Xc#awe1!;B5N3CKUqLgUK+(nZPjNgUKq2tbcQyn5NC zY*9p~OXW19_Ta#BjodIhvn7T;xWW4kAYAZgz!?kb#H2&N|4)u7%0>AX&`peGSy`R4 zjmd8@9O9r5NgvAQMwx#Jmdo}%8mbtC9i%Kw@_*k*G&yq>4~0mRPf=K0^dTGH~g*moInpZ7%8=)0N0LCKtimYt|b%>crlB)v)Q z8seX{CLT6ISXTUpL_~C`HU`IYfje=f4WO zZu&1iIx{r_22uooG6Z4c)%43_z703uoXv=l)#xx#;FUr~Iy0cF01pQ2E!ZtqzckzC zPl=I}s6gUyYVP&!$Q@AEV#wNJk=Qb#^X&v{|L-$Ssnn)|phpfgzI#vz!@mqt@9w|B zgH;vb6Z4+-Hvgw>2>U~blcBc@phP}uKKn!N+lw)ANNmN;V&n3b5HUKs$8y62VxUmHg1rj34Zuws1|Kro~X zm8>Ok+lZL}EQUospbb>(VYD5uP3!JivKG{}0*TnvE&a=B7qL$%eHSpmg7x~1dm2bH z+SUhB*92gK-5)5Taa?&7b*!|1tu{a~$w+%bsric$WMjK0+Rj{xPixEvmZIpM3o*)hP+69C}hqZig*7 zH&EFdgDCU+a1B8HAkf=h0(mq*T3Jt#ZoxWAyL; zB3{Zmz!;guw=TpC$jxOM)gr*$Po(W06KkGGpcvAvQJx9dkeg&GYbpdfkQd;UNLSe4 z&BdS68Q}+Du0A;#W*r7anh_9gMo*tuXmvFAzz%t{0G*jdgp7*q3Wt-1nV;Iu6NKcP zgwW3lQf*>&+uV1HIz7RH1`g9BLPEuQ2|tYgr{Le~F+WsiU`zL_R*D-=xl^NBpgH`R z?Z4-AJJ_J11?borXKy+LEjZfL(O{}j9DsPFe{K-`FCG`qhfd>!bl?xJnc(-f;lI7p zV@?W-Qk{&TYQR#l4XM7sc9EH{`nigy6{ojtgH;s>V1n>F^TatA>o-wM@D2YrfvQsi z=B?ZjTYP^6v8=GLZ)Iler?_&KB0_P<40cv3Z;-0XY$8L7rzk_xUaV&nicvcUu z>U-3+sT-CGVViyrcB1C-5Zh7(XoJ-EVK@`t>qYdx$oav)Ap-z}IIP~cPYn&? zHqfFnHsFZIS}7!i-|}Oat(1Mc@jZ{`w3VL2{$U#rJ{56Uo$q^U*9%{(u#j)DbMdN0 z?m0VNzuy#cH}%#{SD=Q>1Sa}a&-z~xQY^`ZGk{iu)k}zs*8Nf}NE=hs7*`oZ|ItG_ zqzjt0zOMqIcM9Y`DZzx%JpV^(FYH~)ez}P8;RRTs$RS}42C>L3=SB-_;&JJZ^>Ksv zVk&CzUh(Z+1T9RKQc?4 zd&)B@p*8M#C%}Z&5#oT3oR=u1DF!G`vUqgCJEfynjfiBPY~?gn@M_208f7F6S|ifg z6zqNagGWYavBA3Z@La*P*vg)R!<^BE9`r!?XFXT(+TS}|Zh@B!7H9yBqdVzfsekzJ zAy?DE-rk~@0&MSRzM| zMFta_ki+CVn2(!&s4UUaakTkQkb%siL7|B;n)<2zLtC@^LY?^uyv1W>qr7p2=x^uu z4ATrZi2}J~N?`13NON8=e@TWmEX3wol!&rv^1D#kmtE#22GrhJf3D4D@8WvwV zMW*ThTO{zvs!6SLzx zym<>m{^gp`{k%(=J3)o`n^gH_&OW(83+BMgu z*WnSa3wYfX2_2lCo?6C;{&{YPLT}$`@ubxZT~OfIuK{=9aITta&z-%UvwY~IRc#d%5sJYuImCic}#J0xQLm+!iRp1)Ju@> z7JGdHh{<2?FIPLB25D%mIU9=X1rpmtb6L)OzlC*F_BR4kt=R5zi%b1F`vt$tp*B1p zPdR)z=I7RSUHg)88pfZnD&0v7kyyG0ER<}A_x)E}D^S$NlNstIm33aWw(?Cg)*#E3 zG??^wDVnUqdqAdJ_&~cv3C(na0WuMkEL$;Cz#c4=!~B;^REgU5AwmS~oE#=2NfrYJ z4PLU{;slyFZ)s`{1yB;LfMz1hbzkkhgH^ySqN!oPPf?zPnq5 zYd)`ZZ-is)tA0;lalWeU-b0(NryZqlQl{i+7fHiaqrA^ zyBFXiO)Ce{0b+&4c$>pVrH1=vl}C)!ppD~LiJviZMEy*Jo!UQ@>Q}ocIoxjmmU_vr zbO>u=od+Gd9-(7B&w1s})yJO-+#YZc3V1fjY;y_5CxP|X03y*Z#=hkYnibS;frBGC z<&lUdD6yF&Hf-K%8!%B05Q`jdCvJZ=xPq>yB*}F*|A4nVy@P~U^$C>yeZg)Z=6Ht< zal1dCEv?ZnR?B%*EzwE9B%*VwntVhC;A++=|G4XBZw+2s9gQxL)_T3{LC_!-ooMhJ z=u|2aJ6H=MQ#Xu1wps=RB)mzEB+?pMMsNGHX@j6*oL_NUV4EB7l4=LJtastv z$5t-m>FrgC_Hz!oze)Jn0&CY|rs`f$VxsFlMP*y^TcLL!x_OqC^e$*Fr!eF^BY1#% z5=41%Lv=fjVeVDrD|EmdyrY7iH+I~YYxd6oZj|frdbcoBVn7$($P_(Poqh#(IA%b1mNvH_SA*3G)u8`+}Yz+zE=`^Dqy@u{HdsE z9FyJ4drOY%X$iUw-iLMf!{Y(j%i#CEjxAJ;vFZ|msHDN+nTHE4WyQ*3X;Bfu+r^S( z%&QV&?-5zAtu?BZ--@jWMDJF$DWlF$lz0><4xc{xDx|QXkG*G()l?tVl`h1WILGhg zY}hvE4jc(Xty1Xr8a+>IyzZMVo*MSiNpKU3JrKQHR6T$4@MJMd!*D+ z>}tl>vomel^qAaPmEZEI&pN#Y~6(WX=`f1Qw&#re2mHW16ATatAto3RFN6Em$oO zVE#OUHo-PyjTTIRb*7Igx4nV} zwMcg^qwR?8q2=^?W@1yNAiy+FEf|4K?^59Yr@FbQl+EoK{Cb65>*Ei3pG=|uiRXrD ziviiAQFr0h?P1?cRWmG=Do#@HkC!_Rt1i|Ns&8lW>CJp*(hmjB+&@8~QhhUYl4JP^ z+iEUrrF^R79pkylcR5^c+{D+a+eF*f^F#~<^9q2I4 z#Q*47jrQU-+n=)P{}?hzfP6zi+izD07Sbb7hlld|fL5W$Z!VV{o>UTc$&S*>r%->s z-~Sk2RsU&KfVs%;puO-30S65N7MlVP9pOsnzs6S+X^pvh%lGFhjmX%vNGqbT&;N(H zUS|#`j1}rc2AnD&r;s1gvR|DjAwgSD2ONL0uCmhK;oQZ z;gz3C+usITDa*e3yb_F>d2$ zaBW9-rPW;Zn;9c=G^p(lLi*YAZ%H2qd<2sk3)ocN9{u!k>HI|teo6;%+@?y}Y4@;T zloNyeqhI-z3vUlE2M)eXk>!H^iW)hjL!2FCFFDOT-?{ExNHv8tJt?J*$2LPCW@o`1r1 z;AW2A8)sBarH(_I+q;NgauF%NP1TS;KuN+oDps0)QV-t`4`lodQz$A6XVY zeKOOEqe&O%PHDS1=dc;Rj(+|%A!GzTxm}|r4?MO|QBc0tw>bZKWx=)VlKVP2xetnh zsyVcJ*rbiJ*ihAkbCGHzCbrDRq}3oN?y^7g!`h|%cU3`6QIS;J;tGs~efd)J9XtAo zl-^k|h5b$R1CCNu>qIgWGi4}`(P-KmRTNazP2g+hHWAcb1GkTGm{o^x+)EMv!xk!V zliyE22V*5b{j$h!v-EoK$FnhFsiC1EHN|gs>-~OfXpx_9N~;%bo-Mn4p2@Pq^a3tv zV_7X&;L!iT zqPeA@c**Zj*5gXs411_>GNgQKI{G3RsKaoKXW#V%|Egswuxt_?J^R)MiN3a20+`{s zUbNpEh=~Eoy995>@C8QLAK>!sG4r)UHEV`xhGsDN6N6Or(ie2k8y$`Cy(0jI`o_Y9 zh~OPy<9-sh|M_YS(G95VCGn)#vVeb%17y*=u*PdtVAd6}ZcO$6M zZg<+`rpy6USlTbvovz*X)5F}XS!d^=%f0nkhZB0<9ZN5D!29mkYB`cGyM(!FKU6CoNdUnZVwUg;_~Fc=!d?0I>DI}r`O9aC}t3)rFWKa1AoLQ526aN zo_(408bITN34}fl9j~Vpx@=RQ^K`=ypUT&qsn99SxF1|8L`{1nR=-TA`1CpVrCyp^ z%zJDfP-P8v+IjV$uBTZn%o|Hgz~Vg~SYrmn*=d_e2N}_Ml@DfE zM+~44%L51A);UcuVO9AE6~QSM*H?lAg3M;+oH0;ODc}>ch`W8R_4#g1l8l=Sc)6%C zWH9>xgFXNAcB+9pim7&?^8(N~zdK&WxIXFN9sJ^RV zVPQ|g?!NuZOk_a5N(HhEJf=@nyuI5iErDy!>sf4nj8Gul1p@TpyTkU}cHprS{S#M6 zfv}1VS5>_(y%uwQsWFfszHo8Zz}hnCImy(ODY+&tsxX9t665uM%kd0`4mQ(E}l4f8wK*QlWaupEJoZ-(nl*3S%zg7Ox3tZ#fx<|8OsR$N5oY=`|2FyvkEt($l>B(OEx)8 zj>Sm=&YHji^iUktmnWC-WCTI|WIEqs*7tb@rDJ$L1b7zUFC^y;V%yX*pKepw{P}9kdakTh+M%<8v8fH?ecGJ6yr&GZrSN6{tvN50Y zgHvyMu@%KKgF;k3gB-Dk{`(E^oS0AKg~0S(xqj}ps|vNL40|{K^>9k5!cVz(M@o6p zFLpM{3qvC!o;?8p(sbmlYq6>6gCTLjfA9E4|BL{|3~65gTb!FVCz*|Vaa#ktTBTVv zv~A34HsJDf((7_Gl)(~64ST-C%P#2Ao=E|RE$ECiKD5eWacVD@FR6Vzn^OPn>IA#6 z)mWATG&J7e8v4O>XWIz=QwJp^Vm*POv^5aXtLZO38*L|aK}*+6>EdY z$k=UPoLrc{tt+hXvoZ(ftb)dXr{5?FRJfO%9OqYQ?N8`&&E!(K;fR9iV>ekwYXBlY z$5rN|WtYFR%5zL;<-tIng(tGXN$^)iw~_gd*w@1ruOHxYyqxf8!$fIvxLaTm3pn4~ zx1-Qh7uAfJ&BnFgzLOS{IwN=)P{ z6jtQzinP)k!W;eXHA0=7K))z*UcLVPdQv{{8bmYDLlwm8Z&#Y^3>oO@f3?9z7q+;; zC)vT3&}LZwA|eMhcs&rDMm$_;(>f{`gWEZIylCHaR4+TOMr0dFfKrPAt}hrH8=rvp z#JmHI7mV}OhC%R`&vg1e-kgwSl`l>D-3nfvBXY_AMblITlwpQ&{SCaU22S_MjF6`+ zH#^0R3I5dv?ICZ9-&baY6LAeCb&ZDC-9{$6jC68Zt|8>HWq*%Orw`ahtf!dEseo#Y6i?rH<~Iczr!oe8@yd#fhCw~ z!xtPC2*#ltY*gmctw7S~w69KOvhF46>PP|}0leYX2h)XgIOXNbmlj_ccw7`OZfYeU z67UP~*@Ry;c=1nOU0vN%l<*+RqxN$mGXi0dg)!i?KP7Tv8>m-_@LKt?eTSn;^w;n~ z)IWkdK$5-$@%{xyHFZ%Az@*V+y%;D9{PGbLj1aNT@4XY*L8LF?C;{-G#rX;jia{Yw%8-k+jwLWr%bBNZNIAcD-V3Q`aP7Sc-u<{XJ7H#%xQSLkPWp-qkP6e2;J z(ETXX7|a!N1RkIwg5EtU_;wUP`lQ0_gz!7l1ndXR%K9(h+pg3?nCD2LgWv*yF9S#h z5h&~bwy8ielT?zEfWM*22Api8Mj#2_CIyZqem{d(@FCa&H?~u5_iOm}5$H$W!^DXL zb2-|F7@SOu+y8G{5^f&PN(zU+#cBz7z?X~IBH`P7pdxpN_8I-VNZ_g1llWryZ#xEz zf{Gqk%m4QhI{)`6{O?5i|6D9kgfTKR$1_&8s(`-GHleScK$$-I)3`bWmNe{y0mpBv zpZ|J&yI8Qy2gPLiY$*wHMEJq~Rn58oGui)fyiJo%SW8YbqoR}{qShR8NQLAqrx3-h zVdQYH+h)iiq@49_xT(8MvE-P@*_6sTVx%O)l4U9k_vh;S)AvvK{&xLv?Xm58T-Wva zyx;HV>#37v{d6&y`c-UzHRjcPY<8`pd%^8?^9H3o)Ma$nJQxS*0)f|PO^{yT%7uvf z$>ZG{LQ3LvWzw!Pm#VY#wUgqz{rf5ketlSP5|p5mX&MY zBlZ8hw^Q##K!)`_o-ADyY#DlW7JRY|u;&4Nve*1pCh)hJmj3zcV**0?C);pcOD<;~ zoS#nbfAeGCYhU;Bm?zG6b&Rl%Xd)npmgZKVB==Q&YR-Yla&{S^Ju_0(}rbmq1Oyg%6#h=qH za5mG_S>{6@z{~Z4cH2n|9Uo>p&3^WQJf{vV*&`nqHhX8@mHsCrH0& z7L<;$a<29K4*5YXC-<gr@l{s>$N&&WNj4buN@u|hVCXgvDBwa;NDbijdm732el}P3e4n14Q);nNBebRq zv77MR&^6$RbF%S!(v_`l*V5qMuL3cXXkgZxHHI+EDX1%$fFYlrdJcHX{S!}s*ywEr z*cNm`l&Lj!C8N%d6xb;07M=UJIn4^}_Kz$Ury1B9nqH(VKY$u;YT{_8GB;+M7;>Tt z^q{6*=mos91XJF}&Ya|EZsY5nBCr7$;yLtK_ z;oL~EF32)?g&vj-L{lzMfx&Rvq1{%|e*r`P-^;hkt4Len0~q|&QKUNrqXEC$thvW1 zdcgXopF%)2=wy^Q#U)FD$=c2%ppOtnGcMG$Ab=gv;9{%kmKKoYW#X_pfr4{<_brz5 zz~!btNIpYWB;#v1A;~(#5qqJaKDZ zlcOM7C?|e`r|DoI5CCEv2ZrS+w*{`1$zPR;F|beKcy6Jb8Lf$Sf}A3Q(*Ii7U*x|K z8xxH=SljWal?%JBw@{4u0d=ZpX-abNNKh&s(n_;pHMU+xC%?pv?ddU5$Kf1}@4Y@p zw=RM1AFBtcwN=&wt>DgmL>acR76Vh^@)cx6HIYc|F<2YjSso`SJQ-Ugt!Oz8E~bOE ztp;lu#ETuy2oS7f#1P60@Ot>OQAIg3*R<&;NX`B*Gs4>&m@GS^s^nW3H8?pqSPuz$ z-AtVG*y@0CQTWQjMQFh45FCXBv32>ux#KhUGcpg%=I=Az9cb7g9)S8ZsAM{-&c%mr z+dPYCJ(Lt1g(sO%hzRPgY1?d&`xDUjG+GbXnajHDPTu&;e3na zfg=C1DZo2E(w>Nk5ZzI?*GRHY7E9pL^MRGKS4u=O$kiC=BeR&!UeOpC)7?c|osgFN z1leE1`IM{6J+XcB0lXLXjhDt$;G0dh2!vYWc?YEyT#PcA2kxS@Hpawd=5U zOURJ{)ygqtUy|y115OZ4@l}kR zpw*qGZM^=SHcu_S(w$G!csv95c0=uSxv0~rn4!xh)jd0MI*qi~GM+2St9+?$*zkd< zNa6FhXpux~=g8lU*sZ>%nA|t!P1XIUYJ^MWlwWPiVVN&q%E7mdGh&A)95MIX?@P8> ze%OK3aIeRw=u4=GYGoD@7hXv%(Ga}cyol_r%h#(={-hVs!>Q{sq#Hw;1Jvm&fVK}1 zYo2Iy!n!z;B^RSk;z)9@zU)?_>*K^~B6;Qnatz12bRYt4mZGdOLkB3XegT#NNG_+M|!IDi+(qC-XK<_V8+dsCfwukduH=GH| zKf6;MB2bN3coQU$Zz5`-W2`TTsAS&ZZ-Qz;hO!Z|)Vo<7IzF8TTC%=A0BZ!Nm4N#1 zk#q2Gqp__D81Kl+N`P~)G&S()|I@FKjQS=7h`F6X?iQ%GU^Kk-v!kOUMJ8PA@NX&e gK)jKu;gt>Qdz;s6hZ5HnAh_Oi#_XJFnXzZgzsAwS0RR91 diff --git a/doc/images/dict-cs.png b/doc/images/dict-cs.png index ccc02b0d17134efca5b4df2e932e901b474eaea2..55e5ef518fed8b9c598a79ec614c8064be8edd7c 100644 GIT binary patch literal 93837 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 literal 25052 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 6`), -specifying if decompressed data size is provided within the header. -The `Flag_Value` can be converted into `Field_Size`, +specifying if `Frame_Content_Size` (the decompressed data size) +is provided within the header. +`Flag_Value` provides `FCS_Field_Size`, which is the number of bytes used by `Frame_Content_Size` according to the following table: -|`Flag_Value`| 0 | 1 | 2 | 3 | -| ---------- | ------ | --- | --- | --- | -|`Field_Size`| 0 or 1 | 2 | 4 | 8 | +| `Flag_Value` | 0 | 1 | 2 | 3 | +| -------------- | ------ | --- | --- | --- | +|`FCS_Field_Size`| 0 or 1 | 2 | 4 | 8 | -When `Flag_Value` is `0`, `Field_Size` depends on `Single_Segment_flag` : +When `Flag_Value` is `0`, `FCS_Field_Size` depends on `Single_Segment_flag` : if `Single_Segment_flag` is set, `Field_Size` is 1. -Otherwise, `Field_Size` is 0 (content size not provided). +Otherwise, `Field_Size` is 0 : `Frame_Content_Size` is not provided. __`Single_Segment_flag`__ If this flag is set, data must be regenerated within a single continuous memory segment. -In this case, `Frame_Content_Size` is necessarily present, -but `Window_Descriptor` byte is skipped. +In this case, `Window_Descriptor` byte is skipped, +but `Frame_Content_Size` is necessarily present. As a consequence, the decoder must allocate a memory segment of size equal or bigger than `Frame_Content_Size`. In order to preserve the decoder from unreasonable memory requirements, -a decoder can reject a compressed frame +a decoder is allowed to reject a compressed frame which requests a memory size beyond decoder's authorized range. For broader compatibility, decoders are recommended to support memory sizes of at least 8 MB. -This is just a recommendation, +This is only a recommendation, each decoder is free to support higher or lower limits, depending on local limitations. @@ -224,37 +226,38 @@ It also specifies the size of this field as `Field_Size`. #### `Window_Descriptor` -Provides guarantees on maximum back-reference distance -that will be used within compressed data. +Provides guarantees on minimum memory buffer required to decompress a frame. This information is important for decoders to allocate enough memory. -The `Window_Descriptor` byte is optional. It is absent when `Single_Segment_flag` is set. -In this case, the maximum back-reference distance is the content size itself, -which can be any value from 1 to 2^64-1 bytes (16 EB). +The `Window_Descriptor` byte is optional. +When `Single_Segment_flag` is set, `Window_Descriptor` is not present. +In this case, `Window_Size` is `Frame_Content_Size`, +which can be any value from 0 to 2^64-1 bytes (16 ExaBytes). | Bit numbers | 7-3 | 2-0 | | ----------- | ---------- | ---------- | | Field name | `Exponent` | `Mantissa` | -Maximum distance is given by the following formulas : +The minimum memory buffer size is called `Window_Size`. +It is described by the following formulas : ``` windowLog = 10 + Exponent; windowBase = 1 << windowLog; windowAdd = (windowBase / 8) * Mantissa; Window_Size = windowBase + windowAdd; ``` -The minimum window size is 1 KB. -The maximum size is `15*(1<<38)` bytes, which is 1.875 TB. +The minimum `Window_Size` is 1 KB. +The maximum `Window_Size` is `(1<<41) + 7*(1<<38)` bytes, which is 3.75 TB. To properly decode compressed data, a decoder will need to allocate a buffer of at least `Window_Size` bytes. In order to preserve decoder from unreasonable memory requirements, -a decoder can refuse a compressed frame +a decoder is allowed to reject a compressed frame which requests a memory size beyond decoder's authorized range. For improved interoperability, -decoders are recommended to be compatible with window sizes of 8 MB, +decoders are recommended to be compatible with `Window_Size >= 8 MB`, and encoders are recommended to not request more than 8 MB. It's merely a recommendation though, decoders are free to support larger or lower limits, @@ -264,112 +267,118 @@ depending on local limitations. This is a variable size field, which contains the ID of the dictionary required to properly decode the frame. -Note that this field is optional. When it's not present, +`Dictionary_ID` field is optional. When it's not present, it's up to the decoder to make sure it uses the correct dictionary. -Format is little-endian. Field size depends on `Dictionary_ID_flag`. 1 byte can represent an ID 0-255. 2 bytes can represent an ID 0-65535. 4 bytes can represent an ID 0-4294967295. +Format is __little-endian__. It's allowed to represent a small ID (for example `13`) -with a large 4-bytes dictionary ID, losing some compacity in the process. +with a large 4-bytes dictionary ID, even if it is less efficient. _Reserved ranges :_ If the frame is going to be distributed in a private environment, any dictionary ID can be used. However, for public distribution of compressed frames using a dictionary, -the following ranges are reserved for future use and should not be used : -- low range : 1 - 32767 -- high range : >= (2^31) - +the following ranges are reserved and shall not be used : +- low range : `<= 32767` +- high range : `>= (1 << 31)` #### `Frame_Content_Size` This is the original (uncompressed) size. This information is optional. -The `Field_Size` is provided according to value of `Frame_Content_Size_flag`. -The `Field_Size` can be equal to 0 (not present), 1, 2, 4 or 8 bytes. -Format is little-endian. +`Frame_Content_Size` uses a variable number of bytes, provided by `FCS_Field_Size`. +`FCS_Field_Size` is provided by the value of `Frame_Content_Size_flag`. +`FCS_Field_Size` can be equal to 0 (not present), 1, 2, 4 or 8 bytes. -| `Field_Size` | Range | -| ------------ | ---------- | -| 1 | 0 - 255 | -| 2 | 256 - 65791| -| 4 | 0 - 2^32-1 | -| 8 | 0 - 2^64-1 | +| `FCS_Field_Size` | Range | +| ---------------- | ---------- | +| 0 | unknown | +| 1 | 0 - 255 | +| 2 | 256 - 65791| +| 4 | 0 - 2^32-1 | +| 8 | 0 - 2^64-1 | -When `Field_Size` is 1, 4 or 8 bytes, the value is read directly. -When `Field_Size` is 2, _the offset of 256 is added_. +`Frame_Content_Size` format is __little-endian__. +When `FCS_Field_Size` is 1, 4 or 8 bytes, the value is read directly. +When `FCS_Field_Size` is 2, _the offset of 256 is added_. It's allowed to represent a small size (for example `18`) using any compatible variant. + Blocks ------- -After the magic number and header of each block, -there are some number of blocks. -Each frame must have at least one block but there is no upper limit -on the number of blocks per frame. + +After `Magic_Number` and `Frame_Header`, there are some number of blocks. +Each frame must have at least one block, +but there is no upper limit on the number of blocks per frame. The structure of a block is as follows: -| `Last_Block` | `Block_Type` | `Block_Size` | `Block_Content` | -|:------------:|:------------:|:------------:|:---------------:| -| 1 bit | 2 bits | 21 bits | n bytes | +| `Block_Header` | `Block_Content` | +|:--------------:|:---------------:| +| 3 bytes | n bytes | -The block header (`Last_Block`, `Block_Type`, and `Block_Size`) uses 3-bytes. +`Block_Header` uses 3 bytes, written using __little-endian__ convention. +It contains 3 fields : + +| `Last_Block` | `Block_Type` | `Block_Size` | +|:------------:|:------------:|:------------:| +| bit 0 | bits 1-2 | bits 3-23 | __`Last_Block`__ The lowest bit signals if this block is the last one. -The frame will end after this one. +The frame will end after this last block. It may be followed by an optional `Content_Checksum` (see [Zstandard Frames](#zstandard-frames)). -__`Block_Type` and `Block_Size`__ - -The next 2 bits represent the `Block_Type`, -while the remaining 21 bits represent the `Block_Size`. -Format is __little-endian__. +__`Block_Type`__ +The next 2 bits represent the `Block_Type`. There are 4 block types : -| Value | 0 | 1 | 2 | 3 | +| Value | 0 | 1 | 2 | 3 | | ------------ | ----------- | ----------- | ------------------ | --------- | | `Block_Type` | `Raw_Block` | `RLE_Block` | `Compressed_Block` | `Reserved`| - `Raw_Block` - this is an uncompressed block. - `Block_Content` contains `Block_Size` bytes to read and copy - as decoded data. + `Block_Content` contains `Block_Size` bytes. -- `RLE_Block` - this is a single byte, repeated N times. - `Block_Content` consists of a single byte, - and `Block_Size` is the number of times this byte should be repeated. +- `RLE_Block` - this is a single byte, repeated `Block_Size` times. + `Block_Content` consists of a single byte. + On the decompression side, this byte must be repeated `Block_Size` times. - `Compressed_Block` - this is a [Zstandard compressed block](#compressed-blocks), explained later on. `Block_Size` is the length of `Block_Content`, the compressed data. - The decompressed size is unknown, + The decompressed size is not known, but its maximum possible value is guaranteed (see below) - `Reserved` - this is not a block. This value cannot be used with current version of this specification. +__`Block_Size`__ + +The upper 21 bits of `Block_Header` represent the `Block_Size`. + Block sizes must respect a few rules : -- In compressed mode, compressed size is always strictly less than decompressed size. -- Block decompressed size is always <= maximum back-reference distance. +- For `Compressed_Block`, `Block_Size` is always strictly less than decompressed size. +- Block decompressed size is always <= `Window_Size` - Block decompressed size is always <= 128 KB. -A data block is not necessarily "full" : -since an arbitrary “flush” may happen anytime, -block decompressed content can be any size (even empty), +A block can contain any number of bytes (even empty), up to `Block_Maximum_Decompressed_Size`, which is the smallest of : -- Maximum back-reference distance +- `Window_Size` - 128 KB + Compressed Blocks ----------------- -To decompress a compressed block, the compressed size must be provided from -`Block_Size` field in the block header. +To decompress a compressed block, the compressed size must be provided +from `Block_Size` field within `Block_Header`. A compressed block consists of 2 sections : - [Literals Section](#literals-section) @@ -381,36 +390,34 @@ data in [Sequence Execution](#sequence-execution) #### Prerequisites To decode a compressed block, the following elements are necessary : - Previous decoded data, up to a distance of `Window_Size`, - or all previous data when `Single_Segment_flag` is set. -- List of "recent offsets" from the previous compressed block. -- Decoding tables of the previous compressed block for each symbol type + or all previously decoded data when `Single_Segment_flag` is set. +- List of "recent offsets" from previous `Compressed_Block`. +- Decoding tables of previous `Compressed_Block` for each symbol type (literals, literals lengths, match lengths, offsets). Literals Section ---------------- -During sequence execution, symbols from the literals section -During sequence phase, literals will be entangled with match copy operations. All literals are regrouped in the first part of the block. -They can be decoded first, and then copied during sequence operations, -or they can be decoded on the flow, as needed by sequence commands. - -| `Literals_Section_Header` | [`Huffman_Tree_Description`] | Stream1 | [Stream2] | [Stream3] | [Stream4] | -| ------------------------- | ---------------------------- | ------- | --------- | --------- | --------- | +They can be decoded first, and then copied during [Sequence Execution], +or they can be decoded on the flow during [Sequence Execution]. Literals can be stored uncompressed or compressed using Huffman prefix codes. When compressed, an optional tree description can be present, followed by 1 or 4 streams. +| `Literals_Section_Header` | [`Huffman_Tree_Description`] | Stream1 | [Stream2] | [Stream3] | [Stream4] | +| ------------------------- | ---------------------------- | ------- | --------- | --------- | --------- | + #### `Literals_Section_Header` Header is in charge of describing how literals are packed. It's a byte-aligned variable-size bitfield, ranging from 1 to 5 bytes, -using little-endian convention. +using __little-endian__ convention. | `Literals_Block_Type` | `Size_Format` | `Regenerated_Size` | [`Compressed_Size`] | -| --------------------- | ------------- | ------------------ | ----------------- | -| 2 bits | 1 - 2 bits | 5 - 20 bits | 0 - 18 bits | +| --------------------- | ------------- | ------------------ | ------------------- | +| 2 bits | 1 - 2 bits | 5 - 20 bits | 0 - 18 bits | In this representation, bits on the left are the lowest bits. @@ -418,33 +425,38 @@ __`Literals_Block_Type`__ This field uses 2 lowest bits of first byte, describing 4 different block types : -| `Literals_Block_Type` | Value | -| ----------------------------- | ----- | -| `Raw_Literals_Block` | 0 | -| `RLE_Literals_Block` | 1 | -| `Compressed_Literals_Block` | 2 | -| `Repeat_Stats_Literals_Block` | 3 | +| `Literals_Block_Type` | Value | +| --------------------------- | ----- | +| `Raw_Literals_Block` | 0 | +| `RLE_Literals_Block` | 1 | +| `Compressed_Literals_Block` | 2 | +| `Treeless_Literals_Block` | 3 | - `Raw_Literals_Block` - Literals are stored uncompressed. -- `RLE_Literals_Block` - Literals consist of a single byte value repeated N times. +- `RLE_Literals_Block` - Literals consist of a single byte value + repeated `Regenerated_Size` times. - `Compressed_Literals_Block` - This is a standard Huffman-compressed block, starting with a Huffman tree description. See details below. -- `Repeat_Stats_Literals_Block` - This is a Huffman-compressed block, +- `Treeless_Literals_Block` - This is a Huffman-compressed block, using Huffman tree _from previous Huffman-compressed literals block_. - Huffman tree description will be skipped. - Note: If this mode is used without any previous Huffman-table in the frame - (or [dictionary](#dictionary-format)), this should be treated as corruption. + `Huffman_Tree_Description` will be skipped. + Note: If this mode is triggered without any previous Huffman-table in the frame + (or [dictionary](#dictionary-format)), this should be treated as data corruption. __`Size_Format`__ `Size_Format` is divided into 2 families : -- For `Raw_Literals_Block` and `RLE_Literals_Block` it's enough to decode `Regenerated_Size`. -- For `Compressed_Block`, its required to decode both `Compressed_Size` - and `Regenerated_Size` (the decompressed size). It will also decode the number of streams. +- For `Raw_Literals_Block` and `RLE_Literals_Block`, + it's only necessary to decode `Regenerated_Size`. + There is no `Compressed_Size` field. +- For `Compressed_Block` and `Treeless_Literals_Block`, + it's required to decode both `Compressed_Size` + and `Regenerated_Size` (the decompressed size). + It's also necessary to decode the number of streams (1 or 4). -For values spanning several bytes, convention is little-endian. +For values spanning several bytes, convention is __little-endian__. __`Size_Format` for `Raw_Literals_Block` and `RLE_Literals_Block`__ : @@ -463,9 +475,9 @@ __`Size_Format` for `Raw_Literals_Block` and `RLE_Literals_Block`__ : Only Stream1 is present for these cases. Note : it's allowed to represent a short value (for example `13`) -using a long format, accepting the increased compressed data size. +using a long format, even if it's less efficient. -__`Size_Format` for `Compressed_Literals_Block` and `Repeat_Stats_Literals_Block`__ : +__`Size_Format` for `Compressed_Literals_Block` and `Treeless_Literals_Block`__ : - Value 00 : _A single stream_. Both `Regenerated_Size` and `Compressed_Size` use 10 bits (0-1023). @@ -480,67 +492,68 @@ __`Size_Format` for `Compressed_Literals_Block` and `Repeat_Stats_Literals_Block Both `Regenerated_Size` and `Compressed_Size` use 18 bits (0-262143). `Literals_Section_Header` has 5 bytes. -Both `Compressed_Size` and `Regenerated_Size` fields follow little-endian convention. -Note: `Compressed_Size` __includes__ the size of the Huffman Tree description if it -is present. +Both `Compressed_Size` and `Regenerated_Size` fields follow __little-endian__ convention. +Note: `Compressed_Size` __includes__ the size of the Huffman Tree description +_when_ it is present. ### Raw Literals Block -The data in Stream1 is `Regenerated_Size` bytes long, and contains the raw literals data -to be used in sequence execution. +The data in Stream1 is `Regenerated_Size` bytes long, +it contains the raw literals data to be used during [Sequence Execution]. ### RLE Literals Block Stream1 consists of a single byte which should be repeated `Regenerated_Size` times to generate the decoded literals. -### Compressed Literals Block and Repeat Stats Literals Block -Both of these modes contain Huffman encoded data +### Compressed Literals Block and Treeless Literals Block +Both of these modes contain Huffman encoded data. +`Treeless_Literals_Block` does not have a `Huffman_Tree_Description`. #### `Huffman_Tree_Description` This section is only present when `Literals_Block_Type` type is `Compressed_Literals_Block` (`2`). The format of the Huffman tree description can be found at [Huffman Tree description](#huffman-tree-description). -The size Huffman Tree description will be determined during the decoding process, -and must be used to determine where the compressed Huffman streams begin. +The size of `Huffman_Tree_Description` is determined during decoding process, +it must be used to determine where streams begin. +`Total_Streams_Size = Compressed_Size - Huffman_Tree_Description_Size`. -If repeat stats mode is used, the Huffman table used in the previous compressed block will -be used to decompress this block as well. +For `Treeless_Literals_Block`, +the Huffman table comes from previously compressed literals block. -Huffman compressed data consists either 1 or 4 Huffman-coded streams. +Huffman compressed data consists of either 1 or 4 Huffman-coded streams. If only one stream is present, it is a single bitstream occupying the entire -remaining portion of the literals block, encoded as described at +remaining portion of the literals block, encoded as described within [Huffman-Coded Streams](#huffman-coded-streams). If there are four streams, the literals section header only provides enough -information to know the regenerated and compressed sizes of all four streams combined. -The regenerated size of each stream is equal to `(totalSize+3)/4`, except for the last stream, -which may be up to 3 bytes smaller, to reach a total decompressed size match that described -in the literals header. +information to know the decompressed and compressed sizes of all four streams _combined_. +The decompressed size of each stream is equal to `(Regenerated_Size+3)/4`, +except for the last stream which may be up to 3 bytes smaller, +to reach a total decompressed size as specified in `Regenerated_Size`. -The compressed size of each stream is provided explicitly: the first 6 bytes of the compressed -data consist of three 2-byte little endian fields, describing the compressed sizes -of the first three streams. -The last streams size is computed from the total compressed size and the size of the other -three streams. +The compressed size of each stream is provided explicitly: +the first 6 bytes of the compressed data consist of three 2-byte __little-endian__ fields, +describing the compressed sizes of the first three streams. +`Stream4_Size` is computed from total `Total_Streams_Size` minus sizes of other streams. -`stream4CSize = totalCSize - 6 - stream1CSize - stream2CSize - stream3CSize`. +`Stream4_Size = Total_Streams_Size - 6 - Stream1_Size - Stream2_Size - Stream3_Size`. -Note: remember that totalCSize may be smaller than the `Compressed_Size` found in the literals -block header as `Compressed_Size` also contains the size of the Huffman Tree description if it -is present. +Note: remember that `Total_Streams_Size` can be smaller than `Compressed_Size` in header, +because `Compressed_Size` also contains `Huffman_Tree_Description_Size` when it is present. Each of these 4 bitstreams is then decoded independently as a Huffman-Coded stream, as described at [Huffman-Coded Streams](#huffman-coded-streams) + Sequences Section ----------------- A compressed block is a succession of _sequences_ . A sequence is a literal copy command, followed by a match copy command. A literal copy command specifies a length. -It is the number of bytes to be copied (or extracted) from the literal section. +It is the number of bytes to be copied (or extracted) from the Literals Section. A match copy command specifies an offset and a length. When all _sequences_ are decoded, -if there is are any literals left in the _literal section_, +if there are literals left in the _literal section_, these bytes are added at the end of the block. This is described in more detail in [Sequence Execution](#sequence-execution) @@ -557,7 +570,7 @@ followed by the bitstream. | -------------------------- | ------------------------- | ---------------- | ---------------------- | --------- | To decode the `Sequences_Section`, it's required to know its size. -This size is deduced from `blockSize - literalSectionSize`. +This size is deduced from `Block_Size - Literals_Section_Size`. #### `Sequences_Section_Header` @@ -572,7 +585,7 @@ This is a variable size field using between 1 and 3 bytes. Let's call its first byte `byte0`. - `if (byte0 == 0)` : there are no sequences. The sequence section stops there. - Regenerated content is defined entirely by literals section. + Decompressed content is defined entirely as Literals Section content. - `if (byte0 < 128)` : `Number_of_Sequences = byte0` . Uses 1 byte. - `if (byte0 < 255)` : `Number_of_Sequences = ((byte0-128) << 8) + byte1` . Uses 2 bytes. - `if (byte0 == 255)`: `Number_of_Sequences = byte1 + (byte2<<8) + 0x7F00` . Uses 3 bytes. @@ -581,14 +594,14 @@ __Symbol compression modes__ This is a single byte, defining the compression mode of each symbol type. -|Bit number| 7-6 | 5-4 | 3-2 | 1-0 | +|Bit number| 7-6 | 5-4 | 3-2 | 1-0 | | -------- | ----------------------- | -------------- | -------------------- | ---------- | |Field name| `Literals_Lengths_Mode` | `Offsets_Mode` | `Match_Lengths_Mode` | `Reserved` | The last field, `Reserved`, must be all-zeroes. `Literals_Lengths_Mode`, `Offsets_Mode` and `Match_Lengths_Mode` define the `Compression_Mode` of -literals lengths, offsets, and match lengths respectively. +literals lengths, offsets, and match lengths symbols respectively. They follow the same enumeration : @@ -598,17 +611,17 @@ They follow the same enumeration : - `Predefined_Mode` : A predefined FSE distribution table is used, defined in [default distributions](#default-distributions). - The table takes no space in the compressed data. + No distribution table will be present. - `RLE_Mode` : The table description consists of a single byte. - This code will be repeated for every sequence. + This code will be repeated for all sequences. - `Repeat_Mode` : The table used in the previous compressed block will be used again. No distribution table will be present. - Note: this includes RLE mode, so if repeat_mode follows rle_mode the same symbol will be repeated. + Note: this includes RLE mode, so if `Repeat_Mode` follows `RLE_Mode`, the same symbol will be repeated. If this mode is used without any previous sequence table in the frame (or [dictionary](#dictionary-format)) to repeat, this should be treated as corruption. - `FSE_Compressed_Mode` : standard FSE compression. A distribution table will be present. - The format of this distribution table is described in (FSE Table Description)[#fse-table-description]. + The format of this distribution table is described in [FSE Table Description](#fse-table-description). Note that the maximum allowed accuracy log for literals length and match length tables is 9, and the maximum accuracy log for the offsets table is 8. @@ -625,7 +638,7 @@ Literals length codes are values ranging from `0` to `35` included. They define lengths from 0 to 131071 bytes. The literals length is equal to the decoded `Baseline` plus the result of reading `Number_of_Bits` bits from the bitstream, -as a little-endian value. +as a __little-endian__ value. | `Literals_Length_Code` | 0-15 | | ---------------------- | ---------------------- | @@ -654,7 +667,7 @@ Match length codes are values ranging from `0` to `52` included. They define lengths from 3 to 131074 bytes. The match length is equal to the decoded `Baseline` plus the result of reading `Number_of_Bits` bits from the bitstream, -as a little-endian value. +as a __little-endian__ value. | `Match_Length_Code` | 0-31 | | ------------------- | ----------------------- | @@ -685,7 +698,7 @@ Recommendation is to support at least up to `22`. For information, at the time of this writing. the reference decoder supports a maximum `N` value of `28` in 64-bits mode. -An offset code is also the number of additional bits to read in little-endian fashion, +An offset code is also the number of additional bits to read in __little-endian__ fashion, and can be translated into an `Offset_Value` using the following formulas : ``` @@ -720,8 +733,8 @@ begins. FSE decoding requires a 'state' to be carried from symbol to symbol. For more explanation on FSE decoding, see the [FSE section](#fse). -For sequence decoding, a separate state must be kept track of for each of -literal lengths, offsets, and match lengths. +For sequence decoding, a separate state keeps track of each +literal lengths, offsets, and match lengths symbols. Some FSE primitives are also used. For more details on the operation of these primitives, see the [FSE section](#fse). @@ -753,8 +766,7 @@ See the [description of the codes] for how to determine these values. [description of the codes]: #the-codes-for-literals-lengths-match-lengths-and-offsets Decoding starts by reading the `Number_of_Bits` required to decode `Offset`. -It then does the same for `Match_Length`, -and then for `Literals_Length`. +It then does the same for `Match_Length`, and then for `Literals_Length`. This sequence is then used for [sequence execution](#sequence-execution). If it is not the last sequence in the block, @@ -807,6 +819,7 @@ short offsetCodes_defaultDistribution[29] = 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 }; ``` + Sequence Execution ------------------ Once literals and sequences have been decoded, @@ -826,7 +839,8 @@ in this case. The offset is defined as from the current position, so an offset of 6 and a match length of 3 means that 3 bytes should be copied from 6 bytes back. -Note that all offsets must be at most equal to the window size defined by the frame header. +Note that all offsets leading to previously decoded data +must be smaller than `Window_Size` defined in `Frame_Header_Descriptor`. #### Repeat offsets As seen in [Sequence Execution](#sequence-execution), @@ -842,11 +856,10 @@ so an `offset_value` of 1 means `Repeated_Offset2`, an `offset_value` of 2 means `Repeated_Offset3`, and an `offset_value` of 3 means `Repeated_Offset1 - 1_byte`. -In the first block, the offset history is populated with the following values : 1, 4 and 8 (in order). +For the first block, the starting offset history is populated with the following values : 1, 4 and 8 (in order). -Then each block gets its starting offset history from the ending values of the most recent compressed block. -Note that non-compressed blocks are skipped, -they do not contribute to offset history. +Then each block gets its starting offset history from the ending values of the most recent `Compressed_Block`. +Note that blocks which are not `Compressed_Block` are skipped, they do not contribute to offset history. [Offset Codes]: #offset-codes @@ -859,6 +872,7 @@ This means that when `Repeated_Offset1` (most recent) is used, history is unmodi When `Repeated_Offset2` is used, it's swapped with `Repeated_Offset1`. If any other offset is used, it becomes `Repeated_Offset1` and the rest are shift back by one. + Skippable Frames ---------------- @@ -878,7 +892,7 @@ Skippable frames defined in this specification are compatible with [LZ4] ones. __`Magic_Number`__ -4 Bytes, little-endian format. +4 Bytes, __little-endian__ format. Value : 0x184D2A5?, which means any value from 0x184D2A50 to 0x184D2A5F. All 16 values are valid to identify a skippable frame. @@ -886,13 +900,14 @@ __`Frame_Size`__ This is the size, in bytes, of the following `User_Data` (without including the magic number nor the size field itself). -This field is represented using 4 Bytes, little-endian format, unsigned 32-bits. +This field is represented using 4 Bytes, __little-endian__ format, unsigned 32-bits. This means `User_Data` can’t be bigger than (2^32-1) bytes. __`User_Data`__ The `User_Data` can be anything. Data will just be skipped by the decoder. + Entropy Encoding ---------------- Two types of entropy encoding are used by the Zstandard format: @@ -900,7 +915,7 @@ FSE, and Huffman coding. FSE --- -FSE, or FiniteStateEntropy is an entropy coding based on [ANS]. +FSE, short for Finite State Entropy, is an entropy codec based on [ANS]. FSE encoding/decoding involves a state that is carried over between symbols, so decoding must be done in the opposite direction as encoding. Therefore, all FSE bitstreams are read from end to beginning. @@ -909,15 +924,15 @@ For additional details on FSE, see [Finite State Entropy]. [Finite State Entropy]:https://github.com/Cyan4973/FiniteStateEntropy/ -FSE decoding involves a decoding table which has a power of 2 size and three elements: +FSE decoding involves a decoding table which has a power of 2 size, and contain three elements: `Symbol`, `Num_Bits`, and `Baseline`. The `log2` of the table size is its `Accuracy_Log`. The FSE state represents an index in this table. -The next symbol in the stream is the symbol indicated by the table value for that state. -To obtain the next state value, -the decoder should consume `Num_Bits` bits from the stream as a little endian value and add it to baseline. -To obtain the initial state value, consume `Accuracy_Log` bits from the stream as a little endian value. +To obtain the initial state value, consume `Accuracy_Log` bits from the stream as a __little-endian__ value. +The next symbol in the stream is the `Symbol` indicated in the table for that state. +To obtain the next state value, +the decoder should consume `Num_Bits` bits from the stream as a __little-endian__ value and add it to `Baseline`. [ANS]: https://en.wikipedia.org/wiki/Asymmetric_Numeral_Systems @@ -929,7 +944,7 @@ An FSE distribution table describes the probabilities of all symbols from `0` to the last present one (included) on a normalized scale of `1 << Accuracy_Log` . -It's a bitstream which is read forward, in little-endian fashion. +It's a bitstream which is read forward, in __little-endian__ fashion. It's not necessary to know its exact size, since it will be discovered and reported by the decoding process. @@ -1064,7 +1079,7 @@ Huffman Coding -------------- Zstandard Huffman-coded streams are read backwards, similar to the FSE bitstreams. -Therefore, to find the start of the bitstream it is therefore necessary to +Therefore, to find the start of the bitstream, it is therefore to know the offset of the last byte of the Huffman-coded stream. After writing the last bit containing information, the compressor @@ -1077,7 +1092,7 @@ byte to read. The decompressor needs to skip 0-7 initial `0`-bits and the first `1`-bit it occurs. Afterwards, the useful part of the bitstream begins. -The bitstream contains Huffman-coded symbols in little-endian order, +The bitstream contains Huffman-coded symbols in __little-endian__ order, with the codes defined by the method below. ### Huffman Tree Description @@ -1182,14 +1197,14 @@ The Huffman header compression uses 2 states, which share the same FSE distribution table. The first state (`State1`) encodes the even indexed symbols, and the second (`State2`) encodes the odd indexes. -State1 is initialized first, and then State2, and they take turns decoding -a single symbol and updating their state. +`State1` is initialized first, and then `State2`, and they take turns +decoding a single symbol and updating their state. For more details on these FSE operations, see the [FSE section](#fse). The number of symbols to decode is determined by tracking bitStream overflow condition: If updating state after decoding a symbol would require more bits than -remain in the stream, it is assumed the extra bits are 0. Then, +remain in the stream, it is assumed that extra bits are 0. Then, the symbols for each of the final states are decoded and the process is complete. ##### Conversion from weights to Huffman prefix codes @@ -1245,7 +1260,7 @@ it would be encoded as: |Encoding|`0000`|`0001`|`01`|`1`| `10000` | Starting from the end, -it's possible to read the bitstream in a little-endian fashion, +it's possible to read the bitstream in a __little-endian__ fashion, keeping track of already used bits. Since the bitstream is encoded in reverse order, by starting at the end the symbols can be read in forward order. @@ -1258,13 +1273,14 @@ If a bitstream is not entirely and exactly consumed, hence reaching exactly its beginning position with _all_ bits consumed, the decoding process is considered faulty. + Dictionary Format ----------------- -Zstandard is compatible with "raw content" dictionaries, free of any format restriction, -except that they must be at least 8 bytes. -These dictionaries function as if they were just the `Content` block of a formatted -dictionary. +Zstandard is compatible with "raw content" dictionaries, +free of any format restriction, except that they must be at least 8 bytes. +These dictionaries function as if they were just the `Content` part +of a formatted dictionary. But dictionaries created by `zstd --train` follow a format, described here. @@ -1274,9 +1290,9 @@ __Pre-requisites__ : a dictionary has a size, | `Magic_Number` | `Dictionary_ID` | `Entropy_Tables` | `Content` | | -------------- | --------------- | ---------------- | --------- | -__`Magic_Number`__ : 4 bytes ID, value 0xEC30A437, little-endian format +__`Magic_Number`__ : 4 bytes ID, value 0xEC30A437, __little-endian__ format -__`Dictionary_ID`__ : 4 bytes, stored in little-endian format. +__`Dictionary_ID`__ : 4 bytes, stored in __little-endian__ format. `Dictionary_ID` can be any value, except 0 (which means no `Dictionary_ID`). It's used by decoders to check if they use the correct dictionary. @@ -1284,9 +1300,9 @@ _Reserved ranges :_ If the frame is going to be distributed in a private environment, any `Dictionary_ID` can be used. However, for public distribution of compressed frames, - the following ranges are reserved for future use and should not be used : + the following ranges are reserved and shall not be used : - - low range : 1 - 32767 + - low range : <= 32767 - high range : >= (2^31) __`Entropy_Tables`__ : following the same format as the tables in compressed blocks. @@ -1298,26 +1314,30 @@ __`Entropy_Tables`__ : following the same format as the tables in compressed blo These tables populate the Repeat Stats literals mode and Repeat distribution mode for sequence decoding. It's finally followed by 3 offset values, populating recent offsets (instead of using `{1,4,8}`), - stored in order, 4-bytes little-endian each, for a total of 12 bytes. + stored in order, 4-bytes __little-endian__ each, for a total of 12 bytes. Each recent offset must have a value < dictionary size. __`Content`__ : The rest of the dictionary is its content. The content act as a "past" in front of data to compress or decompress, so it can be referenced in sequence commands. As long as the amount of data decoded from this frame is less than or - equal to the window-size, sequence commands may specify offsets longer - than the lenght of total decoded output so far to reference back to the - dictionary. After the total output has surpassed the window size however, + equal to `Window_Size`, sequence commands may specify offsets longer + than the total length of decoded output so far to reference back to the + dictionary. After the total output has surpassed `Window_Size` however, this is no longer allowed and the dictionary is no longer accessible. [compressed blocks]: #the-format-of-compressed_block + + Appendix A - Decoding tables for predefined codes ------------------------------------------------- -This appendix contains FSE decoding tables for the predefined literal length, match length, and offset -codes. The tables have been constructed using the algorithm as given above in the -"from normalized distribution to decoding tables" chapter. The tables here can be used as examples -to crosscheck that an implementation implements the decoding table generation algorithm correctly. +This appendix contains FSE decoding tables +for the predefined literal length, match length, and offset codes. +The tables have been constructed using the algorithm as given above in chapter +"from normalized distribution to decoding tables". +The tables here can be used as examples +to crosscheck that an implementation build its decoding tables correctly. #### Literal Length Code: @@ -1496,6 +1516,7 @@ to crosscheck that an implementation implements the decoding table generation al Version changes --------------- +- 0.2.5 : minor typos and clarifications - 0.2.4 : section restructuring, by Sean Purcell - 0.2.3 : clarified several details, by Sean Purcell - 0.2.2 : added predefined codes, by Johannes Rudolph diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 204f56ea5f21..2e77e7742f60 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1,10 +1,10 @@ -zstd 1.1.4 Manual +zstd 1.2.0 Manual -

zstd 1.1.4 Manual

+

zstd 1.2.0 Manual


Contents

    @@ -57,46 +57,46 @@
    size_t ZSTD_compress( void* dst, size_t dstCapacity,
                     const void* src, size_t srcSize,
                           int compressionLevel);
    -

    Compresses `src` content as a single zstd compressed frame into already allocated `dst`. - Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`. - @return : compressed size written into `dst` (<= `dstCapacity), - or an error code if it fails (which can be tested using ZSTD_isError()). +

    Compresses `src` content as a single zstd compressed frame into already allocated `dst`. + Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`. + @return : compressed size written into `dst` (<= `dstCapacity), + or an error code if it fails (which can be tested using ZSTD_isError()).


    size_t ZSTD_decompress( void* dst, size_t dstCapacity,
                       const void* src, size_t compressedSize);
    -

    `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. - `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()). +

    `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. + `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()).


    unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
    -

    NOTE: This function is planned to be obsolete, in favour of ZSTD_getFrameContentSize. - ZSTD_getFrameContentSize functions the same way, returning the decompressed size of a single - frame, but distinguishes empty frames from frames with an unknown size, or errors. +

    NOTE: This function is planned to be obsolete, in favour of ZSTD_getFrameContentSize. + ZSTD_getFrameContentSize functions the same way, returning the decompressed size of a single + frame, but distinguishes empty frames from frames with an unknown size, or errors. - Additionally, ZSTD_findDecompressedSize can be used instead. It can handle multiple - concatenated frames in one buffer, and so is more general. - As a result however, it requires more computation and entire frames to be passed to it, - as opposed to ZSTD_getFrameContentSize which requires only a single frame's header. + Additionally, ZSTD_findDecompressedSize can be used instead. It can handle multiple + concatenated frames in one buffer, and so is more general. + As a result however, it requires more computation and entire frames to be passed to it, + as opposed to ZSTD_getFrameContentSize which requires only a single frame's header. - '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. + '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.


    Helper functions

    int         ZSTD_maxCLevel(void);               /*!< maximum compression level available */
    @@ -106,28 +106,28 @@ const char* ZSTD_getErrorName(size_t code);     /*!< provides readable strin
     

    Explicit memory management

    
     
    -

    Compression context

       When compressing many times,
    -   it is recommended to allocate a context just once, and re-use it for each successive compression operation.
    -   This will make workload friendlier for system's memory.
    -   Use one context per thread for parallel execution in multi-threaded environments. 
    +

    Compression context

      When compressing many times,
    +  it is recommended to allocate a context just once, and re-use it for each successive compression operation.
    +  This will make workload friendlier for system's memory.
    +  Use one context per thread for parallel execution in multi-threaded environments. 
     
    typedef struct ZSTD_CCtx_s ZSTD_CCtx;
     ZSTD_CCtx* ZSTD_createCCtx(void);
     size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);
     

    size_t ZSTD_compressCCtx(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel);
    -

    Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()). +

    Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()).


    -

    Decompression context

       When decompressing many times,
    -   it is recommended to allocate a context just once, and re-use it for each successive compression operation.
    -   This will make workload friendlier for system's memory.
    -   Use one context per thread for parallel execution in multi-threaded environments. 
    +

    Decompression context

      When decompressing many times,
    +  it is recommended to allocate a context just once, and re-use it for each successive compression operation.
    +  This will make workload friendlier for system's memory.
    +  Use one context per thread for parallel execution in multi-threaded environments. 
     
    typedef struct ZSTD_DCtx_s ZSTD_DCtx;
     ZSTD_DCtx* ZSTD_createDCtx(void);
     size_t     ZSTD_freeDCtx(ZSTD_DCtx* dctx);
     

    size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
    -

    Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()). +

    Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()).


    Simple dictionary API

    
    @@ -169,9 +169,10 @@ size_t     ZSTD_freeDCtx(ZSTD_DCtx* dctx);
                                     void* dst, size_t dstCapacity,
                               const void* src, size_t srcSize,
                               const ZSTD_CDict* cdict);
    -

    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. +

    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. + Frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no)


    ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
    @@ -399,7 +400,7 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v
     


    ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, unsigned byReference,
    -                                      ZSTD_parameters params, ZSTD_customMem customMem);
    +                                      ZSTD_compressionParameters cParams, ZSTD_customMem customMem);
     

    Create a ZSTD_CDict using external alloc and free, and customized compression parameters


    @@ -426,12 +427,19 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v both values are optional, select `0` if unknown.


    -
    size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
    -                               void* dst, size_t dstCapacity,
    -                         const void* src, size_t srcSize,
    -                         const void* dict,size_t dictSize,
    -                               ZSTD_parameters params);
    -

    Same as ZSTD_compress_usingDict(), with fine-tune control of each compression parameter +

    size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
    +                      void* dst, size_t dstCapacity,
    +                const void* src, size_t srcSize,
    +                const void* dict,size_t dictSize,
    +                      ZSTD_parameters params);
    +

    Same as ZSTD_compress_usingDict(), with fine-tune control over each compression parameter +


    + +
    size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
    +                      void* dst, size_t dstCapacity,
    +                const void* src, size_t srcSize,
    +                const ZSTD_CDict* cdict, ZSTD_frameParameters fParams);
    +

    Same as ZSTD_compress_usingCDict(), with fine-tune control over frame parameters


    Advanced decompression functions

    
    @@ -491,20 +499,29 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v
         Note : this use case also happens when using a non-conformant dictionary.
       - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
       - This is not a Zstandard frame.
    -  When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. 
    +  When identifying the exact failure cause, it's possible to use ZSTD_getFrameParams(), which will provide a more precise error code. 
     


    Advanced streaming functions

    
     
     

    Advanced Streaming compression functions

    ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
    +size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);   /**< size of CStream is variable, depending primarily on compression level */
     size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize);   /**< pledgedSrcSize must be correct, a size of 0 means unknown.  for a frame size of 0 use initCStream_advanced */
     size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */
     size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
                                                  ZSTD_parameters params, unsigned long long pledgedSrcSize);  /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */
     size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);  /**< note : cdict will just be referenced, and must outlive compression session */
    -size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);  /**< re-use compression parameters from previous init; skip dictionary loading stage; zcs must be init at least once before. note: pledgedSrcSize must be correct, a size of 0 means unknown.  for a frame size of 0 use initCStream_advanced */
    -size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
    +size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize, ZSTD_frameParameters fParams);  /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
     

    +
    size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
    +

    start a new compression job, using same parameters from previous job. + This is typically useful to skip dictionary loading stage, since it will re-use it in-place.. + Note that zcs must be init at least once before using ZSTD_resetCStream(). + pledgedSrcSize==0 means "srcSize unknown". + If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end. + @return : 0, or an error code (which can be tested using ZSTD_isError()) +


    +

    Advanced Streaming decompression functions

    typedef enum { DStream_p_maxWindowSize } ZSTD_DStreamParameter_e;
     ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
     size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */
    @@ -552,10 +569,9 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
     

    Buffer-less streaming compression functions

    size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
     size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
     size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */
    +size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
    +size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize);   /* compression parameters are already set within cdict. pledgedSrcSize=0 means null-size */
     size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**<  note: if pledgedSrcSize can be 0, indicating unknown size.  if it is non-zero, it must be accurate.  for 0 size frames, use compressBegin_advanced */
    -size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize can be 0, indicating unknown size.  if it is non-zero, it must be accurate.  for 0 size frames, use compressBegin_advanced */
    -size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
    -size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
     

    Buffer-less streaming decompression (synchronous mode)

       A ZSTD_DCtx object is required to track streaming operations.
    @@ -640,19 +656,20 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
         - Compressing and decompressing require a context structure
           + Use ZSTD_createCCtx() and ZSTD_createDCtx()
         - It is necessary to init context before starting
    -      + compression : ZSTD_compressBegin()
    -      + decompression : ZSTD_decompressBegin()
    -      + variants _usingDict() are also allowed
    -      + copyCCtx() and copyDCtx() work too
    -    - Block size is limited, it must be <= ZSTD_getBlockSizeMax()
    -      + If you need to compress more, cut data into multiple blocks
    -      + Consider using the regular ZSTD_compress() instead, as frame metadata costs become negligible when source size is large.
    +      + compression : any ZSTD_compressBegin*() variant, including with dictionary
    +      + decompression : any ZSTD_decompressBegin*() variant, including with dictionary
    +      + copyCCtx() and copyDCtx() can be used too
    +    - Block size is limited, it must be <= ZSTD_getBlockSizeMax() <= ZSTD_BLOCKSIZE_ABSOLUTEMAX
    +      + If input is larger than a block size, it's necessary to split input data into multiple blocks
    +      + For inputs larger than a single block size, consider using the regular ZSTD_compress() instead.
    +        Frame metadata is not that costly, and quickly becomes negligible as source size grows larger.
         - When a block is considered not compressible enough, ZSTD_compressBlock() result will be zero.
           In which case, nothing is produced into `dst`.
           + User must test for such outcome and deal directly with uncompressed data
           + ZSTD_decompressBlock() doesn't accept uncompressed data as input !!!
    -      + In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history.
    -        Use ZSTD_insertBlock() in such a case.
    +      + In case of multiple successive blocks, should some of them be uncompressed,
    +        decoder must be informed of their existence in order to follow proper history.
    +        Use ZSTD_insertBlock() for such a case.
     

    Raw zstd block functions

    size_t ZSTD_getBlockSizeMax(ZSTD_CCtx* cctx);
    diff --git a/examples/simple_compression.c b/examples/simple_compression.c
    index 9d448712ec34..ab1131475575 100644
    --- a/examples/simple_compression.c
    +++ b/examples/simple_compression.c
    @@ -116,7 +116,6 @@ static char* createOutFilename_orDie(const char* filename)
     int main(int argc, const char** argv)
     {
         const char* const exeName = argv[0];
    -    const char* const inFilename = argv[1];
     
         if (argc!=2) {
             printf("wrong arguments\n");
    @@ -125,6 +124,8 @@ int main(int argc, const char** argv)
             return 1;
         }
     
    +    const char* const inFilename = argv[1];
    +
         char* const outFilename = createOutFilename_orDie(inFilename);
         compress_orDie(inFilename, outFilename);
         free(outFilename);
    diff --git a/examples/streaming_compression.c b/examples/streaming_compression.c
    index 4c2c1a1d8bc7..24ad15bd614c 100644
    --- a/examples/streaming_compression.c
    +++ b/examples/streaming_compression.c
    @@ -112,7 +112,6 @@ static const char* createOutFilename_orDie(const char* filename)
     int main(int argc, const char** argv)
     {
         const char* const exeName = argv[0];
    -    const char* const inFilename = argv[1];
     
         if (argc!=2) {
             printf("wrong arguments\n");
    @@ -121,6 +120,8 @@ int main(int argc, const char** argv)
             return 1;
         }
     
    +    const char* const inFilename = argv[1];
    +
         const char* const outFilename = createOutFilename_orDie(inFilename);
         compressFile_orDie(inFilename, outFilename, 1);
     
    diff --git a/examples/streaming_decompression.c b/examples/streaming_decompression.c
    index 400aa673d64b..bb2d80987081 100644
    --- a/examples/streaming_decompression.c
    +++ b/examples/streaming_decompression.c
    @@ -99,7 +99,6 @@ static void decompressFile_orDie(const char* fname)
     int main(int argc, const char** argv)
     {
         const char* const exeName = argv[0];
    -    const char* const inFilename = argv[1];
     
         if (argc!=2) {
             fprintf(stderr, "wrong arguments\n");
    @@ -108,6 +107,8 @@ int main(int argc, const char** argv)
             return 1;
         }
     
    +    const char* const inFilename = argv[1];
    +
         decompressFile_orDie(inFilename);
         return 0;
     }
    diff --git a/lib/Makefile b/lib/Makefile
    index 197fdeeea033..d8d8e179d205 100644
    --- a/lib/Makefile
    +++ b/lib/Makefile
    @@ -71,6 +71,9 @@ libzstd.a: $(ZSTD_OBJ)
     	@echo compiling static library
     	@$(AR) $(ARFLAGS) $@ $^
     
    +libzstd.a-mt: CPPFLAGS += -DZSTD_MULTHREAD
    +libzstd.a-mt: libzstd.a
    +
     $(LIBZSTD): LDFLAGS += -shared -fPIC -fvisibility=hidden
     $(LIBZSTD): $(ZSTD_FILES)
     	@echo compiling dynamic library $(LIBVER)
    @@ -86,10 +89,17 @@ endif
     
     libzstd : $(LIBZSTD)
     
    +libzstd-mt : CPPFLAGS += -DZSTD_MULTITHREAD
    +libzstd-mt : libzstd
    +
     lib: libzstd.a libzstd
     
    -lib-release: DEBUGFLAGS :=
    +lib-mt: CPPFLAGS += -DZSTD_MULTITHREAD
    +lib-mt: lib
    +
    +lib-release lib-release-mt: DEBUGFLAGS :=
     lib-release: lib
    +lib-release-mt: lib-mt
     
     clean:
     	@$(RM) -r *.dSYM   # Mac OS-X specific
    diff --git a/lib/README.md b/lib/README.md
    index 3357e3d87096..79b6fd50014d 100644
    --- a/lib/README.md
    +++ b/lib/README.md
    @@ -22,6 +22,14 @@ Some additional API may be useful if you're looking into advanced features :
                               They are not "stable", their definition may change in the future.
                               Only static linking is allowed.
     
    +#### ZSTDMT API
    +
    +To enable multithreaded compression within the library, invoke `make lib-mt` target.
    +Prototypes are defined in header file `compress/zstdmt_compress.h`.
    +When linking a program that uses ZSTDMT API against libzstd.a on a POSIX system,
    +`-pthread` flag must be provided to the compiler and linker.
    +Note : ZSTDMT prototypes can still be used with a library built without multithread support,
    +but in this case, they will be single threaded only.
     
     #### Modular build
     
    diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h
    index d3873002ebd1..ca42850df324 100644
    --- a/lib/common/bitstream.h
    +++ b/lib/common/bitstream.h
    @@ -2,7 +2,7 @@
        bitstream
        Part of FSE library
        header file (to include)
    -   Copyright (C) 2013-2016, Yann Collet.
    +   Copyright (C) 2013-2017, Yann Collet.
     
        BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
     
    @@ -53,6 +53,16 @@ extern "C" {
     #include "error_private.h"  /* error codes and messages */
     
     
    +/*-*************************************
    +*  Debug
    +***************************************/
    +#if defined(BIT_DEBUG) && (BIT_DEBUG>=1)
    +#  include 
    +#else
    +#  define assert(condition) ((void)0)
    +#endif
    +
    +
     /*=========================================
     *  Target specific
     =========================================*/
    @@ -74,7 +84,7 @@ extern "C" {
     typedef struct
     {
         size_t bitContainer;
    -    int    bitPos;
    +    unsigned bitPos;
         char*  startPtr;
         char*  ptr;
         char*  endPtr;
    @@ -112,6 +122,7 @@ typedef struct
         unsigned bitsConsumed;
         const char* ptr;
         const char* start;
    +    const char* limitPtr;
     } BIT_DStream_t;
     
     typedef enum { BIT_DStream_unfinished = 0,
    @@ -163,7 +174,10 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
     #   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */
         return 31 - __builtin_clz (val);
     #   else   /* Software version */
    -    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
    +    static const unsigned DeBruijnClz[32] = { 0,  9,  1, 10, 13, 21,  2, 29,
    +                                             11, 14, 16, 18, 22, 25,  3, 30,
    +                                              8, 12, 20, 28, 15, 17, 24,  7,
    +                                             19, 27, 23,  6, 26,  5,  4, 31 };
         U32 v = val;
         v |= v >> 1;
         v |= v >> 2;
    @@ -175,31 +189,36 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
     }
     
     /*=====    Local Constants   =====*/
    -static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,  0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF };   /* up to 26 bits */
    +static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F,
    +                                    0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF,
    +                                    0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
    +                                    0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF };   /* up to 26 bits */
     
     
     /*-**************************************************************
     *  bitStream encoding
     ****************************************************************/
     /*! BIT_initCStream() :
    - *  `dstCapacity` must be > sizeof(void*)
    + *  `dstCapacity` must be > sizeof(size_t)
      *  @return : 0 if success,
                   otherwise an error code (can be tested using ERR_isError() ) */
    -MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t dstCapacity)
    +MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
    +                                  void* startPtr, size_t dstCapacity)
     {
         bitC->bitContainer = 0;
         bitC->bitPos = 0;
         bitC->startPtr = (char*)startPtr;
         bitC->ptr = bitC->startPtr;
    -    bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->ptr);
    -    if (dstCapacity <= sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall);
    +    bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
    +    if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
         return 0;
     }
     
     /*! BIT_addBits() :
         can add up to 26 bits into `bitC`.
         Does not check for register overflow ! */
    -MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
    +MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
    +                            size_t value, unsigned nbBits)
     {
         bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
         bitC->bitPos += nbBits;
    @@ -207,34 +226,42 @@ MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
     
     /*! BIT_addBitsFast() :
      *  works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
    -MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
    +MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
    +                                size_t value, unsigned nbBits)
     {
    +    assert((value>>nbBits) == 0);
         bitC->bitContainer |= value << bitC->bitPos;
         bitC->bitPos += nbBits;
     }
     
     /*! BIT_flushBitsFast() :
    + *  assumption : bitContainer has not overflowed
      *  unsafe version; does not check buffer overflow */
     MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
     {
         size_t const nbBytes = bitC->bitPos >> 3;
    +    assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
         MEM_writeLEST(bitC->ptr, bitC->bitContainer);
         bitC->ptr += nbBytes;
    +    assert(bitC->ptr <= bitC->endPtr);
         bitC->bitPos &= 7;
    -    bitC->bitContainer >>= nbBytes*8;   /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
    +    bitC->bitContainer >>= nbBytes*8;
     }
     
     /*! BIT_flushBits() :
    + *  assumption : bitContainer has not overflowed
      *  safe version; check for buffer overflow, and prevents it.
    - *  note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
    + *  note : does not signal buffer overflow.
    + *  overflow will be revealed later on using BIT_closeCStream() */
     MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
     {
         size_t const nbBytes = bitC->bitPos >> 3;
    +    assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
         MEM_writeLEST(bitC->ptr, bitC->bitContainer);
         bitC->ptr += nbBytes;
         if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
         bitC->bitPos &= 7;
    -    bitC->bitContainer >>= nbBytes*8;   /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
    +    bitC->bitContainer >>= nbBytes*8;
     }
     
     /*! BIT_closeCStream() :
    @@ -244,9 +271,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
     {
         BIT_addBitsFast(bitC, 1, 1);   /* endMark */
         BIT_flushBits(bitC);
    -
    -    if (bitC->ptr >= bitC->endPtr) return 0; /* doesn't fit within authorized budget : cancel */
    -
    +    if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
         return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
     }
     
    @@ -264,15 +289,16 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
     {
         if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
     
    +    bitD->start = (const char*)srcBuffer;
    +    bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
    +
         if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */
    -        bitD->start = (const char*)srcBuffer;
             bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
             bitD->bitContainer = MEM_readLEST(bitD->ptr);
             { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
               bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;  /* ensures bitsConsumed is always set */
               if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
         } else {
    -        bitD->start = (const char*)srcBuffer;
             bitD->ptr   = bitD->start;
             bitD->bitContainer = *(const BYTE*)(bitD->start);
             switch(srcSize)
    @@ -330,17 +356,18 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
     #if defined(__BMI__) && defined(__GNUC__)   /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
         return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
     #else
    -    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
    -    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
    +    U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
    +    return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
     #endif
     }
     
     /*! BIT_lookBitsFast() :
    -*   unsafe version; only works only if nbBits >= 1 */
    + *  unsafe version; only works if nbBits >= 1 */
     MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
     {
    -    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
    -    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
    +    U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
    +    assert(nbBits >= 1);
    +    return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
     }
     
     MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
    @@ -365,6 +392,7 @@ MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
     MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
     {
         size_t const value = BIT_lookBitsFast(bitD, nbBits);
    +    assert(nbBits >= 1);
         BIT_skipBits(bitD, nbBits);
         return value;
     }
    @@ -376,10 +404,10 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
                   if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
     MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
     {
    -	if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should not happen => corruption detected */
    -		return BIT_DStream_overflow;
    +    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* overflow detected, like end of stream */
    +        return BIT_DStream_overflow;
     
    -    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
    +    if (bitD->ptr >= bitD->limitPtr) {
             bitD->ptr -= bitD->bitsConsumed >> 3;
             bitD->bitsConsumed &= 7;
             bitD->bitContainer = MEM_readLEST(bitD->ptr);
    @@ -389,6 +417,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
             if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
             return BIT_DStream_completed;
         }
    +    /* start < ptr < limitPtr */
         {   U32 nbBytes = bitD->bitsConsumed >> 3;
             BIT_DStream_status result = BIT_DStream_unfinished;
             if (bitD->ptr - nbBytes < bitD->start) {
    @@ -397,7 +426,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
             }
             bitD->ptr -= nbBytes;
             bitD->bitsConsumed -= nbBytes*8;
    -        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */
    +        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
             return result;
         }
     }
    diff --git a/lib/common/error_private.c b/lib/common/error_private.c
    index a0fa1724aee8..b3287245f1ee 100644
    --- a/lib/common/error_private.c
    +++ b/lib/common/error_private.c
    @@ -29,7 +29,7 @@ const char* ERR_getErrorString(ERR_enum code)
         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(srcSize_wrong): return "Src size is 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";
    @@ -37,6 +37,7 @@ const char* ERR_getErrorString(ERR_enum code)
         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(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples";
         case PREFIX(maxCode):
         default: return notErrorCode;
         }
    diff --git a/lib/common/fse.h b/lib/common/fse.h
    index baac39032675..6d5d41def19b 100644
    --- a/lib/common/fse.h
    +++ b/lib/common/fse.h
    @@ -316,6 +316,10 @@ If there is an error, the function will return an error code, which can be teste
     #define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))
     #define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<2)?(maxTableLog-2):0)) )
    +#define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue)   ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )
     size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
     
     size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);
    @@ -550,9 +554,9 @@ MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U3
     
     MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, U32 symbol)
     {
    -    const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
    +    FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
         const U16* const stateTable = (const U16*)(statePtr->stateTable);
    -    U32 nbBitsOut  = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
    +    U32 const nbBitsOut  = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
         BIT_addBits(bitC, statePtr->value, nbBitsOut);
         statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
     }
    diff --git a/lib/common/huf.h b/lib/common/huf.h
    index e5572760a548..7873ca3d42a5 100644
    --- a/lib/common/huf.h
    +++ b/lib/common/huf.h
    @@ -43,6 +43,21 @@ extern "C" {
     #include     /* size_t */
     
     
    +/* *** library symbols visibility *** */
    +/* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual,
    + *        HUF symbols remain "private" (internal symbols for library only).
    + *        Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */
    +#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
    +#  define HUF_PUBLIC_API __attribute__ ((visibility ("default")))
    +#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1)   /* Visual expected */
    +#  define HUF_PUBLIC_API __declspec(dllexport)
    +#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
    +#  define HUF_PUBLIC_API __declspec(dllimport)  /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */
    +#else
    +#  define HUF_PUBLIC_API
    +#endif
    +
    +
     /* *** simple functions *** */
     /**
     HUF_compress() :
    @@ -55,8 +70,8 @@ HUF_compress() :
                          if return == 1, srcData is a single repeated byte symbol (RLE compression).
                          if HUF_isError(return), compression failed (more details using HUF_getErrorName())
     */
    -size_t HUF_compress(void* dst, size_t dstCapacity,
    -              const void* src, size_t srcSize);
    +HUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity,
    +                             const void* src, size_t srcSize);
     
     /**
     HUF_decompress() :
    @@ -69,32 +84,42 @@ HUF_decompress() :
         @return : size of regenerated data (== originalSize),
                   or an error code, which can be tested using HUF_isError()
     */
    -size_t HUF_decompress(void* dst,  size_t originalSize,
    -                const void* cSrc, size_t cSrcSize);
    +HUF_PUBLIC_API size_t HUF_decompress(void* dst,  size_t originalSize,
    +                               const void* cSrc, size_t cSrcSize);
     
     
     /* ***   Tool functions *** */
    -#define HUF_BLOCKSIZE_MAX (128 * 1024)       /**< maximum input size for a single block compressed with HUF_compress */
    -size_t HUF_compressBound(size_t size);       /**< maximum compressed size (worst case) */
    +#define HUF_BLOCKSIZE_MAX (128 * 1024)                  /**< maximum input size for a single block compressed with HUF_compress */
    +HUF_PUBLIC_API size_t HUF_compressBound(size_t size);   /**< maximum compressed size (worst case) */
     
     /* Error Management */
    -unsigned    HUF_isError(size_t code);        /**< tells if a return value is an error code */
    -const char* HUF_getErrorName(size_t code);   /**< provides error code string (useful for debugging) */
    +HUF_PUBLIC_API unsigned    HUF_isError(size_t code);       /**< tells if a return value is an error code */
    +HUF_PUBLIC_API const char* HUF_getErrorName(size_t code);  /**< provides error code string (useful for debugging) */
     
     
     /* ***   Advanced function   *** */
     
     /** HUF_compress2() :
    - *   Same as HUF_compress(), but offers direct control over `maxSymbolValue` and `tableLog` .
    - *   `tableLog` must be `<= HUF_TABLELOG_MAX` . */
    -size_t HUF_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
    + *  Same as HUF_compress(), but offers direct control over `maxSymbolValue` and `tableLog`.
    + *  `tableLog` must be `<= HUF_TABLELOG_MAX` . */
    +HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
     
     /** HUF_compress4X_wksp() :
    -*   Same as HUF_compress2(), but uses externally allocated `workSpace`, which must be a table of >= 1024 unsigned */
    -size_t HUF_compress4X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);  /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
    + *  Same as HUF_compress2(), but uses externally allocated `workSpace`.
    + *  `workspace` must have minimum alignment of 4, and be at least as large as following macro */
    +#define HUF_WORKSPACE_SIZE (6 << 10)
    +#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32))
    +HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
     
     
     
    +/* ******************************************************************
    + *  WARNING !!
    + *  The following section contains advanced and experimental definitions
    + *  which shall never be used in the context of dll
    + *  because they are not guaranteed to remain stable in the future.
    + *  Only consider them in association with static linking.
    + *******************************************************************/
     #ifdef HUF_STATIC_LINKING_ONLY
     
     /* *** Dependencies *** */
    @@ -117,12 +142,14 @@ size_t HUF_compress4X_wksp (void* dst, size_t dstSize, const void* src, size_t s
     ******************************************/
     /* HUF buffer bounds */
     #define HUF_CTABLEBOUND 129
    -#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */
    +#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true when incompressible is pre-filtered with fast heuristic */
     #define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */
     
     /* static allocation of HUF's Compression Table */
    +#define HUF_CTABLE_SIZE_U32(maxSymbolValue)   ((maxSymbolValue)+1)   /* Use tables of U32, for proper alignment */
    +#define HUF_CTABLE_SIZE(maxSymbolValue)       (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32))
     #define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
    -    U32 name##hb[maxSymbolValue+1]; \
    +    U32 name##hb[HUF_CTABLE_SIZE_U32(maxSymbolValue)]; \
         void* name##hv = &(name##hb); \
         HUF_CElt* name = (HUF_CElt*)(name##hv)   /* no final ; */
     
    @@ -134,10 +161,6 @@ typedef U32 HUF_DTable;
     #define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \
             HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) }
     
    -/* The workspace must have alignment at least 4 and be at least this large */
    -#define HUF_WORKSPACE_SIZE (6 << 10)
    -#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32))
    -
     
     /* ****************************************
     *  Advanced decompression functions
    diff --git a/lib/common/mem.h b/lib/common/mem.h
    index 3cacd216aa02..4773a8b9309e 100644
    --- a/lib/common/mem.h
    +++ b/lib/common/mem.h
    @@ -89,8 +89,7 @@ MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (size
     #ifndef MEM_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */
     #  if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
     #    define MEM_FORCE_MEMORY_ACCESS 2
    -#  elif defined(__INTEL_COMPILER) /*|| defined(_MSC_VER)*/ || \
    -  (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
    +#  elif defined(__INTEL_COMPILER) || defined(__GNUC__)
     #    define MEM_FORCE_MEMORY_ACCESS 1
     #  endif
     #endif
    @@ -122,7 +121,7 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
     /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
     /* currently only defined for gcc and icc */
     #if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32))
    -	__pragma( pack(push, 1) )
    +    __pragma( pack(push, 1) )
         typedef union { U16 u16; U32 u32; U64 u64; size_t st; } unalign;
         __pragma( pack(pop) )
     #else
    diff --git a/lib/common/zstd_errors.h b/lib/common/zstd_errors.h
    index 949dbd0fffac..3d579d969363 100644
    --- a/lib/common/zstd_errors.h
    +++ b/lib/common/zstd_errors.h
    @@ -57,6 +57,7 @@ typedef enum {
       ZSTD_error_maxSymbolValue_tooSmall,
       ZSTD_error_dictionary_corrupted,
       ZSTD_error_dictionary_wrong,
    +  ZSTD_error_dictionaryCreation_failed,
       ZSTD_error_maxCode
     } ZSTD_ErrorCode;
     
    diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h
    index 5c5b28732975..2533333ba83c 100644
    --- a/lib/common/zstd_internal.h
    +++ b/lib/common/zstd_internal.h
    @@ -16,9 +16,9 @@
     #ifdef _MSC_VER    /* Visual Studio */
     #  define FORCE_INLINE static __forceinline
     #  include                     /* For Visual 2005 */
    +#  pragma warning(disable : 4100)        /* disable: C4100: unreferenced formal parameter */
     #  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__
    @@ -58,6 +58,8 @@
     /*-*************************************
     *  shared macros
     ***************************************/
    +#undef MIN
    +#undef MAX
     #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 */
    @@ -104,7 +106,6 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
     #define LONGNBSEQ 0x7F00
     
     #define MINMATCH 3
    -#define EQUAL_READ32 4
     
     #define Litbits  8
     #define MaxLit ((1< FSE_MAX_TABLELOG) return ERROR(GENERIC);   /* Unsupported */
    +    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);   /* Unsupported */
         if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC);   /* Unsupported */
     
         if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog))
    @@ -476,20 +476,20 @@ void FSE_freeCTable (FSE_CTable* ct) { free(ct); }
     /* provides the minimum logSize to safely represent a distribution */
     static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
     {
    -	U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1;
    -	U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;
    -	U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;
    -	return minBits;
    +    U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1;
    +    U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;
    +    U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;
    +    return minBits;
     }
     
     unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus)
     {
    -	U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus;
    +    U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus;
         U32 tableLog = maxTableLog;
    -	U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);
    +    U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);
         if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;
    -	if (maxBitsSrc < tableLog) tableLog = maxBitsSrc;   /* Accuracy can be reduced */
    -	if (minBits > tableLog) tableLog = minBits;   /* Need a minimum to safely represent all symbol values */
    +    if (maxBitsSrc < tableLog) tableLog = maxBitsSrc;   /* Accuracy can be reduced */
    +    if (minBits > tableLog) tableLog = minBits;   /* Need a minimum to safely represent all symbol values */
         if (tableLog < FSE_MIN_TABLELOG) tableLog = FSE_MIN_TABLELOG;
         if (tableLog > FSE_MAX_TABLELOG) tableLog = FSE_MAX_TABLELOG;
         return tableLog;
    @@ -808,7 +808,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src
         if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG;
     
         /* Scan input and build symbol stats */
    -    {   CHECK_V_F(maxCount, FSE_count(count, &maxSymbolValue, src, srcSize) );
    +    {   CHECK_V_F(maxCount, FSE_count_wksp(count, &maxSymbolValue, src, srcSize, (unsigned*)scratchBuffer) );
             if (maxCount == srcSize) return 1;   /* only a single symbol in src : rle */
             if (maxCount == 1) return 0;         /* each symbol present maximum once => not compressible */
             if (maxCount < (srcSize >> 7)) return 0;   /* Heuristic : not compressible enough */
    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
    index 450e5970a4a5..c08b315dab93 100644
    --- a/lib/compress/zstd_compress.c
    +++ b/lib/compress/zstd_compress.c
    @@ -20,6 +20,26 @@
     #include "zstd_internal.h"  /* includes zstd.h */
     
     
    +/*-*************************************
    +*  Debug
    +***************************************/
    +#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
    +#  include 
    +#else
    +#  define assert(condition) ((void)0)
    +#endif
    +
    +#define ZSTD_STATIC_ASSERT(c) { enum { ZSTD_static_assert = 1/(int)(!!(c)) }; }
    +
    +#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
    +#  include 
    +   static unsigned g_debugLevel = ZSTD_DEBUG;
    +#  define DEBUGLOG(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __FILE__ ": "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, " \n"); }
    +#else
    +#  define DEBUGLOG(l, ...)      {}    /* disabled */
    +#endif
    +
    +
     /*-*************************************
     *  Constants
     ***************************************/
    @@ -27,12 +47,22 @@ static const U32 g_searchStrength = 8;   /* control skip over incompressible dat
     #define HASH_READ_SIZE 8
     typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;
     
    +/* entropy tables always have same size */
    +static size_t const hufCTable_size = HUF_CTABLE_SIZE(255);
    +static size_t const litlengthCTable_size = FSE_CTABLE_SIZE(LLFSELog, MaxLL);
    +static size_t const offcodeCTable_size = FSE_CTABLE_SIZE(OffFSELog, MaxOff);
    +static size_t const matchlengthCTable_size = FSE_CTABLE_SIZE(MLFSELog, MaxML);
    +static size_t const entropyScratchSpace_size = HUF_WORKSPACE_SIZE;
    +
     
     /*-*************************************
     *  Helper functions
     ***************************************/
    -#define ZSTD_STATIC_ASSERT(c) { enum { ZSTD_static_assert = 1/(int)(!!(c)) }; }
    -size_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) + 12; }
    +size_t ZSTD_compressBound(size_t srcSize) {
    +    size_t const lowLimit = 256 KB;
    +    size_t const margin = (srcSize < lowLimit) ? (lowLimit-srcSize) >> 12 : 0;  /* from 64 to 0 */
    +    return srcSize + (srcSize >> 8) + margin;
    +}
     
     
     /*-*************************************
    @@ -70,6 +100,7 @@ struct ZSTD_CCtx_s {
         size_t workSpaceSize;
         size_t blockSize;
         U64 frameContentSize;
    +    U64 consumedSrcSize;
         XXH64_state_t xxhState;
         ZSTD_customMem customMem;
     
    @@ -77,13 +108,13 @@ struct ZSTD_CCtx_s {
         U32* hashTable;
         U32* hashTable3;
         U32* chainTable;
    -    HUF_CElt* hufTable;
    -    U32 flagStaticTables;
    -    HUF_repeat flagStaticHufTable;
    -    FSE_CTable offcodeCTable  [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
    -    FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
    -    FSE_CTable litlengthCTable  [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
    -    unsigned tmpCounters[HUF_WORKSPACE_SIZE_U32];
    +    HUF_repeat hufCTable_repeatMode;
    +    HUF_CElt* hufCTable;
    +    U32 fseCTables_ready;
    +    FSE_CTable* offcodeCTable;
    +    FSE_CTable* matchlengthCTable;
    +    FSE_CTable* litlengthCTable;
    +    unsigned* entropyScratchSpace;
     };
     
     ZSTD_CCtx* ZSTD_createCCtx(void)
    @@ -150,9 +181,7 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
         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 searchLengthMax = (cParams.strategy == ZSTD_fast) ? ZSTD_SEARCHLENGTH_MAX : ZSTD_SEARCHLENGTH_MAX-1;
    -      CLAMPCHECK(cParams.searchLength, searchLengthMin, searchLengthMax); }
    +    CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
         CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
         if ((U32)(cParams.strategy) > (U32)ZSTD_btopt2) return ERROR(compressionParameter_unsupported);
         return 0;
    @@ -206,11 +235,14 @@ size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams)
         size_t const hSize = ((size_t)1) << cParams.hashLog;
         U32    const hashLog3 = (cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog);
         size_t const h3Size = ((size_t)1) << hashLog3;
    +    size_t const entropySpace = hufCTable_size + litlengthCTable_size
    +                              + offcodeCTable_size + matchlengthCTable_size
    +                              + entropyScratchSpace_size;
         size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
     
         size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<nextSrc - cctx->base);
         cctx->params = params;
         cctx->frameContentSize = frameContentSize;
    +    cctx->consumedSrcSize = 0;
         cctx->lowLimit = end;
         cctx->dictLimit = end;
         cctx->nextToUpdate = end+1;
    @@ -246,16 +279,16 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 fra
     
     typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset, ZSTDcrp_fullReset } ZSTD_compResetPolicy_e;
     
    -/*! ZSTD_resetCCtx_advanced() :
    +/*! ZSTD_resetCCtx_internal() :
         note : `params` must be validated */
    -static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
    +static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
                                            ZSTD_parameters params, U64 frameContentSize,
                                            ZSTD_compResetPolicy_e const crp)
     {
         if (crp == ZSTDcrp_continue)
             if (ZSTD_equivalentParams(params, zc->params)) {
    -            zc->flagStaticTables = 0;
    -            zc->flagStaticHufTable = HUF_repeat_none;
    +            zc->fseCTables_ready = 0;
    +            zc->hufCTable_repeatMode = HUF_repeat_none;
                 return ZSTD_continueCCtx(zc, params, frameContentSize);
             }
     
    @@ -271,41 +304,67 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
             void* ptr;
     
             /* 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) {
    +                zc->workSpaceSize = 0;
                     ZSTD_free(zc->workSpace, zc->customMem);
                     zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
                     if (zc->workSpace == NULL) return ERROR(memory_allocation);
                     zc->workSpaceSize = neededSpace;
    +                ptr = zc->workSpace;
    +
    +                /* entropy space */
    +                zc->hufCTable = (HUF_CElt*)ptr;
    +                ptr = (char*)zc->hufCTable + hufCTable_size;  /* note : HUF_CElt* is incomplete type, size is estimated via macro */
    +                zc->offcodeCTable = (FSE_CTable*) ptr;
    +                ptr = (char*)ptr + offcodeCTable_size;
    +                zc->matchlengthCTable = (FSE_CTable*) ptr;
    +                ptr = (char*)ptr + matchlengthCTable_size;
    +                zc->litlengthCTable = (FSE_CTable*) ptr;
    +                ptr = (char*)ptr + litlengthCTable_size;
    +                assert(((size_t)ptr & 3) == 0);   /* ensure correct alignment */
    +                zc->entropyScratchSpace = (unsigned*) ptr;
             }   }
     
    -        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;
    -        zc->flagStaticHufTable = HUF_repeat_none;
    -        ptr = ((U32*)ptr) + 256;  /* note : HUF_CElt* is incomplete type, size is simulated using U32 */
    +        /* init params */
    +        zc->params = params;
    +        zc->blockSize = blockSize;
    +        zc->frameContentSize = frameContentSize;
    +        zc->consumedSrcSize = 0;
     
    +        XXH64_reset(&zc->xxhState, 0);
    +        zc->stage = ZSTDcs_init;
    +        zc->dictID = 0;
    +        zc->loadedDictEnd = 0;
    +        zc->fseCTables_ready = 0;
    +        zc->hufCTable_repeatMode = HUF_repeat_none;
             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]; }
    +        zc->hashLog3 = hashLog3;
    +        zc->seqStore.litLengthSum = 0;
     
    +        /* ensure entropy tables are close together at the beginning */
    +        assert((void*)zc->hufCTable == zc->workSpace);
    +        assert((char*)zc->offcodeCTable == (char*)zc->hufCTable + hufCTable_size);
    +        assert((char*)zc->matchlengthCTable == (char*)zc->offcodeCTable + offcodeCTable_size);
    +        assert((char*)zc->litlengthCTable == (char*)zc->matchlengthCTable + matchlengthCTable_size);
    +        assert((char*)zc->entropyScratchSpace == (char*)zc->litlengthCTable + litlengthCTable_size);
    +        ptr = (char*)zc->entropyScratchSpace + entropyScratchSpace_size;
    +
    +        /* opt parser space */
             if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btopt2)) {
    +            assert(((size_t)ptr & 3) == 0);  /* ensure ptr is properly aligned */
                 zc->seqStore.litFreq = (U32*)ptr;
                 zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL+1);
    @@ -315,8 +374,17 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
                 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;
             }
    +
    +        /* table Space */
    +        if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace);   /* reset tables only */
    +        assert(((size_t)ptr & 3) == 0);  /* ensure ptr is properly aligned */
    +        zc->hashTable = (U32*)(ptr);
    +        zc->chainTable = zc->hashTable + hSize;
    +        zc->hashTable3 = zc->chainTable + chainSize;
    +        ptr = zc->hashTable3 + h3Size;
    +
    +        /* sequences storage */
             zc->seqStore.sequencesStart = (seqDef*)ptr;
             ptr = zc->seqStore.sequencesStart + maxNbSeq;
             zc->seqStore.llCode = (BYTE*) ptr;
    @@ -324,10 +392,6 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
             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;
         }
     }
    @@ -341,27 +405,32 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
         for (i=0; irep[i] = 0;
     }
     
    -/*! ZSTD_copyCCtx() :
    -*   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, unsigned long long pledgedSrcSize)
    +
    +/*! ZSTD_copyCCtx_internal() :
    + *  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()).
    + *  pledgedSrcSize=0 means "empty" if fParams.contentSizeFlag=1
    + *  @return : 0, or an error code */
    +size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx,
    +                              ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize)
     {
         if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
     
    -
         memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
         {   ZSTD_parameters params = srcCCtx->params;
    -        params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
    -        ZSTD_resetCCtx_advanced(dstCCtx, params, pledgedSrcSize, ZSTDcrp_noMemset);
    +        params.fParams = fParams;
    +        DEBUGLOG(5, "ZSTD_resetCCtx_internal : dictIDFlag : %u \n", !fParams.noDictIDFlag);
    +        ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize, ZSTDcrp_noMemset);
         }
     
         /* copy tables */
         {   size_t const chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog);
    -        size_t const hSize = ((size_t)1) << srcCCtx->params.cParams.hashLog;
    +        size_t const hSize =  (size_t)1 << srcCCtx->params.cParams.hashLog;
             size_t const h3Size = (size_t)1 << srcCCtx->hashLog3;
             size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
    -        memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace);
    +        assert((U32*)dstCCtx->chainTable == (U32*)dstCCtx->hashTable + hSize);  /* chainTable must follow hashTable */
    +        assert((U32*)dstCCtx->hashTable3 == (U32*)dstCCtx->chainTable + chainSize);
    +        memcpy(dstCCtx->hashTable, srcCCtx->hashTable, tableSpace);   /* presumes all tables follow each other */
         }
     
         /* copy dictionary offsets */
    @@ -376,23 +445,36 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long
         dstCCtx->dictID       = srcCCtx->dictID;
     
         /* copy entropy tables */
    -    dstCCtx->flagStaticTables = srcCCtx->flagStaticTables;
    -    dstCCtx->flagStaticHufTable = srcCCtx->flagStaticHufTable;
    -    if (srcCCtx->flagStaticTables) {
    -        memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, sizeof(dstCCtx->litlengthCTable));
    -        memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, sizeof(dstCCtx->matchlengthCTable));
    -        memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, sizeof(dstCCtx->offcodeCTable));
    +    dstCCtx->fseCTables_ready = srcCCtx->fseCTables_ready;
    +    if (srcCCtx->fseCTables_ready) {
    +        memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, litlengthCTable_size);
    +        memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, matchlengthCTable_size);
    +        memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, offcodeCTable_size);
         }
    -    if (srcCCtx->flagStaticHufTable) {
    -        memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256*4);
    +    dstCCtx->hufCTable_repeatMode = srcCCtx->hufCTable_repeatMode;
    +    if (srcCCtx->hufCTable_repeatMode) {
    +        memcpy(dstCCtx->hufCTable, srcCCtx->hufCTable, hufCTable_size);
         }
     
         return 0;
     }
     
    +/*! ZSTD_copyCCtx() :
    + *  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()).
    + *  pledgedSrcSize==0 means "unknown".
    +*   @return : 0, or an error code */
    +size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)
    +{
    +    ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
    +    fParams.contentSizeFlag = pledgedSrcSize>0;
    +
    +    return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx, fParams, pledgedSrcSize);
    +}
    +
     
     /*! ZSTD_reduceTable() :
    -*   reduce table indexes by `reducerValue` */
    + *  reduce table indexes by `reducerValue` */
     static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reducerValue)
     {
         U32 u;
    @@ -499,26 +581,28 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
     
         /* small ? don't even attempt compression (speed opt) */
     #   define LITERAL_NOENTROPY 63
    -    {   size_t const minLitSize = zc->flagStaticHufTable == HUF_repeat_valid ? 6 : LITERAL_NOENTROPY;
    +    {   size_t const minLitSize = zc->hufCTable_repeatMode == HUF_repeat_valid ? 6 : LITERAL_NOENTROPY;
             if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
         }
     
         if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall);   /* not enough space for compression */
    -    {   HUF_repeat repeat = zc->flagStaticHufTable;
    +    {   HUF_repeat repeat = zc->hufCTable_repeatMode;
             int const preferRepeat = zc->params.cParams.strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
             if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
    -        cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11, zc->tmpCounters, sizeof(zc->tmpCounters), zc->hufTable, &repeat, preferRepeat)
    -                                : HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11, zc->tmpCounters, sizeof(zc->tmpCounters), zc->hufTable, &repeat, preferRepeat);
    +        cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
    +                                      zc->entropyScratchSpace, entropyScratchSpace_size, zc->hufCTable, &repeat, preferRepeat)
    +                                : HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
    +                                      zc->entropyScratchSpace, entropyScratchSpace_size, zc->hufCTable, &repeat, preferRepeat);
             if (repeat != HUF_repeat_none) { hType = set_repeat; }    /* reused the existing table */
    -        else { zc->flagStaticHufTable = HUF_repeat_check; }       /* now have a table to reuse */
    +        else { zc->hufCTable_repeatMode = HUF_repeat_check; }       /* now have a table to reuse */
         }
     
         if ((cLitSize==0) | (cLitSize >= srcSize - minGain)) {
    -        zc->flagStaticHufTable = HUF_repeat_none;
    +        zc->hufCTable_repeatMode = HUF_repeat_none;
             return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
         }
         if (cLitSize==1) {
    -        zc->flagStaticHufTable = HUF_repeat_none;
    +        zc->hufCTable_repeatMode = HUF_repeat_none;
             return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
         }
     
    @@ -637,12 +721,12 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
     
         /* CTable for Literal Lengths */
         {   U32 max = MaxLL;
    -        size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, zc->tmpCounters);
    +        size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, zc->entropyScratchSpace);
             if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
                 *op++ = llCodeTable[0];
                 FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
                 LLtype = set_rle;
    -        } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
    +        } else if ((zc->fseCTables_ready) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
                 LLtype = set_repeat;
             } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LL_defaultNormLog-1)))) {
                 FSE_buildCTable_wksp(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));
    @@ -653,7 +737,7 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
                 if (count[llCodeTable[nbSeq-1]]>1) { count[llCodeTable[nbSeq-1]]--; nbSeq_1--; }
                 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
                 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog);   /* overflow protected */
    -              if (FSE_isError(NCountSize)) return ERROR(GENERIC);
    +              if (FSE_isError(NCountSize)) return NCountSize;
                   op += NCountSize; }
                 FSE_buildCTable_wksp(CTable_LitLength, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));
                 LLtype = set_compressed;
    @@ -661,12 +745,12 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
     
         /* CTable for Offsets */
         {   U32 max = MaxOff;
    -        size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, zc->tmpCounters);
    +        size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, zc->entropyScratchSpace);
             if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
                 *op++ = ofCodeTable[0];
                 FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
                 Offtype = set_rle;
    -        } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
    +        } else if ((zc->fseCTables_ready) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
                 Offtype = set_repeat;
             } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (OF_defaultNormLog-1)))) {
                 FSE_buildCTable_wksp(CTable_OffsetBits, OF_defaultNorm, MaxOff, OF_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));
    @@ -677,7 +761,7 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
                 if (count[ofCodeTable[nbSeq-1]]>1) { count[ofCodeTable[nbSeq-1]]--; nbSeq_1--; }
                 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
                 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog);   /* overflow protected */
    -              if (FSE_isError(NCountSize)) return ERROR(GENERIC);
    +              if (FSE_isError(NCountSize)) return NCountSize;
                   op += NCountSize; }
                 FSE_buildCTable_wksp(CTable_OffsetBits, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));
                 Offtype = set_compressed;
    @@ -685,12 +769,12 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
     
         /* CTable for MatchLengths */
         {   U32 max = MaxML;
    -        size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, zc->tmpCounters);
    +        size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, zc->entropyScratchSpace);
             if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
                 *op++ = *mlCodeTable;
                 FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
                 MLtype = set_rle;
    -        } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
    +        } else if ((zc->fseCTables_ready) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
                 MLtype = set_repeat;
             } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (ML_defaultNormLog-1)))) {
                 FSE_buildCTable_wksp(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));
    @@ -701,14 +785,14 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
                 if (count[mlCodeTable[nbSeq-1]]>1) { count[mlCodeTable[nbSeq-1]]--; nbSeq_1--; }
                 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
                 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog);   /* overflow protected */
    -              if (FSE_isError(NCountSize)) return ERROR(GENERIC);
    +              if (FSE_isError(NCountSize)) return NCountSize;
                   op += NCountSize; }
                 FSE_buildCTable_wksp(CTable_MatchLength, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));
                 MLtype = set_compressed;
         }   }
     
         *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
    -    zc->flagStaticTables = 0;
    +    zc->fseCTables_ready = 0;
     
         /* Encoding Sequences */
         {   BIT_CStream_t blockStream;
    @@ -787,7 +871,7 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
         {   size_t const minGain = ZSTD_minGain(srcSize);
             size_t const maxCSize = srcSize - minGain;
             if ((size_t)(op-ostart) >= maxCSize) {
    -            zc->flagStaticHufTable = HUF_repeat_none;
    +            zc->hufCTable_repeatMode = HUF_repeat_none;
                 return 0;
         }   }
     
    @@ -816,7 +900,7 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const v
             const U32 pos = (U32)((const BYTE*)literals - g_start);
             if (g_start==NULL) g_start = (const BYTE*)literals;
             if ((pos > 1895000) && (pos < 1895300))
    -            fprintf(stderr, "Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
    +            DEBUGLOG(5, "Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
                        pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
         }
     #endif
    @@ -825,14 +909,20 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const v
         seqStorePtr->lit += litLength;
     
         /* literal Length */
    -    if (litLength>0xFFFF) { seqStorePtr->longLengthID = 1; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); }
    +    if (litLength>0xFFFF) {
    +        seqStorePtr->longLengthID = 1;
    +        seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
    +    }
         seqStorePtr->sequences[0].litLength = (U16)litLength;
     
         /* match offset */
         seqStorePtr->sequences[0].offset = offsetCode + 1;
     
         /* match Length */
    -    if (matchCode>0xFFFF) { seqStorePtr->longLengthID = 2; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); }
    +    if (matchCode>0xFFFF) {
    +        seqStorePtr->longLengthID = 2;
    +        seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
    +    }
         seqStorePtr->sequences[0].matchLength = (U16)matchCode;
     
         seqStorePtr->sequences++;
    @@ -853,7 +943,14 @@ static unsigned ZSTD_NbCommonBytes (register size_t val)
     #       elif defined(__GNUC__) && (__GNUC__ >= 3)
                 return (__builtin_ctzll((U64)val) >> 3);
     #       else
    -            static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
    +            static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,
    +                                                     0, 3, 1, 3, 1, 4, 2, 7,
    +                                                     0, 2, 3, 6, 1, 5, 3, 5,
    +                                                     1, 3, 4, 4, 2, 5, 6, 7,
    +                                                     7, 0, 1, 2, 3, 3, 4, 6,
    +                                                     2, 6, 5, 5, 3, 4, 5, 6,
    +                                                     7, 1, 2, 4, 6, 4, 4, 5,
    +                                                     7, 2, 6, 5, 7, 6, 7, 7 };
                 return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
     #       endif
             } else { /* 32 bits */
    @@ -864,7 +961,10 @@ static unsigned ZSTD_NbCommonBytes (register size_t val)
     #       elif defined(__GNUC__) && (__GNUC__ >= 3)
                 return (__builtin_ctz((U32)val) >> 3);
     #       else
    -            static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
    +            static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
    +                                                     3, 2, 2, 1, 3, 2, 0, 1,
    +                                                     3, 3, 1, 2, 2, 2, 2, 0,
    +                                                     3, 1, 2, 0, 1, 0, 1, 1 };
                 return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
     #       endif
             }
    @@ -936,7 +1036,7 @@ static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE
     ***************************************/
     static const U32 prime3bytes = 506832829U;
     static U32    ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes)  >> (32-h) ; }
    -MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); }   /* only in zstd_opt.h */
    +MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
     
     static const U32 prime4bytes = 2654435761U;
     static U32    ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
    @@ -1085,7 +1185,7 @@ static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
         const U32 mls = ctx->params.cParams.searchLength;
         switch(mls)
         {
    -    default:
    +    default: /* includes case 3 */
         case 4 :
             ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
         case 5 :
    @@ -1135,7 +1235,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
             if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
                && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
                 const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
    -            mLength = ZSTD_count_2segments(ip+1+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repMatchEnd, lowPrefixPtr) + EQUAL_READ32;
    +            mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
                 ip++;
                 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
             } else {
    @@ -1147,7 +1247,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
                 {   const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
                     const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
                     U32 offset;
    -                mLength = ZSTD_count_2segments(ip+EQUAL_READ32, match+EQUAL_READ32, iend, matchEnd, lowPrefixPtr) + EQUAL_READ32;
    +                mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
                     while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; }   /* catch up */
                     offset = current - matchIndex;
                     offset_2 = offset_1;
    @@ -1171,7 +1271,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
                     if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex))  /* intentional overflow */
                        && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
                         const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
    -                    size_t repLength2 = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch2+EQUAL_READ32, iend, repEnd2, lowPrefixPtr) + EQUAL_READ32;
    +                    size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
                         U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset;   /* swap offset_2 <=> offset_1 */
                         ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
                         hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
    @@ -1199,7 +1299,7 @@ static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
         U32 const mls = ctx->params.cParams.searchLength;
         switch(mls)
         {
    -    default:
    +    default: /* includes case 3 */
         case 4 :
             ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return;
         case 5 :
    @@ -1274,7 +1374,9 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
             const BYTE* match = base + matchIndexS;
             hashLong[h2] = hashSmall[h] = current;   /* update hash tables */
     
    -        if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) { /* note : by construction, offset_1 <= current */
    +        assert(offset_1 <= current);   /* supposed guaranteed by construction */
    +        if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
    +            /* favor repcode */
                 mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
                 ip++;
                 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
    @@ -1285,15 +1387,15 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
                     offset = (U32)(ip-matchLong);
                     while (((ip>anchor) & (matchLong>lowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
                 } else if ( (matchIndexS > lowestIndex) && (MEM_read32(match) == MEM_read32(ip)) ) {
    -                size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
    -                U32 const matchIndex3 = hashLong[h3];
    -                const BYTE* match3 = base + matchIndex3;
    -                hashLong[h3] = current + 1;
    -                if ( (matchIndex3 > lowestIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {
    -                    mLength = ZSTD_count(ip+9, match3+8, iend) + 8;
    +                size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
    +                U32 const matchIndexL3 = hashLong[hl3];
    +                const BYTE* matchL3 = base + matchIndexL3;
    +                hashLong[hl3] = current + 1;
    +                if ( (matchIndexL3 > lowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1)) ) {
    +                    mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;
                         ip++;
    -                    offset = (U32)(ip-match3);
    -                    while (((ip>anchor) & (match3>lowest)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */
    +                    offset = (U32)(ip-matchL3);
    +                    while (((ip>anchor) & (matchL3>lowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
                     } else {
                         mLength = ZSTD_count(ip+4, match+4, iend) + 4;
                         offset = (U32)(ip-match);
    @@ -1353,7 +1455,7 @@ static void ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_
         const U32 mls = ctx->params.cParams.searchLength;
         switch(mls)
         {
    -    default:
    +    default: /* includes case 3 */
         case 4 :
             ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4); return;
         case 5 :
    @@ -1462,8 +1564,8 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
     
             if (ip <= ilimit) {
                 /* Fill Table */
    -			hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2;
    -			hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = current+2;
    +            hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2;
    +            hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = current+2;
                 hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
                 hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
                 /* check immediate repcode */
    @@ -1474,7 +1576,7 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
                     if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex))  /* intentional overflow */
                        && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
                         const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
    -                    size_t const repLength2 = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch2+EQUAL_READ32, iend, repEnd2, lowPrefixPtr) + EQUAL_READ32;
    +                    size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
                         U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset;   /* swap offset_2 <=> offset_1 */
                         ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
                         hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
    @@ -1503,7 +1605,7 @@ static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
         U32 const mls = ctx->params.cParams.searchLength;
         switch(mls)
         {
    -    default:
    +    default: /* includes case 3 */
         case 4 :
             ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4); return;
         case 5 :
    @@ -1588,7 +1690,7 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
                 match = dictBase + matchIndex;
                 matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
                 if (matchIndex+matchLength >= dictLimit)
    -				match = base + matchIndex;   /* to prepare for next usage of match[matchLength] */
    +                match = base + matchIndex;   /* to prepare for next usage of match[matchLength] */
             }
     
             if (matchLength > bestLength) {
    @@ -1667,7 +1769,7 @@ static size_t ZSTD_insertBtAndFindBestMatch (
                 match = dictBase + matchIndex;
                 matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
                 if (matchIndex+matchLength >= dictLimit)
    -				match = base + matchIndex;   /* to prepare for next usage of match[matchLength] */
    +                match = base + matchIndex;   /* to prepare for next usage of match[matchLength] */
             }
     
             if (matchLength > bestLength) {
    @@ -1733,9 +1835,10 @@ static size_t ZSTD_BtFindBestMatch_selectMLS (
     {
         switch(matchLengthSearch)
         {
    -    default :
    +    default : /* includes case 3 */
         case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
         case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
    +    case 7 :
         case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
         }
     }
    @@ -1772,9 +1875,10 @@ static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
     {
         switch(matchLengthSearch)
         {
    -    default :
    +    default : /* includes case 3 */
         case 4 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
         case 5 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
    +    case 7 :
         case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
         }
     }
    @@ -1831,7 +1935,7 @@ size_t ZSTD_HcFindBestMatch_generic (
         const U32 current = (U32)(ip-base);
         const U32 minChain = current > chainSize ? current - chainSize : 0;
         int nbAttempts=maxNbAttempts;
    -    size_t ml=EQUAL_READ32-1;
    +    size_t ml=4-1;
     
         /* HC4 match finder */
         U32 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
    @@ -1846,11 +1950,15 @@ size_t ZSTD_HcFindBestMatch_generic (
             } else {
                 match = dictBase + matchIndex;
                 if (MEM_read32(match) == MEM_read32(ip))   /* assumption : matchIndex <= dictLimit-4 (by table construction) */
    -                currentMl = ZSTD_count_2segments(ip+EQUAL_READ32, match+EQUAL_READ32, iLimit, dictEnd, prefixStart) + EQUAL_READ32;
    +                currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;
             }
     
             /* save best solution */
    -        if (currentMl > ml) { ml = currentMl; *offsetPtr = current - matchIndex + ZSTD_REP_MOVE; if (ip+currentMl == iLimit) break; /* best possible, and avoid read overflow*/ }
    +        if (currentMl > ml) {
    +            ml = currentMl;
    +            *offsetPtr = current - matchIndex + ZSTD_REP_MOVE;
    +            if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
    +        }
     
             if (matchIndex <= minChain) break;
             matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
    @@ -1868,9 +1976,10 @@ FORCE_INLINE size_t ZSTD_HcFindBestMatch_selectMLS (
     {
         switch(matchLengthSearch)
         {
    -    default :
    +    default : /* includes case 3 */
         case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
         case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
    +    case 7 :
         case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
         }
     }
    @@ -1884,9 +1993,10 @@ FORCE_INLINE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
     {
         switch(matchLengthSearch)
         {
    -    default :
    +    default : /* includes case 3 */
         case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
         case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
    +    case 7 :
         case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
         }
     }
    @@ -1934,7 +2044,7 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
             /* check repCode */
             if ((offset_1>0) & (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1))) {
                 /* repcode : we take it */
    -            matchLength = ZSTD_count(ip+1+EQUAL_READ32, ip+1+EQUAL_READ32-offset_1, iend) + EQUAL_READ32;
    +            matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
                 if (depth==0) goto _storeSequence;
             }
     
    @@ -1945,7 +2055,7 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
                     matchLength = ml2, start = ip, offset=offsetFound;
             }
     
    -        if (matchLength < EQUAL_READ32) {
    +        if (matchLength < 4) {
                 ip += ((ip-anchor) >> g_searchStrength) + 1;   /* jump faster over incompressible sections */
                 continue;
             }
    @@ -1955,17 +2065,17 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
             while (ip0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
    -                size_t const mlRep = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-offset_1, iend) + EQUAL_READ32;
    +                size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
                     int const gain2 = (int)(mlRep * 3);
                     int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
    -                if ((mlRep >= EQUAL_READ32) && (gain2 > gain1))
    +                if ((mlRep >= 4) && (gain2 > gain1))
                         matchLength = mlRep, offset = 0, start = ip;
                 }
                 {   size_t offset2=99999999;
                     size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
                     int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1));   /* raw approx */
                     int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
    -                if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
    +                if ((ml2 >= 4) && (gain2 > gain1)) {
                         matchLength = ml2, offset = offset2, start = ip;
                         continue;   /* search a better one */
                 }   }
    @@ -1974,17 +2084,17 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
                 if ((depth==2) && (ip0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
    -                    size_t const ml2 = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-offset_1, iend) + EQUAL_READ32;
    +                    size_t const ml2 = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
                         int const gain2 = (int)(ml2 * 4);
                         int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
    -                    if ((ml2 >= EQUAL_READ32) && (gain2 > gain1))
    +                    if ((ml2 >= 4) && (gain2 > gain1))
                             matchLength = ml2, offset = 0, start = ip;
                     }
                     {   size_t offset2=99999999;
                         size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
                         int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1));   /* raw approx */
                         int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
    -                    if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
    +                    if ((ml2 >= 4) && (gain2 > gain1)) {
                             matchLength = ml2, offset = offset2, start = ip;
                             continue;
                 }   }   }
    @@ -1993,7 +2103,9 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
     
             /* catch up */
             if (offset) {
    -            while ((start>anchor) && (start>base+offset-ZSTD_REP_MOVE) && (start[-1] == start[-1-offset+ZSTD_REP_MOVE]))   /* only search for offset within prefix */
    +            while ( (start > anchor)
    +                 && (start > base+offset-ZSTD_REP_MOVE)
    +                 && (start[-1] == start[-1-offset+ZSTD_REP_MOVE]) )  /* only search for offset within prefix */
                     { start--; matchLength++; }
                 offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
             }
    @@ -2010,7 +2122,7 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
                  && ((offset_2>0)
                  & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
                 /* store sequence */
    -            matchLength = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-offset_2, iend) + EQUAL_READ32;
    +            matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
                 offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
                 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
                 ip += matchLength;
    @@ -2099,7 +2211,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
                 if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
                     /* repcode detected we should take it */
                     const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
    -                matchLength = ZSTD_count_2segments(ip+1+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
    +                matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4;
                     if (depth==0) goto _storeSequence;
             }   }
     
    @@ -2110,7 +2222,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
                     matchLength = ml2, start = ip, offset=offsetFound;
             }
     
    -         if (matchLength < EQUAL_READ32) {
    +         if (matchLength < 4) {
                 ip += ((ip-anchor) >> g_searchStrength) + 1;   /* jump faster over incompressible sections */
                 continue;
             }
    @@ -2129,10 +2241,10 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
                     if (MEM_read32(ip) == MEM_read32(repMatch)) {
                         /* repcode detected */
                         const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
    -                    size_t const repLength = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
    +                    size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
                         int const gain2 = (int)(repLength * 3);
                         int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
    -                    if ((repLength >= EQUAL_READ32) && (gain2 > gain1))
    +                    if ((repLength >= 4) && (gain2 > gain1))
                             matchLength = repLength, offset = 0, start = ip;
                 }   }
     
    @@ -2141,7 +2253,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
                     size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
                     int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1));   /* raw approx */
                     int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
    -                if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
    +                if ((ml2 >= 4) && (gain2 > gain1)) {
                         matchLength = ml2, offset = offset2, start = ip;
                         continue;   /* search a better one */
                 }   }
    @@ -2159,10 +2271,10 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
                         if (MEM_read32(ip) == MEM_read32(repMatch)) {
                             /* repcode detected */
                             const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
    -                        size_t repLength = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
    -                        int gain2 = (int)(repLength * 4);
    -                        int gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
    -                        if ((repLength >= EQUAL_READ32) && (gain2 > gain1))
    +                        size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
    +                        int const gain2 = (int)(repLength * 4);
    +                        int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
    +                        if ((repLength >= 4) && (gain2 > gain1))
                                 matchLength = repLength, offset = 0, start = ip;
                     }   }
     
    @@ -2171,7 +2283,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
                         size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
                         int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1));   /* raw approx */
                         int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
    -                    if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
    +                    if ((ml2 >= 4) && (gain2 > gain1)) {
                             matchLength = ml2, offset = offset2, start = ip;
                             continue;
                 }   }   }
    @@ -2203,7 +2315,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
                 if (MEM_read32(ip) == MEM_read32(repMatch)) {
                     /* repcode detected we should take it */
                     const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
    -                matchLength = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
    +                matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
                     offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset;   /* swap offset history */
                     ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
                     ip += matchLength;
    @@ -2294,8 +2406,12 @@ typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t sr
     static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
     {
         static const ZSTD_blockCompressor blockCompressor[2][8] = {
    -        { ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2, ZSTD_compressBlock_btopt, ZSTD_compressBlock_btopt2 },
    -        { ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict, ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict, ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btopt2_extDict }
    +        { ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy,
    +          ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2,
    +          ZSTD_compressBlock_btopt, ZSTD_compressBlock_btopt2 },
    +        { ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict,
    +          ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict,
    +          ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btopt2_extDict }
         };
     
         return blockCompressor[extDict][(U32)strat];
    @@ -2311,7 +2427,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCa
         if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) return 0;   /* don't even attempt compression below a certain srcSize */
         ZSTD_resetSeqStore(&(zc->seqStore));
         if (current > zc->nextToUpdate + 384)
    -        zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384));   /* update tree not updated after finding very long rep matches */
    +        zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384));   /* limited update after finding a very long match */
         blockCompressor(zc, src, srcSize);
         return ZSTD_compressSequences(zc, dst, dstCapacity, srcSize);
     }
    @@ -2343,7 +2459,8 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
             U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
             size_t cSize;
     
    -        if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE) return ERROR(dstSize_tooSmall);   /* not enough space to store compressed block */
    +        if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE)
    +            return ERROR(dstSize_tooSmall);   /* not enough space to store compressed block */
             if (remaining < blockSize) blockSize = remaining;
     
             /* preemptive overflow correction */
    @@ -2398,7 +2515,8 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
     static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
                                         ZSTD_parameters params, U64 pledgedSrcSize, U32 dictID)
     {   BYTE* const op = (BYTE*)dst;
    -    U32   const dictIDSizeCode = (dictID>0) + (dictID>=256) + (dictID>=65536);   /* 0-3 */
    +    U32   const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536);   /* 0-3 */
    +    U32   const dictIDSizeCode = params.fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength;   /* 0-3 */
         U32   const checksumFlag = params.fParams.checksumFlag>0;
         U32   const windowSize = 1U << params.cParams.windowLog;
         U32   const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
    @@ -2410,6 +2528,9 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
         size_t pos;
     
         if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
    +    DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u \n", !params.fParams.noDictIDFlag);
    +    DEBUGLOG(5, "ZSTD_writeFrameHeader : dictID : %u \n", dictID);
    +    DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDSizeCode : %u \n", dictIDSizeCode);
     
         MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
         op[4] = frameHeaderDecriptionByte; pos=5;
    @@ -2478,6 +2599,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
                                  ZSTD_compress_generic (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
                                  ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
             if (ZSTD_isError(cSize)) return cSize;
    +        cctx->consumedSrcSize += srcSize;
             return cSize + fhSize;
         } else
             return fhSize;
    @@ -2488,7 +2610,7 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
                                   void* dst, size_t dstCapacity,
                             const void* src, size_t srcSize)
     {
    -    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1, 0);
    +    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */);
     }
     
     
    @@ -2501,10 +2623,12 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
     {
         size_t const blockSizeMax = ZSTD_getBlockSizeMax(cctx);
         if (srcSize > blockSizeMax) return ERROR(srcSize_wrong);
    -    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0, 0);
    +    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
     }
     
    -
    +/*! ZSTD_loadDictionaryContent() :
    + *  @return : 0, or an error code
    + */
     static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t srcSize)
     {
         const BYTE* const ip = (const BYTE*) src;
    @@ -2534,13 +2658,15 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
         case ZSTD_greedy:
         case ZSTD_lazy:
         case ZSTD_lazy2:
    -        ZSTD_insertAndFindFirstIndex (zc, iend-HASH_READ_SIZE, zc->params.cParams.searchLength);
    +        if (srcSize >= HASH_READ_SIZE)
    +            ZSTD_insertAndFindFirstIndex(zc, iend-HASH_READ_SIZE, zc->params.cParams.searchLength);
             break;
     
         case ZSTD_btlazy2:
         case ZSTD_btopt:
         case ZSTD_btopt2:
    -        ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
    +        if (srcSize >= HASH_READ_SIZE)
    +            ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
             break;
     
         default:
    @@ -2567,18 +2693,15 @@ static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSym
     
     
     /* Dictionary format :
    -    Magic == ZSTD_DICT_MAGIC (4 bytes)
    -    HUF_writeCTable(256)
    -    FSE_writeNCount(off)
    -    FSE_writeNCount(ml)
    -    FSE_writeNCount(ll)
    -    RepOffsets
    -    Dictionary content
    -*/
    -/*! ZSTD_loadDictEntropyStats() :
    -    @return : size read from dictionary
    -    note : magic number supposed already checked */
    -static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
    + * See :
    + * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
    + */
    +/*! ZSTD_loadZstdDictionary() :
    + * @return : 0, or an error code
    + *  assumptions : magic number supposed already checked
    + *                dictSize supposed > 8
    + */
    +static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
     {
         const BYTE* dictPtr = (const BYTE*)dict;
         const BYTE* const dictEnd = dictPtr + dictSize;
    @@ -2586,7 +2709,11 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
         unsigned offcodeMaxValue = MaxOff;
         BYTE scratchBuffer[1<hufTable, 255, dict, dictSize);
    +    dictPtr += 4;   /* skip magic number */
    +    cctx->dictID = cctx->params.fParams.noDictIDFlag ? 0 :  MEM_readLE32(dictPtr);
    +    dictPtr += 4;
    +
    +    {   size_t const hufHeaderSize = HUF_readCTable(cctx->hufCTable, 255, dictPtr, dictEnd-dictPtr);
             if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
             dictPtr += hufHeaderSize;
         }
    @@ -2596,7 +2723,8 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
             if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
             if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
             /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
    -        CHECK_E (FSE_buildCTable_wksp(cctx->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, scratchBuffer, sizeof(scratchBuffer)), dictionary_corrupted);
    +        CHECK_E( FSE_buildCTable_wksp(cctx->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, scratchBuffer, sizeof(scratchBuffer)),
    +                 dictionary_corrupted);
             dictPtr += offcodeHeaderSize;
         }
     
    @@ -2606,8 +2734,9 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
             if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
             if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
             /* Every match length code must have non-zero probability */
    -        CHECK_F (ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
    -        CHECK_E (FSE_buildCTable_wksp(cctx->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, scratchBuffer, sizeof(scratchBuffer)), dictionary_corrupted);
    +        CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
    +        CHECK_E( FSE_buildCTable_wksp(cctx->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, scratchBuffer, sizeof(scratchBuffer)),
    +                 dictionary_corrupted);
             dictPtr += matchlengthHeaderSize;
         }
     
    @@ -2617,49 +2746,51 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
             if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
             if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
             /* Every literal length code must have non-zero probability */
    -        CHECK_F (ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
    -        CHECK_E(FSE_buildCTable_wksp(cctx->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, scratchBuffer, sizeof(scratchBuffer)), dictionary_corrupted);
    +        CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
    +        CHECK_E( FSE_buildCTable_wksp(cctx->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, scratchBuffer, sizeof(scratchBuffer)),
    +                 dictionary_corrupted);
             dictPtr += litlengthHeaderSize;
         }
     
         if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
    -    cctx->rep[0] = MEM_readLE32(dictPtr+0); if (cctx->rep[0] == 0 || cctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
    -    cctx->rep[1] = MEM_readLE32(dictPtr+4); if (cctx->rep[1] == 0 || cctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
    -    cctx->rep[2] = MEM_readLE32(dictPtr+8); if (cctx->rep[2] == 0 || cctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
    +    cctx->rep[0] = MEM_readLE32(dictPtr+0);
    +    cctx->rep[1] = MEM_readLE32(dictPtr+4);
    +    cctx->rep[2] = MEM_readLE32(dictPtr+8);
         dictPtr += 12;
     
    -    {   U32 offcodeMax = MaxOff;
    -        if ((size_t)(dictEnd - dictPtr) <= ((U32)-1) - 128 KB) {
    -            U32 const maxOffset = (U32)(dictEnd - dictPtr) + 128 KB; /* The maximum offset that must be supported */
    -            /* Calculate minimum offset code required to represent maxOffset */
    -            offcodeMax = ZSTD_highbit32(maxOffset);
    +    {   size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
    +        U32 offcodeMax = MaxOff;
    +        if (dictContentSize <= ((U32)-1) - 128 KB) {
    +            U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */
    +            offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
             }
    -        /* Every possible supported offset <= dictContentSize + 128 KB must be representable */
    +        /* All offset values <= dictContentSize + 128 KB must be representable */
             CHECK_F (ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
    -    }
    +        /* All repCodes must be <= dictContentSize and != 0*/
    +        {   U32 u;
    +            for (u=0; u<3; u++) {
    +                if (cctx->rep[u] == 0) return ERROR(dictionary_corrupted);
    +                if (cctx->rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
    +        }   }
     
    -    cctx->flagStaticTables = 1;
    -    cctx->flagStaticHufTable = HUF_repeat_valid;
    -    return dictPtr - (const BYTE*)dict;
    +        cctx->fseCTables_ready = 1;
    +        cctx->hufCTable_repeatMode = HUF_repeat_valid;
    +        return ZSTD_loadDictionaryContent(cctx, dictPtr, dictContentSize);
    +    }
     }
     
     /** ZSTD_compress_insertDictionary() :
     *   @return : 0, or an error code */
    -static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
    +static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
     {
         if ((dict==NULL) || (dictSize<=8)) return 0;
     
         /* dict as pure content */
    -    if ((MEM_readLE32(dict) != ZSTD_DICT_MAGIC) || (zc->forceRawDict))
    -        return ZSTD_loadDictionaryContent(zc, dict, dictSize);
    -    zc->dictID = zc->params.fParams.noDictIDFlag ? 0 :  MEM_readLE32((const char*)dict+4);
    +    if ((MEM_readLE32(dict) != ZSTD_DICT_MAGIC) || (cctx->forceRawDict))
    +        return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
     
    -    /* known magic number : dict is parsed for entropy stats and content */
    -    {   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);
    -    }
    +    /* dict as zstd dictionary */
    +    return ZSTD_loadZstdDictionary(cctx, dict, dictSize);
     }
     
     /*! ZSTD_compressBegin_internal() :
    @@ -2669,7 +2800,8 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
                                        ZSTD_parameters params, U64 pledgedSrcSize)
     {
         ZSTD_compResetPolicy_e const crp = dictSize ? ZSTDcrp_fullReset : ZSTDcrp_continue;
    -    CHECK_F(ZSTD_resetCCtx_advanced(cctx, params, pledgedSrcSize, crp));
    +    assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
    +    CHECK_F(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, crp));
         return ZSTD_compress_insertDictionary(cctx, dict, dictSize);
     }
     
    @@ -2745,10 +2877,13 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
                        const void* src, size_t srcSize)
     {
         size_t endResult;
    -    size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1, 1);
    +    size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 1 /* last chunk */);
         if (ZSTD_isError(cSize)) return cSize;
         endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
         if (ZSTD_isError(endResult)) return endResult;
    +    if (cctx->params.fParams.contentSizeFlag) {  /* control src size */
    +        if (cctx->frameContentSize != cctx->consumedSrcSize) return ERROR(srcSize_wrong);
    +    }
         return cSize + endResult;
     }
     
    @@ -2773,7 +2908,8 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
         return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
     }
     
    -size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict, size_t dictSize, int compressionLevel)
    +size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
    +                               const void* dict, size_t dictSize, int compressionLevel)
     {
         ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, dict ? dictSize : 0);
         params.fParams.contentSizeFlag = 1;
    @@ -2812,8 +2948,16 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
         return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
     }
     
    +static ZSTD_parameters ZSTD_makeParams(ZSTD_compressionParameters cParams, ZSTD_frameParameters fParams)
    +{
    +    ZSTD_parameters params;
    +    params.cParams = cParams;
    +    params.fParams = fParams;
    +    return params;
    +}
    +
     ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, unsigned byReference,
    -                                      ZSTD_parameters params, ZSTD_customMem customMem)
    +                                      ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
     {
         if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
         if (!customMem.customAlloc || !customMem.customFree) return NULL;
    @@ -2838,7 +2982,9 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, u
                 cdict->dictContent = internalBuffer;
             }
     
    -        {   size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0);
    +        {   ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksumFlag */, 0 /* noDictIDFlag */ };   /* dummy */
    +            ZSTD_parameters const params = ZSTD_makeParams(cParams, fParams);
    +            size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0);
                 if (ZSTD_isError(errorCode)) {
                     ZSTD_free(cdict->dictBuffer, customMem);
                     ZSTD_free(cdict, customMem);
    @@ -2855,17 +3001,15 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, u
     ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
     {
         ZSTD_customMem const allocator = { NULL, NULL, NULL };
    -    ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
    -    params.fParams.contentSizeFlag = 1;
    -    return ZSTD_createCDict_advanced(dict, dictSize, 0, params, allocator);
    +    ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
    +    return ZSTD_createCDict_advanced(dict, dictSize, 0, cParams, allocator);
     }
     
     ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
     {
         ZSTD_customMem const allocator = { NULL, NULL, NULL };
    -    ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
    -    params.fParams.contentSizeFlag = 1;
    -    return ZSTD_createCDict_advanced(dict, dictSize, 1, params, allocator);
    +    ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
    +    return ZSTD_createCDict_advanced(dict, dictSize, 1, cParams, allocator);
     }
     
     size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
    @@ -2883,34 +3027,55 @@ static ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
         return ZSTD_getParamsFromCCtx(cdict->refContext);
     }
     
    -size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize)
    +/* ZSTD_compressBegin_usingCDict_advanced() :
    + * cdict must be != NULL */
    +size_t ZSTD_compressBegin_usingCDict_advanced(
    +    ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
    +    ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
     {
    -    if (cdict->dictContentSize) CHECK_F(ZSTD_copyCCtx(cctx, cdict->refContext, pledgedSrcSize))
    +    if (cdict==NULL) return ERROR(GENERIC);  /* does not support NULL cdict */
    +    DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced : dictIDFlag == %u \n", !fParams.noDictIDFlag);
    +    if (cdict->dictContentSize)
    +        CHECK_F( ZSTD_copyCCtx_internal(cctx, cdict->refContext, fParams, pledgedSrcSize) )
         else {
             ZSTD_parameters params = cdict->refContext->params;
    -        params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
    -        CHECK_F(ZSTD_compressBegin_advanced(cctx, NULL, 0, params, pledgedSrcSize));
    +        params.fParams = fParams;
    +        CHECK_F(ZSTD_compressBegin_internal(cctx, NULL, 0, params, pledgedSrcSize));
         }
         return 0;
     }
     
    +/* ZSTD_compressBegin_usingCDict() :
    + * pledgedSrcSize=0 means "unknown"
    + * if pledgedSrcSize>0, it will enable contentSizeFlag */
    +size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
    +{
    +    ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
    +    DEBUGLOG(5, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u \n", !fParams.noDictIDFlag);
    +    return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, 0);
    +}
    +
    +size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
    +                                void* dst, size_t dstCapacity,
    +                                const void* src, size_t srcSize,
    +                                const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
    +{
    +    CHECK_F (ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize));   /* will check if cdict != NULL */
    +    return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
    +}
    +
     /*! 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 */
    + *  Compression using a digested Dictionary.
    + *  Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times.
    + *  Note that compression parameters are decided at CDict creation time
    + *  while frame parameters are hardcoded */
     size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
                                     void* dst, size_t dstCapacity,
                                     const void* src, size_t srcSize,
                                     const ZSTD_CDict* cdict)
     {
    -    CHECK_F(ZSTD_compressBegin_usingCDict(cctx, cdict, srcSize));
    -
    -    if (cdict->refContext->params.fParams.contentSizeFlag==1) {
    -        cctx->params.fParams.contentSizeFlag = 1;
    -        cctx->frameContentSize = srcSize;
    -    }
    -
    -    return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
    +    ZSTD_frameParameters const fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
    +    return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);
     }
     
     
    @@ -2939,7 +3104,6 @@ struct ZSTD_CStream_s {
         U32    checksum;
         U32    frameEnded;
         U64    pledgedSrcSize;
    -    U64    inputProcessed;
         ZSTD_parameters params;
         ZSTD_customMem customMem;
     };   /* typedef'd to ZSTD_CStream within "zstd.h" */
    @@ -2970,9 +3134,13 @@ 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->cctx);
    +        zcs->cctx = NULL;
             ZSTD_freeCDict(zcs->cdictLocal);
    +        zcs->cdictLocal = NULL;
             ZSTD_free(zcs->inBuff, cMem);
    +        zcs->inBuff = NULL;
             ZSTD_free(zcs->outBuff, cMem);
    +        zcs->outBuff = NULL;
             ZSTD_free(zcs, cMem);
             return 0;
         }
    @@ -2982,14 +3150,20 @@ size_t ZSTD_freeCStream(ZSTD_CStream* zcs)
     /*======   Initialization   ======*/
     
     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_CStreamOutSize(void)
    +{
    +    return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
    +}
     
     static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
     {
         if (zcs->inBuffSize==0) return ERROR(stage_wrong);   /* zcs has not been init at least once => can't reset */
     
    -    if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict(zcs->cctx, zcs->cdict, pledgedSrcSize))
    -    else CHECK_F(ZSTD_compressBegin_advanced(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize));
    +    DEBUGLOG(5, "ZSTD_resetCStream_internal : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag);
    +
    +    if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict_advanced(zcs->cctx, zcs->cdict, zcs->params.fParams, pledgedSrcSize))
    +    else CHECK_F(ZSTD_compressBegin_internal(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize));
     
         zcs->inToCompress = 0;
         zcs->inBuffPos = 0;
    @@ -2998,7 +3172,6 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs, unsigned long long p
         zcs->stage = zcss_load;
         zcs->frameEnded = 0;
         zcs->pledgedSrcSize = pledgedSrcSize;
    -    zcs->inputProcessed = 0;
         return 0;   /* ready to go */
     }
     
    @@ -3006,70 +3179,109 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
     {
     
         zcs->params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
    -
    +    DEBUGLOG(5, "ZSTD_resetCStream : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag);
         return ZSTD_resetCStream_internal(zcs, pledgedSrcSize);
     }
     
    +/* ZSTD_initCStream_internal() :
    + * params are supposed validated at this stage
    + * and zcs->cdict is supposed to be correct */
    +static size_t ZSTD_initCStream_stage2(ZSTD_CStream* zcs,
    +                                const ZSTD_parameters params,
    +                                unsigned long long pledgedSrcSize)
    +{
    +    assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
    +
    +    /* allocate buffers */
    +    {   size_t const neededInBuffSize = (size_t)1 << params.cParams.windowLog;
    +        if (zcs->inBuffSize < neededInBuffSize) {
    +            zcs->inBuffSize = 0;
    +            ZSTD_free(zcs->inBuff, zcs->customMem);
    +            zcs->inBuff = (char*) ZSTD_malloc(neededInBuffSize, zcs->customMem);
    +            if (zcs->inBuff == NULL) return ERROR(memory_allocation);
    +            zcs->inBuffSize = neededInBuffSize;
    +        }
    +        zcs->blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, neededInBuffSize);
    +    }
    +    if (zcs->outBuffSize < ZSTD_compressBound(zcs->blockSize)+1) {
    +        size_t const outBuffSize = ZSTD_compressBound(zcs->blockSize)+1;
    +        zcs->outBuffSize = 0;
    +        ZSTD_free(zcs->outBuff, zcs->customMem);
    +        zcs->outBuff = (char*) ZSTD_malloc(outBuffSize, zcs->customMem);
    +        if (zcs->outBuff == NULL) return ERROR(memory_allocation);
    +        zcs->outBuffSize = outBuffSize;
    +    }
    +
    +    zcs->checksum = params.fParams.checksumFlag > 0;
    +    zcs->params = params;
    +
    +    DEBUGLOG(5, "ZSTD_initCStream_stage2 : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
    +    return ZSTD_resetCStream_internal(zcs, pledgedSrcSize);
    +}
    +
    +/* ZSTD_initCStream_usingCDict_advanced() :
    + * same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
    +size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize, ZSTD_frameParameters fParams)
    +{
    +    if (!cdict) return ERROR(GENERIC);   /* cannot handle NULL cdict (does not know what to do) */
    +    {   ZSTD_parameters params = ZSTD_getParamsFromCDict(cdict);
    +        params.fParams = fParams;
    +        zcs->cdict = cdict;
    +        return ZSTD_initCStream_stage2(zcs, params, pledgedSrcSize);
    +    }
    +}
    +
    +/* note : cdict must outlive compression session */
    +size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
    +{
    +    ZSTD_frameParameters const fParams = { 0 /* content */, 0 /* checksum */, 0 /* noDictID */ };
    +    return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, 0, fParams);
    +}
    +
    +static size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
    +                                const void* dict, size_t dictSize,
    +                                ZSTD_parameters params, unsigned long long pledgedSrcSize)
    +{
    +    assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
    +    zcs->cdict = NULL;
    +
    +    if (dict && dictSize >= 8) {
    +        ZSTD_freeCDict(zcs->cdictLocal);
    +        zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0 /* copy */, params.cParams, zcs->customMem);
    +        if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
    +        zcs->cdict = zcs->cdictLocal;
    +    }
    +
    +    DEBUGLOG(5, "ZSTD_initCStream_internal : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
    +    return ZSTD_initCStream_stage2(zcs, params, pledgedSrcSize);
    +}
    +
     size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
                                      const void* dict, size_t dictSize,
                                      ZSTD_parameters params, unsigned long long pledgedSrcSize)
     {
    -    /* allocate buffers */
    -    {   size_t const neededInBuffSize = (size_t)1 << params.cParams.windowLog;
    -        if (zcs->inBuffSize < neededInBuffSize) {
    -            zcs->inBuffSize = neededInBuffSize;
    -            ZSTD_free(zcs->inBuff, zcs->customMem);
    -            zcs->inBuff = (char*) ZSTD_malloc(neededInBuffSize, zcs->customMem);
    -            if (zcs->inBuff == NULL) return ERROR(memory_allocation);
    -        }
    -        zcs->blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, neededInBuffSize);
    -    }
    -    if (zcs->outBuffSize < ZSTD_compressBound(zcs->blockSize)+1) {
    -        zcs->outBuffSize = ZSTD_compressBound(zcs->blockSize)+1;
    -        ZSTD_free(zcs->outBuff, zcs->customMem);
    -        zcs->outBuff = (char*) ZSTD_malloc(zcs->outBuffSize, zcs->customMem);
    -        if (zcs->outBuff == NULL) return ERROR(memory_allocation);
    -    }
    -
    -    if (dict && dictSize >= 8) {
    -        ZSTD_freeCDict(zcs->cdictLocal);
    -        zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0, params, zcs->customMem);
    -        if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
    -        zcs->cdict = zcs->cdictLocal;
    -    } else zcs->cdict = NULL;
    -
    -    zcs->checksum = params.fParams.checksumFlag > 0;
    -    zcs->params = params;
    -
    -    return ZSTD_resetCStream_internal(zcs, pledgedSrcSize);
    -}
    -
    -/* note : cdict must outlive compression session */
    -size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
    -{
    -    ZSTD_parameters const params = ZSTD_getParamsFromCDict(cdict);
    -    size_t const initError =  ZSTD_initCStream_advanced(zcs, NULL, 0, params, 0);
    -    zcs->cdict = cdict;
    -    zcs->cctx->dictID = params.fParams.noDictIDFlag ? 0 : cdict->refContext->dictID;
    -    return initError;
    +    CHECK_F( ZSTD_checkCParams(params.cParams) );
    +    DEBUGLOG(5, "ZSTD_initCStream_advanced : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
    +    return ZSTD_initCStream_internal(zcs, dict, dictSize, params, pledgedSrcSize);
     }
     
     size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
     {
         ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
    -    return ZSTD_initCStream_advanced(zcs, dict, dictSize, params, 0);
    +    return ZSTD_initCStream_internal(zcs, dict, dictSize, params, 0);
     }
     
     size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
     {
         ZSTD_parameters params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
    -    if (pledgedSrcSize) params.fParams.contentSizeFlag = 1;
    -    return ZSTD_initCStream_advanced(zcs, NULL, 0, params, pledgedSrcSize);
    +    params.fParams.contentSizeFlag = (pledgedSrcSize>0);
    +    return ZSTD_initCStream_internal(zcs, NULL, 0, params, pledgedSrcSize);
     }
     
     size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
     {
    -    return ZSTD_initCStream_usingDict(zcs, NULL, 0, compressionLevel);
    +    ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
    +    return ZSTD_initCStream_internal(zcs, NULL, 0, params, 0);
     }
     
     size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
    @@ -3163,7 +3375,6 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
     
         *srcSizePtr = ip - istart;
         *dstCapacityPtr = op - ostart;
    -    zcs->inputProcessed += *srcSizePtr;
         if (zcs->frameEnded) return 0;
         {   size_t hintInSize = zcs->inBuffTarget - zcs->inBuffPos;
             if (hintInSize==0) hintInSize = zcs->blockSize;
    @@ -3208,14 +3419,12 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
         BYTE* const oend = (BYTE*)(output->dst) + output->size;
         BYTE* op = ostart;
     
    -    if ((zcs->pledgedSrcSize) && (zcs->inputProcessed != zcs->pledgedSrcSize))
    -        return ERROR(srcSize_wrong);   /* pledgedSrcSize not respected */
    -
         if (zcs->stage != zcss_final) {
             /* flush whatever remains */
             size_t srcSize = 0;
             size_t sizeWritten = output->size - output->pos;
    -        size_t const notEnded = ZSTD_compressStream_generic(zcs, ostart, &sizeWritten, &srcSize, &srcSize, zsf_end);  /* use a valid src address instead of NULL */
    +        size_t const notEnded = ZSTD_compressStream_generic(zcs, ostart, &sizeWritten,
    +                                     &srcSize /* use a valid src address instead of NULL */, &srcSize, zsf_end);
             size_t const remainingToFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
             op += sizeWritten;
             if (remainingToFlush) {
    @@ -3225,7 +3434,9 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
             /* create epilogue */
             zcs->stage = zcss_final;
             zcs->outBuffContentSize = !notEnded ? 0 :
    -            ZSTD_compressEnd(zcs->cctx, zcs->outBuff, zcs->outBuffSize, NULL, 0);  /* write epilogue, including final empty block, into outBuff */
    +            /* write epilogue, including final empty block, into outBuff */
    +            ZSTD_compressEnd(zcs->cctx, zcs->outBuff, zcs->outBuffSize, NULL, 0);
    +        if (ZSTD_isError(zcs->outBuffContentSize)) return zcs->outBuffContentSize;
         }
     
         /* flush epilogue */
    @@ -3268,7 +3479,7 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
         { 22, 21, 21,  5,  5, 16, ZSTD_btlazy2 },  /* level 15 */
         { 23, 22, 22,  5,  5, 16, ZSTD_btlazy2 },  /* level 16 */
         { 23, 21, 22,  4,  5, 24, ZSTD_btopt   },  /* level 17 */
    -    { 23, 23, 22,  6,  5, 32, ZSTD_btopt   },  /* level 18 */
    +    { 23, 22, 22,  5,  4, 32, ZSTD_btopt   },  /* level 18 */
         { 23, 23, 22,  6,  3, 48, ZSTD_btopt   },  /* level 19 */
         { 25, 25, 23,  7,  3, 64, ZSTD_btopt2  },  /* level 20 */
         { 26, 26, 23,  7,  3,256, ZSTD_btopt2  },  /* level 21 */
    diff --git a/lib/compress/zstd_opt.h b/lib/compress/zstd_opt.h
    index ac418b61c834..54376119121d 100644
    --- a/lib/compress/zstd_opt.h
    +++ b/lib/compress/zstd_opt.h
    @@ -175,10 +175,10 @@ MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const B
         }
     
         /* match offset */
    -	{   BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
    -		seqStorePtr->offCodeSum++;
    -		seqStorePtr->offCodeFreq[offCode]++;
    -	}
    +    {   BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
    +        seqStorePtr->offCodeSum++;
    +        seqStorePtr->offCodeFreq[offCode]++;
    +    }
     
         /* match Length */
         {   const BYTE ML_deltaCode = 36;
    @@ -360,6 +360,7 @@ static U32 ZSTD_BtGetAllMatches_selectMLS (
         default :
         case 4 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
         case 5 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
    +    case 7 :
         case 6 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
         }
     }
    @@ -387,6 +388,7 @@ static U32 ZSTD_BtGetAllMatches_selectMLS_extDict (
         default :
         case 4 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
         case 5 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
    +    case 7 :
         case 6 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
         }
     }
    diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c
    index 45514a81a3af..fc7f52a2902d 100644
    --- a/lib/compress/zstdmt_compress.c
    +++ b/lib/compress/zstdmt_compress.c
    @@ -33,7 +33,7 @@
     #  include 
     #  include 
     #  include 
    -   static unsigned g_debugLevel = 3;
    +   static unsigned g_debugLevel = 5;
     #  define DEBUGLOGRAW(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __VA_ARGS__); }
     #  define DEBUGLOG(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __FILE__ ": "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, " \n"); }
     
    @@ -44,26 +44,26 @@
         DEBUGLOGRAW(l, " \n");       \
     }
     
    -static unsigned long long GetCurrentClockTimeMicroseconds()
    +static unsigned long long GetCurrentClockTimeMicroseconds(void)
     {
        static clock_t _ticksPerSecond = 0;
        if (_ticksPerSecond <= 0) _ticksPerSecond = sysconf(_SC_CLK_TCK);
     
    -   struct tms junk; clock_t newTicks = (clock_t) times(&junk);
    -   return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond);
    +   { struct tms junk; clock_t newTicks = (clock_t) times(&junk);
    +     return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond); }
     }
     
     #define MUTEX_WAIT_TIME_DLEVEL 5
     #define PTHREAD_MUTEX_LOCK(mutex) \
     if (g_debugLevel>=MUTEX_WAIT_TIME_DLEVEL) { \
    -   unsigned long long beforeTime = GetCurrentClockTimeMicroseconds(); \
    -   pthread_mutex_lock(mutex); \
    -   unsigned long long afterTime = GetCurrentClockTimeMicroseconds(); \
    -   unsigned long long elapsedTime = (afterTime-beforeTime); \
    -   if (elapsedTime > 1000) {  /* or whatever threshold you like; I'm using 1 millisecond here */ \
    -      DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
    +    unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \
    +    pthread_mutex_lock(mutex); \
    +    {   unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \
    +        unsigned long long const elapsedTime = (afterTime-beforeTime); \
    +        if (elapsedTime > 1000) {  /* or whatever threshold you like; I'm using 1 millisecond here */ \
    +            DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
                    elapsedTime, #mutex); \
    -  } \
    +    }   } \
     } else pthread_mutex_lock(mutex);
     
     #else
    @@ -228,17 +228,19 @@ void ZSTDMT_compressChunk(void* jobDescription)
         ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
         const void* const src = (const char*)job->srcStart + job->dictSize;
         buffer_t const dstBuff = job->dstBuff;
    -    DEBUGLOG(3, "job (first:%u) (last:%u) : dictSize %u, srcSize %u", job->firstChunk, job->lastChunk, (U32)job->dictSize, (U32)job->srcSize);
    +    DEBUGLOG(3, "job (first:%u) (last:%u) : dictSize %u, srcSize %u",
    +                 job->firstChunk, job->lastChunk, (U32)job->dictSize, (U32)job->srcSize);
         if (job->cdict) {  /* should only happen for first segment */
    -        size_t const initError = ZSTD_compressBegin_usingCDict(job->cctx, job->cdict, job->fullFrameSize);
    +        size_t const initError = ZSTD_compressBegin_usingCDict_advanced(job->cctx, job->cdict, job->params.fParams, job->fullFrameSize);
             if (job->cdict) DEBUGLOG(3, "using CDict ");
             if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
         } else {  /* srcStart points at reloaded section */
    -        size_t const dictModeError = ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceRawDict, 1);  /* Force loading dictionary in "content-only" mode (no header analysis) */
    -        size_t const initError = ZSTD_compressBegin_advanced(job->cctx, job->srcStart, job->dictSize, job->params, 0);
    -        if (ZSTD_isError(initError) || ZSTD_isError(dictModeError)) { job->cSize = initError; goto _endJob; }
    -        ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceWindow, 1);
    -    }
    +        if (!job->firstChunk) job->params.fParams.contentSizeFlag = 0;  /* ensure no srcSize control */
    +        {   size_t const dictModeError = ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceRawDict, 1);  /* Force loading dictionary in "content-only" mode (no header analysis) */
    +            size_t const initError = ZSTD_compressBegin_advanced(job->cctx, job->srcStart, job->dictSize, job->params, job->fullFrameSize);
    +            if (ZSTD_isError(initError) || ZSTD_isError(dictModeError)) { job->cSize = initError; goto _endJob; }
    +            ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceWindow, 1);
    +    }   }
         if (!job->firstChunk) {  /* flush and overwrite frame header when it's not first segment */
             size_t const hSize = ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, src, 0);
             if (ZSTD_isError(hSize)) { job->cSize = hSize; goto _endJob; }
    @@ -250,7 +252,9 @@ void ZSTDMT_compressChunk(void* jobDescription)
         job->cSize = (job->lastChunk) ?
                      ZSTD_compressEnd     (job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize) :
                      ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize);
    -    DEBUGLOG(3, "compressed %u bytes into %u bytes   (first:%u) (last:%u)", (unsigned)job->srcSize, (unsigned)job->cSize, job->firstChunk, job->lastChunk);
    +    DEBUGLOG(3, "compressed %u bytes into %u bytes   (first:%u) (last:%u)",
    +                (unsigned)job->srcSize, (unsigned)job->cSize, job->firstChunk, job->lastChunk);
    +    DEBUGLOG(5, "dstBuff.size : %u ; => %s", (U32)dstBuff.size, ZSTD_getErrorName(job->cSize));
     
     _endJob:
         PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
    @@ -388,14 +392,17 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
                                int compressionLevel)
     {
         ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, 0);
    +    U32 const overlapLog = (compressionLevel >= ZSTD_maxCLevel()) ? 0 : 3;
    +    size_t const overlapSize = (size_t)1 << (params.cParams.windowLog - overlapLog);
         size_t const chunkTargetSize = (size_t)1 << (params.cParams.windowLog + 2);
    -    unsigned const nbChunksMax = (unsigned)(srcSize / chunkTargetSize) + (srcSize < chunkTargetSize) /* min 1 */;
    +    unsigned const nbChunksMax = (unsigned)(srcSize / chunkTargetSize) + 1;
         unsigned nbChunks = MIN(nbChunksMax, mtctx->nbThreads);
         size_t const proposedChunkSize = (srcSize + (nbChunks-1)) / nbChunks;
         size_t const avgChunkSize = ((proposedChunkSize & 0x1FFFF) < 0xFFFF) ? proposedChunkSize + 0xFFFF : proposedChunkSize;   /* avoid too small last block */
         size_t remainingSrcSize = srcSize;
         const char* const srcStart = (const char*)src;
    -    size_t frameStartPos = 0;
    +    unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbChunks : (unsigned)(dstCapacity / ZSTD_compressBound(avgChunkSize));  /* presumes avgChunkSize >= 256 KB, which should be the case */
    +    size_t frameStartPos = 0, dstBufferPos = 0;
     
         DEBUGLOG(3, "windowLog : %2u => chunkTargetSize : %u bytes  ", params.cParams.windowLog, (U32)chunkTargetSize);
         DEBUGLOG(2, "nbChunks  : %2u   (chunkSize : %u bytes)   ", nbChunks, (U32)avgChunkSize);
    @@ -409,10 +416,11 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
         {   unsigned u;
             for (u=0; ubuffPool, dstBufferCapacity) : dstAsBuffer;
    +            size_t const dstBufferCapacity = ZSTD_compressBound(chunkSize);
    +            buffer_t const dstAsBuffer = { (char*)dst + dstBufferPos, dstBufferCapacity };
    +            buffer_t const dstBuffer = u < compressWithinDst ? dstAsBuffer : ZSTDMT_getBuffer(mtctx->buffPool, dstBufferCapacity);
                 ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(mtctx->cctxPool);
    +            size_t dictSize = u ? overlapSize : 0;
     
                 if ((cctx==NULL) || (dstBuffer.start==NULL)) {
                     mtctx->jobs[u].cSize = ERROR(memory_allocation);   /* job result */
    @@ -421,7 +429,8 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
                     break;   /* let's wait for previous jobs to complete, but don't start new ones */
                 }
     
    -            mtctx->jobs[u].srcStart = srcStart + frameStartPos;
    +            mtctx->jobs[u].srcStart = srcStart + frameStartPos - dictSize;
    +            mtctx->jobs[u].dictSize = dictSize;
                 mtctx->jobs[u].srcSize = chunkSize;
                 mtctx->jobs[u].fullFrameSize = srcSize;
                 mtctx->jobs[u].params = params;
    @@ -438,6 +447,7 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
                 POOL_add(mtctx->factory, ZSTDMT_compressChunk, &mtctx->jobs[u]);
     
                 frameStartPos += chunkSize;
    +            dstBufferPos += dstBufferCapacity;
                 remainingSrcSize -= chunkSize;
         }   }
         /* note : since nbChunks <= nbThreads, all jobs should be running immediately in parallel */
    @@ -461,8 +471,10 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
                     if (ZSTD_isError(cSize)) error = cSize;
                     if ((!error) && (dstPos + cSize > dstCapacity)) error = ERROR(dstSize_tooSmall);
                     if (chunkID) {   /* note : chunk 0 is already written directly into dst */
    -                    if (!error) memcpy((char*)dst + dstPos, mtctx->jobs[chunkID].dstBuff.start, cSize);
    -                    ZSTDMT_releaseBuffer(mtctx->buffPool, mtctx->jobs[chunkID].dstBuff);
    +                    if (!error)
    +                        memmove((char*)dst + dstPos, mtctx->jobs[chunkID].dstBuff.start, cSize);  /* may overlap if chunk decompressed within dst */
    +                    if (chunkID >= compressWithinDst)   /* otherwise, it decompresses within dst */
    +                        ZSTDMT_releaseBuffer(mtctx->buffPool, mtctx->jobs[chunkID].dstBuff);
                         mtctx->jobs[chunkID].dstBuff = g_nullBuffer;
                     }
                     dstPos += cSize ;
    @@ -509,7 +521,7 @@ static size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
         if (updateDict) {
             ZSTD_freeCDict(zcs->cdict); zcs->cdict = NULL;
             if (dict && dictSize) {
    -            zcs->cdict = ZSTD_createCDict_advanced(dict, dictSize, 0, params, cmem);
    +            zcs->cdict = ZSTD_createCDict_advanced(dict, dictSize, 0, params.cParams, cmem);
                 if (zcs->cdict == NULL) return ERROR(memory_allocation);
         }   }
         zcs->frameContentSize = pledgedSrcSize;
    diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c
    index 2aaa4a3df3c5..910f9ab783c3 100644
    --- a/lib/decompress/zstd_decompress.c
    +++ b/lib/decompress/zstd_decompress.c
    @@ -177,30 +177,6 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
         memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize);  /* no need to copy workspace */
     }
     
    -#if 0
    -/* deprecated */
    -static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
    -{
    -    ZSTD_decompressBegin(dstDCtx);  /* init */
    -    if (srcDCtx) {   /* support refDCtx on NULL */
    -        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->entropy.LLTable;
    -        dstDCtx->MLTptr = srcDCtx->entropy.MLTable;
    -        dstDCtx->OFTptr = srcDCtx->entropy.OFTable;
    -        dstDCtx->HUFptr = srcDCtx->entropy.hufTable;
    -        dstDCtx->entropy.rep[0] = srcDCtx->entropy.rep[0];
    -        dstDCtx->entropy.rep[1] = srcDCtx->entropy.rep[1];
    -        dstDCtx->entropy.rep[2] = srcDCtx->entropy.rep[2];
    -    }
    -}
    -#endif
    -
     static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict);
     
     
    @@ -431,7 +407,8 @@ typedef struct
     
     /*! ZSTD_getcBlockSize() :
     *   Provides the size of compressed block from block header `src` */
    -size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
    +size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
    +                          blockProperties_t* bpPtr)
     {
         if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
         {   U32 const cBlockHeader = MEM_readLE24(src);
    @@ -446,7 +423,8 @@ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bp
     }
     
     
    -static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
    +static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
    +                          const void* src, size_t srcSize)
     {
         if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
         memcpy(dst, src, srcSize);
    @@ -454,7 +432,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src,
     }
     
     
    -static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize, size_t regenSize)
    +static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
    +                         const void* src, size_t srcSize,
    +                               size_t regenSize)
     {
         if (srcSize != 1) return ERROR(srcSize_wrong);
         if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall);
    @@ -595,176 +575,70 @@ typedef union {
         U32 alignedBy4;
     } FSE_decode_t4;
     
    +/* Default FSE distribution table for Literal Lengths */
     static const FSE_decode_t4 LL_defaultDTable[(1< (size_t)(oLitEnd - base)) {
    -        /* offset beyond prefix */
    +        /* offset beyond prefix -> go into extDict */
             if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
             match = dictEnd + (match - base);
             if (match + sequence.matchLength <= dictEnd) {
    @@ -1156,21 +1033,26 @@ FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int con
         U32 const totalBits = llBits+mlBits+ofBits;
     
         static const U32 LL_base[MaxLL+1] = {
    -                             0,  1,  2,  3,  4,  5,  6,  7,  8,  9,   10,    11,    12,    13,    14,     15,
    -                            16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
    +                             0,  1,    2,     3,     4,     5,     6,      7,
    +                             8,  9,   10,    11,    12,    13,    14,     15,
    +                            16, 18,   20,    22,    24,    28,    32,     40,
    +                            48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
                                 0x2000, 0x4000, 0x8000, 0x10000 };
     
         static const U32 ML_base[MaxML+1] = {
    -                             3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,   14,    15,    16,    17,    18,
    -                            19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,   30,    31,    32,    33,    34,
    -                            35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
    +                             3,  4,  5,    6,     7,     8,     9,    10,
    +                            11, 12, 13,   14,    15,    16,    17,    18,
    +                            19, 20, 21,   22,    23,    24,    25,    26,
    +                            27, 28, 29,   30,    31,    32,    33,    34,
    +                            35, 37, 39,   41,    43,    47,    51,    59,
    +                            67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
                                 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
     
         static const U32 OF_base[MaxOff+1] = {
    -                             0,        1,       1,       5,     0xD,     0x1D,     0x3D,     0x7D,
    -                             0xFD,   0x1FD,   0x3FD,   0x7FD,   0xFFD,   0x1FFD,   0x3FFD,   0x7FFD,
    -                             0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
    -                             0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
    +                     0,        1,       1,       5,     0xD,     0x1D,     0x3D,     0x7D,
    +                     0xFD,   0x1FD,   0x3FD,   0x7FD,   0xFFD,   0x1FFD,   0x3FFD,   0x7FFD,
    +                     0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
    +                     0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
     
         /* sequence */
         {   size_t offset;
    @@ -1476,7 +1358,7 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
         if (ZSTD_isLegacy(src, srcSize)) return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
     #endif
         if (srcSize >= ZSTD_skippableHeaderSize &&
    -            (MEM_readLE32(src) & 0xFFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
    +            (MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
             return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + 4);
         } else {
             const BYTE* ip = (const BYTE*)src;
    @@ -2115,15 +1997,18 @@ unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
     }
     
     /*! ZSTD_getDictID_fromFrame() :
    - *  Provides the dictID required to decompressed the frame stored within `src`.
    + *  Provides the dictID required to decompresse frame stored within `src`.
      *  If @return == 0, the dictID could not be decoded.
      *  This could for one of the following reasons :
    - *  - The frame does not require a dictionary to be decoded (most common case).
    - *  - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
    + *  - The frame does not require a dictionary (most common case).
    + *  - The frame was built with dictID intentionally removed.
    + *    Needed dictionary is a hidden information.
      *    Note : this use case also happens when using a non-conformant dictionary.
    - *  - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
    + *  - `srcSize` is too small, and as a result, frame header could not be decoded.
    + *    Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
      *  - This is not a Zstandard frame.
    - *  When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
    + *  When identifying the exact failure cause, it's possible to use
    + *  ZSTD_getFrameParams(), which will provide a more precise error code. */
     unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
     {
         ZSTD_frameParams zfp = { 0 , 0 , 0 , 0 };
    @@ -2209,9 +2094,13 @@ 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->dctx);
    +        zds->dctx = NULL;
             ZSTD_freeDDict(zds->ddictLocal);
    +        zds->ddictLocal = NULL;
             ZSTD_free(zds->inBuff, cMem);
    +        zds->inBuff = NULL;
             ZSTD_free(zds->outBuff, cMem);
    +        zds->outBuff = NULL;
     #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
             if (zds->legacyContext)
                 ZSTD_freeLegacyStreamContext(zds->legacyContext, zds->previousLegacyVersion);
    @@ -2247,7 +2136,9 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
         return ZSTD_initDStream_usingDict(zds, NULL, 0);
     }
     
    -size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)  /**< note : ddict will just be referenced, and must outlive decompression session */
    +/* ZSTD_initDStream_usingDDict() :
    + * ddict will just be referenced, and must outlive decompression session */
    +size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)
     {
         size_t const initResult = ZSTD_initDStream(zds);
         zds->ddict = ddict;
    @@ -2277,8 +2168,11 @@ size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
     
     size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds)
     {
    -    if (zds==NULL) return 0;   /* support sizeof on NULL */
    -    return sizeof(*zds) + ZSTD_sizeof_DCtx(zds->dctx) + ZSTD_sizeof_DDict(zds->ddictLocal) + zds->inBuffSize + zds->outBuffSize;
    +    if (zds==NULL) return 0;   /* support sizeof NULL */
    +    return sizeof(*zds)
    +           + ZSTD_sizeof_DCtx(zds->dctx)
    +           + ZSTD_sizeof_DDict(zds->ddictLocal)
    +           + zds->inBuffSize + zds->outBuffSize;
     }
     
     
    @@ -2376,15 +2270,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
                     zds->blockSize = blockSize;
                     if (zds->inBuffSize < blockSize) {
                         ZSTD_free(zds->inBuff, zds->customMem);
    -                    zds->inBuffSize = blockSize;
    +                    zds->inBuffSize = 0;
                         zds->inBuff = (char*)ZSTD_malloc(blockSize, zds->customMem);
                         if (zds->inBuff == NULL) return ERROR(memory_allocation);
    +                    zds->inBuffSize = blockSize;
                     }
                     if (zds->outBuffSize < neededOutSize) {
                         ZSTD_free(zds->outBuff, zds->customMem);
    -                    zds->outBuffSize = neededOutSize;
    +                    zds->outBuffSize = 0;
                         zds->outBuff = (char*)ZSTD_malloc(neededOutSize, zds->customMem);
                         if (zds->outBuff == NULL) return ERROR(memory_allocation);
    +                    zds->outBuffSize = neededOutSize;
                 }   }
                 zds->stage = zdss_read;
                 /* pass-through */
    diff --git a/lib/dictBuilder/cover.c b/lib/dictBuilder/cover.c
    index 3a7b9f39f9fd..1863c8f34542 100644
    --- a/lib/dictBuilder/cover.c
    +++ b/lib/dictBuilder/cover.c
    @@ -59,8 +59,6 @@ static int g_displayLevel = 2;
         if ((clock() - g_time > refreshRate) || (displayLevel >= 4)) {             \
           g_time = clock();                                                        \
           DISPLAY(__VA_ARGS__);                                                    \
    -      if (displayLevel >= 4)                                                   \
    -        fflush(stdout);                                                        \
         }                                                                          \
       }
     #define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__)
    @@ -236,10 +234,22 @@ static size_t COVER_sum(const size_t *samplesSizes, unsigned nbSamples) {
      * Returns 1 if the dmer at lp is greater than the dmer at rp.
      */
     static int COVER_cmp(COVER_ctx_t *ctx, const void *lp, const void *rp) {
    -  const U32 lhs = *(const U32 *)lp;
    -  const U32 rhs = *(const U32 *)rp;
    +  U32 const lhs = *(U32 const *)lp;
    +  U32 const rhs = *(U32 const *)rp;
       return memcmp(ctx->samples + lhs, ctx->samples + rhs, ctx->d);
     }
    +/**
    + * Faster version for d <= 8.
    + */
    +static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) {
    +  U64 const mask = (ctx->d == 8) ? (U64)-1 : (((U64)1 << (8 * ctx->d)) - 1);
    +  U64 const lhs = MEM_readLE64(ctx->samples + *(U32 const *)lp) & mask;
    +  U64 const rhs = MEM_readLE64(ctx->samples + *(U32 const *)rp) & mask;
    +  if (lhs < rhs) {
    +    return -1;
    +  }
    +  return (lhs > rhs);
    +}
     
     /**
      * Same as COVER_cmp() except ties are broken by pointer value
    @@ -253,6 +263,16 @@ static int COVER_strict_cmp(const void *lp, const void *rp) {
       }
       return result;
     }
    +/**
    + * Faster version for d <= 8.
    + */
    +static int COVER_strict_cmp8(const void *lp, const void *rp) {
    +  int result = COVER_cmp8(g_ctx, lp, rp);
    +  if (result == 0) {
    +    result = lp < rp ? -1 : 1;
    +  }
    +  return result;
    +}
     
     /**
      * Returns the first pointer in [first, last) whose element does not compare
    @@ -508,7 +528,7 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
       const BYTE *const samples = (const BYTE *)samplesBuffer;
       const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples);
       /* Checks */
    -  if (totalSamplesSize < d ||
    +  if (totalSamplesSize < MAX(d, sizeof(U64)) ||
           totalSamplesSize >= (size_t)COVER_MAX_SAMPLES_SIZE) {
         DISPLAYLEVEL(1, "Total samples size is too large, maximum size is %u MB\n",
                      (COVER_MAX_SAMPLES_SIZE >> 20));
    @@ -522,7 +542,7 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
       ctx->samplesSizes = samplesSizes;
       ctx->nbSamples = nbSamples;
       /* Partial suffix array */
    -  ctx->suffixSize = totalSamplesSize - d + 1;
    +  ctx->suffixSize = totalSamplesSize - MAX(d, sizeof(U64)) + 1;
       ctx->suffix = (U32 *)malloc(ctx->suffixSize * sizeof(U32));
       /* Maps index to the dmerID */
       ctx->dmerAt = (U32 *)malloc(ctx->suffixSize * sizeof(U32));
    @@ -556,7 +576,8 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
         }
         /* qsort doesn't take an opaque pointer, so pass as a global */
         g_ctx = ctx;
    -    qsort(ctx->suffix, ctx->suffixSize, sizeof(U32), &COVER_strict_cmp);
    +    qsort(ctx->suffix, ctx->suffixSize, sizeof(U32),
    +          (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp));
       }
       DISPLAYLEVEL(2, "Computing frequencies\n");
       /* For each dmer group (group of positions with the same first d bytes):
    @@ -566,8 +587,8 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
        * 2. We calculate how many samples the dmer occurs in and save it in
        *    freqs[dmerId].
        */
    -  COVER_groupBy(ctx->suffix, ctx->suffixSize, sizeof(U32), ctx, &COVER_cmp,
    -                &COVER_group);
    +  COVER_groupBy(ctx->suffix, ctx->suffixSize, sizeof(U32), ctx,
    +                (ctx->d <= 8 ? &COVER_cmp8 : &COVER_cmp), &COVER_group);
       ctx->freqs = ctx->suffix;
       ctx->suffix = NULL;
       return 1;
    @@ -918,10 +939,10 @@ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer,
       /* constants */
       const unsigned nbThreads = parameters->nbThreads;
       const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d;
    -  const unsigned kMaxD = parameters->d == 0 ? 16 : parameters->d;
    -  const unsigned kMinK = parameters->k == 0 ? kMaxD : parameters->k;
    -  const unsigned kMaxK = parameters->k == 0 ? 2048 : parameters->k;
    -  const unsigned kSteps = parameters->steps == 0 ? 32 : parameters->steps;
    +  const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d;
    +  const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k;
    +  const unsigned kMaxK = parameters->k == 0 ? 2000 : parameters->k;
    +  const unsigned kSteps = parameters->steps == 0 ? 40 : parameters->steps;
       const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1);
       const unsigned kIterations =
           (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize);
    diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c
    index 0757dbbbb643..179e02effa4d 100644
    --- a/lib/dictBuilder/zdict.c
    +++ b/lib/dictBuilder/zdict.c
    @@ -11,8 +11,9 @@
     /*-**************************************
     *  Tuning parameters
     ****************************************/
    +#define MINRATIO 4   /* minimum nb of apparition to be selected in dictionary */
     #define ZDICT_MAX_SAMPLES_SIZE (2000U << 20)
    -#define ZDICT_MIN_SAMPLES_SIZE 512
    +#define ZDICT_MIN_SAMPLES_SIZE (ZDICT_CONTENTSIZE_MIN * MINRATIO)
     
     
     /*-**************************************
    @@ -59,11 +60,8 @@
     
     #define NOISELENGTH 32
     
    -#define MINRATIO 4
     static const int g_compressionLevel_default = 6;
     static const U32 g_selectivity_default = 9;
    -static const size_t g_provision_entropySize = 200;
    -static const size_t g_min_fast_dictContent = 192;
     
     
     /*-*************************************
    @@ -308,10 +306,10 @@ static dictItem ZDICT_analyzePos(
             /* look backward */
             length = MINMATCHLENGTH;
             while ((length >= MINMATCHLENGTH) & (start > 0)) {
    -        	length = ZDICT_count(b + pos, b + suffix[start - 1]);
    -        	if (length >= LLIMIT) length = LLIMIT - 1;
    -        	lengthList[length]++;
    -        	if (length >= MINMATCHLENGTH) start--;
    +            length = ZDICT_count(b + pos, b + suffix[start - 1]);
    +            if (length >= LLIMIT) length = LLIMIT - 1;
    +            lengthList[length]++;
    +            if (length >= MINMATCHLENGTH) start--;
             }
     
             /* largest useful length */
    @@ -363,21 +361,35 @@ static dictItem ZDICT_analyzePos(
     }
     
     
    +static int isIncluded(const void* in, const void* container, size_t length)
    +{
    +    const char* const ip = (const char*) in;
    +    const char* const into = (const char*) container;
    +    size_t u;
    +
    +    for (u=0; upos;
         const U32 eltEnd = elt.pos + elt.length;
    +    const char* const buf = (const char*) buffer;
     
         /* tail overlap */
         U32 u; for (u=1; u elt.pos) && (table[u].pos <= eltEnd)) {  /* overlap, existing > new */
                 /* append */
    -            U32 addedLength = table[u].pos - elt.pos;
    +            U32 const addedLength = table[u].pos - elt.pos;
                 table[u].length += addedLength;
                 table[u].pos = elt.pos;
                 table[u].savings += elt.savings * addedLength / elt.length;   /* rough approx */
    @@ -393,9 +405,10 @@ static U32 ZDICT_checkMerge(dictItem* table, dictItem elt, U32 eltNbToSkip)
         /* front overlap */
         for (u=1; u= elt.pos) && (table[u].pos < elt.pos)) {  /* overlap, existing < new */
                 /* append */
    -            int addedLength = (int)eltEnd - (table[u].pos + table[u].length);
    +            int const addedLength = (int)eltEnd - (table[u].pos + table[u].length);
                 table[u].savings += elt.length / 8;    /* rough approx bonus */
                 if (addedLength > 0) {   /* otherwise, elt fully included into existing */
                     table[u].length += addedLength;
    @@ -407,7 +420,18 @@ static U32 ZDICT_checkMerge(dictItem* table, dictItem elt, U32 eltNbToSkip)
                     table[u] = table[u-1], u--;
                 table[u] = elt;
                 return u;
    -    }   }
    +        }
    +
    +        if (MEM_read64(buf + table[u].pos) == MEM_read64(buf + elt.pos + 1)) {
    +            if (isIncluded(buf + table[u].pos, buf + elt.pos + 1, table[u].length)) {
    +                size_t const addedLength = MAX( (int)elt.length - (int)table[u].length , 1 );
    +                table[u].pos = elt.pos;
    +                table[u].savings += (U32)(elt.savings * addedLength / elt.length);
    +                table[u].length = MIN(elt.length, table[u].length + 1);
    +                return u;
    +            }
    +        }
    +    }
     
         return 0;
     }
    @@ -425,14 +449,14 @@ static void ZDICT_removeDictItem(dictItem* table, U32 id)
     }
     
     
    -static void ZDICT_insertDictItem(dictItem* table, U32 maxSize, dictItem elt)
    +static void ZDICT_insertDictItem(dictItem* table, U32 maxSize, dictItem elt, const void* buffer)
     {
         /* merge if possible */
    -    U32 mergeId = ZDICT_checkMerge(table, elt, 0);
    +    U32 mergeId = ZDICT_tryMerge(table, elt, 0, buffer);
         if (mergeId) {
             U32 newMerge = 1;
             while (newMerge) {
    -            newMerge = ZDICT_checkMerge(table, table[mergeId], mergeId);
    +            newMerge = ZDICT_tryMerge(table, table[mergeId], mergeId, buffer);
                 if (newMerge) ZDICT_removeDictItem(table, mergeId);
                 mergeId = newMerge;
             }
    @@ -480,7 +504,7 @@ static size_t ZDICT_trainBuffer(dictItem* dictList, U32 dictListSize,
     #   define DISPLAYUPDATE(l, ...) if (notificationLevel>=l) { \
                 if (ZDICT_clockSpan(displayClock) > refreshRate)  \
                 { displayClock = clock(); DISPLAY(__VA_ARGS__); \
    -            if (notificationLevel>=4) fflush(stdout); } }
    +            if (notificationLevel>=4) fflush(stderr); } }
     
         /* init */
         DISPLAYLEVEL(2, "\r%70s\r", "");   /* clean display line */
    @@ -521,7 +545,7 @@ static size_t ZDICT_trainBuffer(dictItem* dictList, U32 dictListSize,
                 if (doneMarks[cursor]) { cursor++; continue; }
                 solution = ZDICT_analyzePos(doneMarks, suffix, reverseSuffix[cursor], buffer, minRatio, notificationLevel);
                 if (solution.length==0) { cursor++; continue; }
    -            ZDICT_insertDictItem(dictList, dictListSize, solution);
    +            ZDICT_insertDictItem(dictList, dictListSize, solution, buffer);
                 cursor += solution.length;
                 DISPLAYUPDATE(2, "\r%4.2f %% \r", (double)cursor / bufferSize * 100);
         }   }
    @@ -683,19 +707,19 @@ static size_t ZDICT_analyzeEntropy(void*  dstBuffer, size_t maxDstSize,
             goto _cleanup;
         }
         if (offcodeMax>OFFCODE_MAX) { eSize = ERROR(dictionary_wrong); goto _cleanup; }   /* too large dictionary */
    -    for (u=0; u<256; u++) countLit[u]=1;   /* any character must be described */
    -    for (u=0; u<=offcodeMax; u++) offcodeCount[u]=1;
    -    for (u=0; u<=MaxML; u++) matchLengthCount[u]=1;
    -    for (u=0; u<=MaxLL; u++) litLengthCount[u]=1;
    +    for (u=0; u<256; u++) countLit[u] = 1;   /* any character must be described */
    +    for (u=0; u<=offcodeMax; u++) offcodeCount[u] = 1;
    +    for (u=0; u<=MaxML; u++) matchLengthCount[u] = 1;
    +    for (u=0; u<=MaxLL; u++) litLengthCount[u] = 1;
         memset(repOffset, 0, sizeof(repOffset));
         repOffset[1] = repOffset[4] = repOffset[8] = 1;
         memset(bestRepOffset, 0, sizeof(bestRepOffset));
    -    if (compressionLevel==0) compressionLevel=g_compressionLevel_default;
    +    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)) {
    +        if (ZSTD_isError(beginResult)) {
    +            DISPLAYLEVEL(1, "error : ZSTD_compressBegin_advanced() failed : %s \n", ZSTD_getErrorName(beginResult));
                 eSize = ERROR(GENERIC);
    -            DISPLAYLEVEL(1, "error : ZSTD_compressBegin_advanced failed \n");
                 goto _cleanup;
         }   }
     
    @@ -812,7 +836,6 @@ static size_t ZDICT_analyzeEntropy(void*  dstBuffer, size_t maxDstSize,
         MEM_writeLE32(dstPtr+4, repStartValue[1]);
         MEM_writeLE32(dstPtr+8, repStartValue[2]);
     #endif
    -    //dstPtr += 12;
         eSize += 12;
     
     _cleanup:
    @@ -831,7 +854,7 @@ size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
                               ZDICT_params_t params)
     {
         size_t hSize;
    -#define HBUFFSIZE 256
    +#define HBUFFSIZE 256   /* should prove large enough for all entropy headers */
         BYTE header[HBUFFSIZE];
         int const compressionLevel = (params.compressionLevel <= 0) ? g_compressionLevel_default : params.compressionLevel;
         U32 const notificationLevel = params.notificationLevel;
    @@ -877,20 +900,11 @@ size_t ZDICT_addEntropyTablesFromBuffer_advanced(void* dictBuffer, size_t dictCo
                                                      const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
                                                      ZDICT_params_t params)
     {
    -    size_t hSize;
         int const compressionLevel = (params.compressionLevel <= 0) ? g_compressionLevel_default : params.compressionLevel;
         U32 const notificationLevel = params.notificationLevel;
    +    size_t hSize = 8;
     
    -    /* dictionary header */
    -    MEM_writeLE32(dictBuffer, ZSTD_DICT_MAGIC);
    -    {   U64 const randomID = XXH64((char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize, 0);
    -        U32 const compliantID = (randomID % ((1U<<31)-32768)) + 32768;
    -        U32 const dictID = params.dictID ? params.dictID : compliantID;
    -        MEM_writeLE32((char*)dictBuffer+4, dictID);
    -    }
    -    hSize = 8;
    -
    -    /* entropy tables */
    +    /* calculate entropy tables */
         DISPLAYLEVEL(2, "\r%70s\r", "");   /* clean display line */
         DISPLAYLEVEL(2, "statistics ... \n");
         {   size_t const eSize = ZDICT_analyzeEntropy((char*)dictBuffer+hSize, dictBufferCapacity-hSize,
    @@ -902,6 +916,13 @@ size_t ZDICT_addEntropyTablesFromBuffer_advanced(void* dictBuffer, size_t dictCo
             hSize += eSize;
         }
     
    +    /* add dictionary header (after entropy tables) */
    +    MEM_writeLE32(dictBuffer, ZSTD_DICT_MAGIC);
    +    {   U64 const randomID = XXH64((char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize, 0);
    +        U32 const compliantID = (randomID % ((1U<<31)-32768)) + 32768;
    +        U32 const dictID = params.dictID ? params.dictID : compliantID;
    +        MEM_writeLE32((char*)dictBuffer+4, dictID);
    +    }
     
         if (hSize + dictContentSize < dictBufferCapacity)
             memmove((char*)dictBuffer + hSize, (char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize);
    @@ -929,8 +950,8 @@ size_t ZDICT_trainFromBuffer_unsafe(
     
         /* checks */
         if (!dictList) return ERROR(memory_allocation);
    -    if (maxDictSize <= g_provision_entropySize + g_min_fast_dictContent) { free(dictList); return ERROR(dstSize_tooSmall); }
    -    if (samplesBuffSize < ZDICT_MIN_SAMPLES_SIZE) { free(dictList); return 0; }   /* not enough source to create dictionary */
    +    if (maxDictSize < ZDICT_DICTSIZE_MIN) { free(dictList); return ERROR(dstSize_tooSmall); }   /* requested dictionary size is too small */
    +    if (samplesBuffSize < ZDICT_MIN_SAMPLES_SIZE) { free(dictList); return ERROR(dictionaryCreation_failed); }   /* not enough source to create dictionary */
     
         /* init */
         ZDICT_initDictItem(dictList);
    @@ -963,14 +984,15 @@ size_t ZDICT_trainFromBuffer_unsafe(
     
         /* create dictionary */
         {   U32 dictContentSize = ZDICT_dictSize(dictList);
    -        if (dictContentSize < targetDictSize/3) {
    +        if (dictContentSize < ZDICT_CONTENTSIZE_MIN) { free(dictList); return ERROR(dictionaryCreation_failed); }   /* dictionary content too small */
    +        if (dictContentSize < targetDictSize/4) {
                 DISPLAYLEVEL(2, "!  warning : selected content significantly smaller than requested (%u < %u) \n", dictContentSize, (U32)maxDictSize);
    +            if (samplesBuffSize < 10 * targetDictSize)
    +                DISPLAYLEVEL(2, "!  consider increasing the number of samples (total size : %u MB)\n", (U32)(samplesBuffSize>>20));
                 if (minRep > MINRATIO) {
                     DISPLAYLEVEL(2, "!  consider increasing selectivity to produce larger dictionary (-s%u) \n", selectivity+1);
                     DISPLAYLEVEL(2, "!  note : larger dictionaries are not necessarily better, test its efficiency on samples \n");
                 }
    -            if (samplesBuffSize < 10 * targetDictSize)
    -                DISPLAYLEVEL(2, "!  consider increasing the number of samples (total size : %u MB)\n", (U32)(samplesBuffSize>>20));
             }
     
             if ((dictContentSize > targetDictSize*3) && (nbSamples > 2*MINRATIO) && (selectivity>1)) {
    @@ -978,7 +1000,7 @@ size_t ZDICT_trainFromBuffer_unsafe(
                 while ((nbSamples >> proposedSelectivity) <= MINRATIO) { proposedSelectivity--; }
                 DISPLAYLEVEL(2, "!  note : calculated dictionary significantly larger than requested (%u > %u) \n", dictContentSize, (U32)maxDictSize);
                 DISPLAYLEVEL(2, "!  consider increasing dictionary size, or produce denser dictionary (-s%u) \n", proposedSelectivity);
    -            DISPLAYLEVEL(2, "!  always test dictionary efficiency on samples \n");
    +            DISPLAYLEVEL(2, "!  always test dictionary efficiency on real samples \n");
             }
     
             /* limit dictionary size */
    diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h
    index 4ead4474fa9b..9b53de346527 100644
    --- a/lib/dictBuilder/zdict.h
    +++ b/lib/dictBuilder/zdict.h
    @@ -88,7 +88,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dict
     
     /*! COVER_params_t :
         For all values 0 means default.
    -    kMin and d are the only required parameters.
    +    k and d are the only required parameters.
     */
     typedef struct {
         unsigned k;                  /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */
    @@ -147,18 +147,18 @@ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void* dictBuffer, size_t dictB
         Samples must be stored concatenated in a flat buffer `samplesBuffer`,
         supplied with an array of sizes `samplesSizes`, providing the size of each sample in order.
     
    -    dictContentSize must be > ZDICT_CONTENTSIZE_MIN bytes.
    -    maxDictSize must be >= dictContentSize, and must be > ZDICT_DICTSIZE_MIN bytes.
    +    dictContentSize must be >= ZDICT_CONTENTSIZE_MIN bytes.
    +    maxDictSize must be >= dictContentSize, and must be >= ZDICT_DICTSIZE_MIN bytes.
     
         @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`),
                   or an error code, which can be tested by ZDICT_isError().
         note : ZDICT_finalizeDictionary() will push notifications into stderr if instructed to, using notificationLevel>0.
    -    note 2 : dictBuffer and customDictContent can overlap
    +    note 2 : dictBuffer and dictContent can overlap
     */
    -#define ZDICT_CONTENTSIZE_MIN 256
    -#define ZDICT_DICTSIZE_MIN    512
    +#define ZDICT_CONTENTSIZE_MIN 128
    +#define ZDICT_DICTSIZE_MIN    256
     ZDICTLIB_API size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
    -                                const void* customDictContent, size_t dictContentSize,
    +                                const void* dictContent, size_t dictContentSize,
                                     const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
                                     ZDICT_params_t parameters);
     
    diff --git a/lib/legacy/zstd_v01.c b/lib/legacy/zstd_v01.c
    index bcacb8d5d7a2..cf5354d6a9b6 100644
    --- a/lib/legacy/zstd_v01.c
    +++ b/lib/legacy/zstd_v01.c
    @@ -1432,7 +1432,7 @@ typedef struct ZSTD_Cctx_s
     #else
         U32 hashTable[HASH_TABLESIZE];
     #endif
    -	BYTE buffer[WORKPLACESIZE];
    +    BYTE buffer[WORKPLACESIZE];
     } cctxi_t;
     
     
    diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c
    index 2297b28c8b2e..3cf8f4778250 100644
    --- a/lib/legacy/zstd_v02.c
    +++ b/lib/legacy/zstd_v02.c
    @@ -475,8 +475,8 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
     
     MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
     {
    -	if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    -		return BIT_DStream_overflow;
    +    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    +        return BIT_DStream_overflow;
     
         if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))
         {
    @@ -1334,8 +1334,8 @@ static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsi
                     else
                     {
                         bitCount -= (int)(8 * (iend - 4 - ip));
    -					ip = iend - 4;
    -				}
    +                    ip = iend - 4;
    +                }
                     bitStream = MEM_readLE32(ip) >> (bitCount & 31);
                 }
             }
    @@ -2040,7 +2040,7 @@ static size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)
             rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
         }
     
    -	/* Build rankVal */
    +    /* Build rankVal */
         {
             const U32 minBits = tableLog+1 - maxW;
             U32 nextRankVal = 0;
    @@ -2374,7 +2374,7 @@ static size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize)
             rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
         }
     
    -	/* Build rankVal */
    +    /* Build rankVal */
         {
             const U32 minBits = tableLog+1 - maxW;
             U32 nextRankVal = 0;
    @@ -2948,14 +2948,14 @@ static size_t ZSTD_decodeLiteralsBlock(void* ctx,
                 const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
                 if (litSize > srcSize-11)   /* risk of reading too far with wildcopy */
                 {
    -				if (litSize > srcSize-3) return ERROR(corruption_detected);
    -				memcpy(dctx->litBuffer, istart, litSize);
    -				dctx->litPtr = dctx->litBuffer;
    -				dctx->litSize = litSize;
    -				memset(dctx->litBuffer + dctx->litSize, 0, 8);
    -				return litSize+3;
    -			}
    -			/* direct reference into compressed stream */
    +                if (litSize > srcSize-3) return ERROR(corruption_detected);
    +                memcpy(dctx->litBuffer, istart, litSize);
    +                dctx->litPtr = dctx->litBuffer;
    +                dctx->litSize = litSize;
    +                memset(dctx->litBuffer + dctx->litSize, 0, 8);
    +                return litSize+3;
    +            }
    +            /* direct reference into compressed stream */
                 dctx->litPtr = istart+3;
                 dctx->litSize = litSize;
                 return litSize+3;
    @@ -3515,13 +3515,13 @@ static size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSi
     
     unsigned ZSTDv02_isError(size_t code)
     {
    -	return ZSTD_isError(code);
    +    return ZSTD_isError(code);
     }
     
     size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,
                          const void* src, size_t compressedSize)
     {
    -	return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
    +    return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
     }
     
     size_t ZSTDv02_findFrameCompressedSize(const void *src, size_t compressedSize)
    @@ -3531,25 +3531,25 @@ size_t ZSTDv02_findFrameCompressedSize(const void *src, size_t compressedSize)
     
     ZSTDv02_Dctx* ZSTDv02_createDCtx(void)
     {
    -	return (ZSTDv02_Dctx*)ZSTD_createDCtx();
    +    return (ZSTDv02_Dctx*)ZSTD_createDCtx();
     }
     
     size_t ZSTDv02_freeDCtx(ZSTDv02_Dctx* dctx)
     {
    -	return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);
    +    return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);
     }
     
     size_t ZSTDv02_resetDCtx(ZSTDv02_Dctx* dctx)
     {
    -	return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);
    +    return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);
     }
     
     size_t ZSTDv02_nextSrcSizeToDecompress(ZSTDv02_Dctx* dctx)
     {
    -	return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);
    +    return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);
     }
     
     size_t ZSTDv02_decompressContinue(ZSTDv02_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
     {
    -	return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);
    +    return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);
     }
    diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c
    index ef654931f528..f438330a4692 100644
    --- a/lib/legacy/zstd_v03.c
    +++ b/lib/legacy/zstd_v03.c
    @@ -477,8 +477,8 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
     
     MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
     {
    -	if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    -		return BIT_DStream_overflow;
    +    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    +        return BIT_DStream_overflow;
     
         if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))
         {
    @@ -1335,8 +1335,8 @@ static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsi
                     else
                     {
                         bitCount -= (int)(8 * (iend - 4 - ip));
    -					ip = iend - 4;
    -				}
    +                    ip = iend - 4;
    +                }
                     bitStream = MEM_readLE32(ip) >> (bitCount & 31);
                 }
             }
    @@ -2037,7 +2037,7 @@ static size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)
             rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
         }
     
    -	/* Build rankVal */
    +    /* Build rankVal */
         {
             const U32 minBits = tableLog+1 - maxW;
             U32 nextRankVal = 0;
    @@ -2589,14 +2589,14 @@ static size_t ZSTD_decodeLiteralsBlock(void* ctx,
                 const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
                 if (litSize > srcSize-11)   /* risk of reading too far with wildcopy */
                 {
    -				if (litSize > srcSize-3) return ERROR(corruption_detected);
    -				memcpy(dctx->litBuffer, istart, litSize);
    -				dctx->litPtr = dctx->litBuffer;
    -				dctx->litSize = litSize;
    -				memset(dctx->litBuffer + dctx->litSize, 0, 8);
    -				return litSize+3;
    -			}
    -			/* direct reference into compressed stream */
    +                if (litSize > srcSize-3) return ERROR(corruption_detected);
    +                memcpy(dctx->litBuffer, istart, litSize);
    +                dctx->litPtr = dctx->litBuffer;
    +                dctx->litSize = litSize;
    +                memset(dctx->litBuffer + dctx->litSize, 0, 8);
    +                return litSize+3;
    +            }
    +            /* direct reference into compressed stream */
                 dctx->litPtr = istart+3;
                 dctx->litSize = litSize;
                 return litSize+3;
    @@ -3156,13 +3156,13 @@ static size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSi
     
     unsigned ZSTDv03_isError(size_t code)
     {
    -	return ZSTD_isError(code);
    +    return ZSTD_isError(code);
     }
     
     size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,
                          const void* src, size_t compressedSize)
     {
    -	return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
    +    return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
     }
     
     size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t srcSize)
    @@ -3172,25 +3172,25 @@ size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t srcSize)
     
     ZSTDv03_Dctx* ZSTDv03_createDCtx(void)
     {
    -	return (ZSTDv03_Dctx*)ZSTD_createDCtx();
    +    return (ZSTDv03_Dctx*)ZSTD_createDCtx();
     }
     
     size_t ZSTDv03_freeDCtx(ZSTDv03_Dctx* dctx)
     {
    -	return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);
    +    return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);
     }
     
     size_t ZSTDv03_resetDCtx(ZSTDv03_Dctx* dctx)
     {
    -	return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);
    +    return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);
     }
     
     size_t ZSTDv03_nextSrcSizeToDecompress(ZSTDv03_Dctx* dctx)
     {
    -	return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);
    +    return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);
     }
     
     size_t ZSTDv03_decompressContinue(ZSTDv03_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
     {
    -	return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);
    +    return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);
     }
    diff --git a/lib/legacy/zstd_v04.c b/lib/legacy/zstd_v04.c
    index 09040e68ec56..1a29da92d1e8 100644
    --- a/lib/legacy/zstd_v04.c
    +++ b/lib/legacy/zstd_v04.c
    @@ -882,8 +882,8 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
     
     MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
     {
    -	if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    -		return BIT_DStream_overflow;
    +    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    +        return BIT_DStream_overflow;
     
         if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))
         {
    @@ -1451,8 +1451,8 @@ static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsi
                     else
                     {
                         bitCount -= (int)(8 * (iend - 4 - ip));
    -					ip = iend - 4;
    -				}
    +                    ip = iend - 4;
    +                }
                     bitStream = MEM_readLE32(ip) >> (bitCount & 31);
                 }
             }
    diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c
    index a6f5f5dbbd16..674f5b0e4a8e 100644
    --- a/lib/legacy/zstd_v05.c
    +++ b/lib/legacy/zstd_v05.c
    @@ -884,8 +884,8 @@ MEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, U32 nbBits)
     
     MEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD)
     {
    -	if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    -		return BITv05_DStream_overflow;
    +    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    +        return BITv05_DStream_overflow;
     
         if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
             bitD->ptr -= bitD->bitsConsumed >> 3;
    diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c
    index a4258b67a618..ad8c4cd3186d 100644
    --- a/lib/legacy/zstd_v06.c
    +++ b/lib/legacy/zstd_v06.c
    @@ -982,8 +982,8 @@ MEM_STATIC size_t BITv06_readBitsFast(BITv06_DStream_t* bitD, U32 nbBits)
                   if status == unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
     MEM_STATIC BITv06_DStream_status BITv06_reloadDStream(BITv06_DStream_t* bitD)
     {
    -	if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    -		return BITv06_DStream_overflow;
    +    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
    +        return BITv06_DStream_overflow;
     
         if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
             bitD->ptr -= bitD->bitsConsumed >> 3;
    diff --git a/lib/zstd.h b/lib/zstd.h
    index a3237c77eebd..f8050c136104 100644
    --- a/lib/zstd.h
    +++ b/lib/zstd.h
    @@ -55,8 +55,8 @@ extern "C" {
     
     /*------   Version   ------*/
     #define ZSTD_VERSION_MAJOR    1
    -#define ZSTD_VERSION_MINOR    1
    -#define ZSTD_VERSION_RELEASE  4
    +#define ZSTD_VERSION_MINOR    2
    +#define ZSTD_VERSION_RELEASE  0
     
     #define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
     #define ZSTD_QUOTE(str) #str
    @@ -71,48 +71,48 @@ ZSTDLIB_API unsigned ZSTD_versionNumber(void);   /**< library version number; to
     *  Simple API
     ***************************************/
     /*! ZSTD_compress() :
    -    Compresses `src` content as a single zstd compressed frame into already allocated `dst`.
    -    Hint : compression runs faster if `dstCapacity` >=  `ZSTD_compressBound(srcSize)`.
    -    @return : compressed size written into `dst` (<= `dstCapacity),
    -              or an error code if it fails (which can be tested using ZSTD_isError()). */
    + *  Compresses `src` content as a single zstd compressed frame into already allocated `dst`.
    + *  Hint : compression runs faster if `dstCapacity` >=  `ZSTD_compressBound(srcSize)`.
    + *  @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_decompress() :
    -    `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames.
    -    `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()). */
    + *  `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames.
    + *  `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() :
    -*   NOTE: This function is planned to be obsolete, in favour of ZSTD_getFrameContentSize.
    -*   ZSTD_getFrameContentSize functions the same way, returning the decompressed size of a single
    -*   frame, but distinguishes empty frames from frames with an unknown size, or errors.
    -*
    -*   Additionally, ZSTD_findDecompressedSize can be used instead.  It can handle multiple
    -*   concatenated frames in one buffer, and so is more general.
    -*   As a result however, it requires more computation and entire frames to be passed to it,
    -*   as opposed to ZSTD_getFrameContentSize which requires only a single frame's header.
    -*
    -*   '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. */
    + *  NOTE: This function is planned to be obsolete, in favour of ZSTD_getFrameContentSize.
    + *  ZSTD_getFrameContentSize functions the same way, returning the decompressed size of a single
    + *  frame, but distinguishes empty frames from frames with an unknown size, or errors.
    + *
    + *  Additionally, ZSTD_findDecompressedSize can be used instead.  It can handle multiple
    + *  concatenated frames in one buffer, and so is more general.
    + *  As a result however, it requires more computation and entire frames to be passed to it,
    + *  as opposed to ZSTD_getFrameContentSize which requires only a single frame's header.
    + *
    + *  '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);
     
     
    @@ -127,29 +127,29 @@ ZSTDLIB_API const char* ZSTD_getErrorName(size_t code);     /*!< provides readab
     *  Explicit memory management
     ***************************************/
     /*= Compression context
    -*   When compressing many times,
    -*   it is recommended to allocate a context just once, and re-use it for each successive compression operation.
    -*   This will make workload friendlier for system's memory.
    -*   Use one context per thread for parallel execution in multi-threaded environments. */
    + *  When compressing many times,
    + *  it is recommended to allocate a context just once, and re-use it for each successive compression operation.
    + *  This will make workload friendlier for system's memory.
    + *  Use one context per thread for parallel execution in multi-threaded environments. */
     typedef struct ZSTD_CCtx_s ZSTD_CCtx;
     ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
     ZSTDLIB_API size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);
     
     /*! ZSTD_compressCCtx() :
    -    Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()). */
    + *  Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()). */
     ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel);
     
     /*= Decompression context
    -*   When decompressing many times,
    -*   it is recommended to allocate a context just once, and re-use it for each successive compression operation.
    -*   This will make workload friendlier for system's memory.
    -*   Use one context per thread for parallel execution in multi-threaded environments. */
    + *  When decompressing many times,
    + *  it is recommended to allocate a context just once, and re-use it for each successive compression operation.
    + *  This will make workload friendlier for system's memory.
    + *  Use one context per thread for parallel execution in multi-threaded environments. */
     typedef struct ZSTD_DCtx_s ZSTD_DCtx;
     ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);
     ZSTDLIB_API size_t     ZSTD_freeDCtx(ZSTD_DCtx* dctx);
     
     /*! ZSTD_decompressDCtx() :
    -*   Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()). */
    + *  Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()). */
     ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
     
     
    @@ -194,9 +194,10 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize
     ZSTDLIB_API size_t      ZSTD_freeCDict(ZSTD_CDict* CDict);
     
     /*! 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. */
    + *  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.
    + *  Frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
     ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
                                                 void* dst, size_t dstCapacity,
                                           const void* src, size_t srcSize,
    @@ -487,7 +488,7 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, siz
     /*! 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, unsigned byReference,
    -                                                  ZSTD_parameters params, ZSTD_customMem customMem);
    +                                                  ZSTD_compressionParameters cParams, ZSTD_customMem customMem);
     
     /*! ZSTD_sizeof_CDict() :
      *  Gives the amount of memory used by a given ZSTD_sizeof_CDict */
    @@ -513,12 +514,19 @@ ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
     ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
     
     /*! ZSTD_compress_advanced() :
    -*   Same as ZSTD_compress_usingDict(), with fine-tune control of each compression parameter */
    -ZSTDLIB_API size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
    -                                           void* dst, size_t dstCapacity,
    -                                     const void* src, size_t srcSize,
    -                                     const void* dict,size_t dictSize,
    -                                           ZSTD_parameters params);
    +*   Same as ZSTD_compress_usingDict(), with fine-tune control over each compression parameter */
    +ZSTDLIB_API size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
    +                                  void* dst, size_t dstCapacity,
    +                            const void* src, size_t srcSize,
    +                            const void* dict,size_t dictSize,
    +                                  ZSTD_parameters params);
    +
    +/*! ZSTD_compress_usingCDict_advanced() :
    +*   Same as ZSTD_compress_usingCDict(), with fine-tune control over frame parameters */
    +ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
    +                                  void* dst, size_t dstCapacity,
    +                            const void* src, size_t srcSize,
    +                            const ZSTD_CDict* cdict, ZSTD_frameParameters fParams);
     
     
     /*--- Advanced decompression functions ---*/
    @@ -578,7 +586,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
      *    Note : this use case also happens when using a non-conformant dictionary.
      *  - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
      *  - This is not a Zstandard frame.
    - *  When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
    + *  When identifying the exact failure cause, it's possible to use ZSTD_getFrameParams(), which will provide a more precise error code. */
     ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
     
     
    @@ -588,13 +596,22 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
     
     /*=====   Advanced Streaming compression functions  =====*/
     ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
    +ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);   /**< size of CStream is variable, depending primarily on compression level */
     ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize);   /**< pledgedSrcSize must be correct, a size of 0 means unknown.  for a frame size of 0 use initCStream_advanced */
     ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */
     ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
                                                  ZSTD_parameters params, unsigned long long pledgedSrcSize);  /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */
     ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);  /**< note : cdict will just be referenced, and must outlive compression session */
    -ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);  /**< re-use compression parameters from previous init; skip dictionary loading stage; zcs must be init at least once before. note: pledgedSrcSize must be correct, a size of 0 means unknown.  for a frame size of 0 use initCStream_advanced */
    -ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
    +ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize, ZSTD_frameParameters fParams);  /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
    +
    +/*! ZSTD_resetCStream() :
    + *  start a new compression job, using same parameters from previous job.
    + *  This is typically useful to skip dictionary loading stage, since it will re-use it in-place..
    + *  Note that zcs must be init at least once before using ZSTD_resetCStream().
    + *  pledgedSrcSize==0 means "srcSize unknown".
    + *  If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.
    + *  @return : 0, or an error code (which can be tested using ZSTD_isError()) */
    +ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
     
     
     /*=====   Advanced Streaming decompression functions  =====*/
    @@ -650,8 +667,10 @@ 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); /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */
    +ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
    +ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize);   /* compression parameters are already set within cdict. pledgedSrcSize=0 means null-size */
     ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**<  note: if pledgedSrcSize can be 0, indicating unknown size.  if it is non-zero, it must be accurate.  for 0 size frames, use compressBegin_advanced */
    -ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize can be 0, indicating unknown size.  if it is non-zero, it must be accurate.  for 0 size frames, use compressBegin_advanced */
    +
     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);
     
    @@ -745,19 +764,20 @@ ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
         - Compressing and decompressing require a context structure
           + Use ZSTD_createCCtx() and ZSTD_createDCtx()
         - It is necessary to init context before starting
    -      + compression : ZSTD_compressBegin()
    -      + decompression : ZSTD_decompressBegin()
    -      + variants _usingDict() are also allowed
    -      + copyCCtx() and copyDCtx() work too
    -    - Block size is limited, it must be <= ZSTD_getBlockSizeMax()
    -      + If you need to compress more, cut data into multiple blocks
    -      + Consider using the regular ZSTD_compress() instead, as frame metadata costs become negligible when source size is large.
    +      + compression : any ZSTD_compressBegin*() variant, including with dictionary
    +      + decompression : any ZSTD_decompressBegin*() variant, including with dictionary
    +      + copyCCtx() and copyDCtx() can be used too
    +    - Block size is limited, it must be <= ZSTD_getBlockSizeMax() <= ZSTD_BLOCKSIZE_ABSOLUTEMAX
    +      + If input is larger than a block size, it's necessary to split input data into multiple blocks
    +      + For inputs larger than a single block size, consider using the regular ZSTD_compress() instead.
    +        Frame metadata is not that costly, and quickly becomes negligible as source size grows larger.
         - When a block is considered not compressible enough, ZSTD_compressBlock() result will be zero.
           In which case, nothing is produced into `dst`.
           + User must test for such outcome and deal directly with uncompressed data
           + ZSTD_decompressBlock() doesn't accept uncompressed data as input !!!
    -      + In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history.
    -        Use ZSTD_insertBlock() in such a case.
    +      + In case of multiple successive blocks, should some of them be uncompressed,
    +        decoder must be informed of their existence in order to follow proper history.
    +        Use ZSTD_insertBlock() for such a case.
     */
     
     #define ZSTD_BLOCKSIZE_ABSOLUTEMAX (128 * 1024)   /* define, for static allocation */
    diff --git a/programs/Makefile b/programs/Makefile
    index 1475cb610916..0c920a87bcbd 100644
    --- a/programs/Makefile
    +++ b/programs/Makefile
    @@ -18,6 +18,19 @@
     
     ZSTDDIR = ../lib
     
    +# Version numbers
    +LIBVER_SRC := $(ZSTDDIR)/zstd.h
    +LIBVER_MAJOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)`
    +LIBVER_MINOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)`
    +LIBVER_PATCH_SCRIPT:=`sed -n '/define ZSTD_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)`
    +LIBVER_SCRIPT:= $(LIBVER_MAJOR_SCRIPT).$(LIBVER_MINOR_SCRIPT).$(LIBVER_PATCH_SCRIPT)
    +LIBVER_MAJOR := $(shell echo $(LIBVER_MAJOR_SCRIPT))
    +LIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT))
    +LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT))
    +LIBVER  := $(shell echo $(LIBVER_SCRIPT))
    +
    +ZSTD_VERSION=$(LIBVER)
    +
     ifeq ($(shell $(CC) -v 2>&1 | grep -c "gcc version "), 1)
     ALIGN_LOOP = -falign-loops=32
     else
    @@ -69,10 +82,23 @@ else
     EXT =
     endif
     
    +VOID = /dev/null
    +
    +# thread detection
    +NO_THREAD_MSG := ==> no threads, building without multithreading support
    +HAVE_PTHREAD := $(shell printf '\#include \nint main(void) { return 0; }' | $(CC) $(FLAGS) -o have_pthread$(EXT) -x c - -pthread 2> $(VOID) && rm have_pthread$(EXT) && echo 1 || echo 0)
    +HAVE_THREAD := $(shell [ "$(HAVE_PTHREAD)" -eq "1" -o -n "$(filter Windows%,$(OS))" ] && echo 1 || echo 0)
    +ifeq ($(HAVE_THREAD), 1)
    +THREAD_MSG := ==> building with threading support
    +THREAD_CPP := -DZSTD_MULTITHREAD
    +THREAD_LD := -pthread
    +else
    +THREAD_MSG := $(NO_THREAD_MSG)
    +endif
    +
     # zlib detection
     NO_ZLIB_MSG := ==> no zlib, building zstd without .gz support
    -VOID = /dev/null
    -HAVE_ZLIB := $(shell printf '\#include \nint main(){}' | $(CC) -o have_zlib -x c - -lz 2> $(VOID) && rm have_zlib$(EXT) && echo 1 || echo 0)
    +HAVE_ZLIB := $(shell printf '\#include \nint main(void) { return 0; }' | $(CC) $(FLAGS) -o have_zlib$(EXT) -x c - -lz 2> $(VOID) && rm have_zlib$(EXT) && echo 1 || echo 0)
     ifeq ($(HAVE_ZLIB), 1)
     ZLIB_MSG := ==> building zstd with .gz compression support
     ZLIBCPP = -DZSTD_GZCOMPRESS -DZSTD_GZDECOMPRESS
    @@ -80,9 +106,10 @@ ZLIBLD = -lz
     else
     ZLIB_MSG := $(NO_ZLIB_MSG)
     endif
    +
     # lzma detection
     NO_LZMA_MSG := ==> no liblzma, building zstd without .xz/.lzma support
    -HAVE_LZMA := $(shell printf '\#include \nint main(){}' | $(CC) -o have_lzma -x c - -llzma 2> $(VOID) && rm have_lzma$(EXT) && echo 1 || echo 0)
    +HAVE_LZMA := $(shell printf '\#include \nint main(void) { return 0; }' | $(CC) $(FLAGS) -o have_lzma$(EXT) -x c - -llzma 2> $(VOID) && rm have_lzma$(EXT) && echo 1 || echo 0)
     ifeq ($(HAVE_LZMA), 1)
     LZMA_MSG := ==> building zstd with .xz/.lzma compression support
     LZMACPP = -DZSTD_LZMACOMPRESS -DZSTD_LZMADECOMPRESS
    @@ -91,6 +118,16 @@ else
     LZMA_MSG := $(NO_LZMA_MSG)
     endif
     
    +# lz4 detection
    +NO_LZ4_MSG := ==> no liblz4, building zstd without .lz4 support
    +HAVE_LZ4 := $(shell printf '\#include \n\#include \nint main(void) { return 0; }' | $(CC) $(FLAGS) -o have_lz4$(EXT) -x c - -llz4 2> $(VOID) && rm have_lz4$(EXT) && echo 1 || echo 0)
    +ifeq ($(HAVE_LZ4), 1)
    +LZ4_MSG := ==> building zstd with .lz4 compression support
    +LZ4CPP = -DZSTD_LZ4COMPRESS -DZSTD_LZ4DECOMPRESS
    +LZ4LD = -llz4
    +else
    +LZ4_MSG := $(NO_LZ4_MSG)
    +endif
     
     .PHONY: default all clean clean_decomp_o install uninstall generate_res
     
    @@ -100,17 +137,20 @@ all: zstd
     
     $(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP)
     
    -zstd : CPPFLAGS += $(ZLIBCPP)
    -zstd : LDFLAGS += $(ZLIBLD)
    -zstd : LZMA_MSG := $(NO_LZMA_MSG)
    -zstd-nogz : ZLIB_MSG := $(NO_ZLIB_MSG)
    -zstd-nogz : LZMA_MSG := $(NO_LZMA_MSG)
    -xzstd : CPPFLAGS += $(ZLIBCPP) $(LZMACPP)
    -xzstd : LDFLAGS += $(ZLIBLD) $(LZMALD)
    -zstd zstd-nogz xzstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
    -zstd zstd-nogz xzstd : $(ZSTDLIB_OBJ) zstdcli.o fileio.o bench.o datagen.o dibio.o
    +zstd xzstd zstd4 xzstd4 : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP)
    +zstd xzstd zstd4 xzstd4 : LDFLAGS += $(THREAD_LD) $(ZLIBLD)
    +xzstd xzstd4 : CPPFLAGS += $(LZMACPP)
    +xzstd xzstd4 : LDFLAGS += $(LZMALD)
    +zstd4 xzstd4 : CPPFLAGS += $(LZ4CPP)
    +zstd4 xzstd4 : LDFLAGS += $(LZ4LD)
    +zstd zstd4 : LZMA_MSG := - xz/lzma support is disabled
    +zstd xzstd : LZ4_MSG := - lz4 support is disabled
    +zstd xzstd zstd4 xzstd4 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
    +zstd xzstd zstd4 xzstd4 : $(ZSTDLIB_FILES) zstdcli.o fileio.o bench.o datagen.o dibio.o
    +	@echo "$(THREAD_MSG)"
     	@echo "$(ZLIB_MSG)"
     	@echo "$(LZMA_MSG)"
    +	@echo "$(LZ4_MSG)"
     ifneq (,$(filter Windows%,$(OS)))
     	windres/generate_res.bat
     endif
    @@ -126,10 +166,20 @@ ifneq (,$(filter Windows%,$(OS)))
     endif
     	$(CC) -m32 $(FLAGS) $^ $(RES32_FILE) -o $@$(EXT)
     
    -
     zstd-nolegacy : clean_decomp_o
     	$(MAKE) zstd ZSTD_LEGACY_SUPPORT=0
     
    +zstd-nomt : THREAD_CPP :=
    +zstd-nomt : THREAD_LD :=
    +zstd-nomt : THREAD_MSG := - multi-threading disabled
    +zstd-nomt : zstd
    +
    +zstd-nogz : ZLIBCPP :=
    +zstd-nogz : ZLIBLD :=
    +zstd-nogz : ZLIB_MSG := - gzip support is disabled
    +zstd-nogz : zstd
    +
    +
     zstd-pgo : MOREFLAGS = -fprofile-generate
     zstd-pgo : clean zstd
     	./zstd -b19i1 $(PROFILE_WITH)
    @@ -142,22 +192,18 @@ zstd-pgo : clean zstd
     	$(RM) $(ZSTDDECOMP_O)
     	$(MAKE) zstd MOREFLAGS=-fprofile-use
     
    -zstd-frugal: $(ZSTD_FILES) zstdcli.c fileio.c
    +# minimal target, with only zstd compression and decompression. no bench. no legacy.
    +zstd-small: CFLAGS = "-Os -s"
    +zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c fileio.c
     	$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o zstd$(EXT)
     
    -zstd-small:
    -	CFLAGS="-Os -s" $(MAKE) zstd-frugal
    -
     zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c fileio.c
     	$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o $@$(EXT)
     
     zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c fileio.c
     	$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT)
     
    -zstdmt: CPPFLAGS += -DZSTD_MULTITHREAD
    -ifeq (,$(filter Windows%,$(OS)))
    -zstdmt: LDFLAGS += -lpthread
    -endif
    +# zstd is now built with Multi-threading by default
     zstdmt: zstd
     
     generate_res:
    @@ -174,6 +220,19 @@ clean:
     clean_decomp_o:
     	@$(RM) $(ZSTDDECOMP_O)
     
    +MD2ROFF = ronn
    +MD2ROFF_FLAGS = --roff --warnings --manual="User Commands" --organization="zstd $(ZSTD_VERSION)"
    +
    +zstd.1: zstd.1.md
    +	cat $^ | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\.\\\".*/!p' > $@
    +
    +man: zstd.1
    +
    +clean-man:
    +	rm zstd.1
    +
    +preview-man: clean-man man
    +	man ./zstd.1
     
     #-----------------------------------------------------------------------------
     # make install is validated only for Linux, OSX, BSD, Hurd and Solaris targets
    @@ -206,6 +265,7 @@ install: zstd
     	@$(INSTALL_PROGRAM) zstd $(DESTDIR)$(BINDIR)/zstd
     	@ln -sf zstd $(DESTDIR)$(BINDIR)/zstdcat
     	@ln -sf zstd $(DESTDIR)$(BINDIR)/unzstd
    +	@ln -sf zstd $(DESTDIR)$(BINDIR)/zstdmt
     	@$(INSTALL_SCRIPT) zstdless $(DESTDIR)$(BINDIR)/zstdless
     	@$(INSTALL_SCRIPT) zstdgrep $(DESTDIR)$(BINDIR)/zstdgrep
     	@echo Installing man pages
    diff --git a/programs/README.md b/programs/README.md
    index 203fd7b49bce..d7922a0969e4 100644
    --- a/programs/README.md
    +++ b/programs/README.md
    @@ -11,8 +11,29 @@ There are however other Makefile targets that create different variations of CLI
     - `zstd-decompress` : decompressor-only version of CLI; without dictionary builder, benchmark, and support for decompression of legacy zstd versions
     
     
    +#### Compilation variables
    +`zstd` tries to detect and use the following features automatically :
    +
    +- __HAVE_THREAD__ : multithreading is automatically enabled when `pthread` is detected.
    +  It's possible to disable multithread support, by either compiling `zstd-nomt` target or using HAVE_THREAD=0 variable.
    +  Example : make zstd HAVE_THREAD=0
    +  It's also possible to force compilation with multithread support, using HAVE_THREAD=1.
    +  In which case, linking stage will fail if `pthread` library cannot be found.
    +  This might be useful to prevent silent feature disabling.
    +
    +- __HAVE_ZLIB__ : `zstd` can compress and decompress files in `.gz` format.
    +  This is done through command `--format=gzip`.
    +  Alternatively, symlinks named `gzip` or `gunzip` will mimic intended behavior.
    +  .gz support is automatically enabled when `zlib` library is detected at build time.
    +  It's possible to disable .gz support, by either compiling `zstd-nogz` target or using HAVE_ZLIB=0 variable.
    +  Example : make zstd HAVE_ZLIB=0
    +  It's also possible to force compilation with zlib support, using HAVE_ZLIB=1.
    +  In which case, linking stage will fail if `zlib` library cannot be found.
    +  This might be useful to prevent silent feature disabling.
    +
    +
     #### Aggregation of parameters
    -CLI supports aggregation of parameters i.e. `-b1`, `-e18`, and `-i1` can be joined into `-b1e18i1`. 
    +CLI supports aggregation of parameters i.e. `-b1`, `-e18`, and `-i1` can be joined into `-b1e18i1`.
     
     
     #### Dictionary builder in Command Line Interface
    @@ -23,7 +44,7 @@ which can be loaded before compression and decompression.
     
     Using a 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). 
    +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.
    @@ -35,7 +56,6 @@ Usage of the dictionary builder and created dictionaries with CLI:
     3. Decompress with the dictionary: `zstd --decompress FILE.zst -D dictionaryName`
     
     
    -
     #### Benchmark in Command Line Interface
     CLI includes in-memory compression benchmark module for zstd.
     The benchmark is conducted using given filenames. The files are read into memory and joined together.
    @@ -48,7 +68,6 @@ One can select compression levels starting from `-b` and ending with `-e`.
     The `-i` parameter selects minimal time used for each of tested levels.
     
     
    -
     #### Usage of Command Line Interface
     The full list of options can be obtained with `-h` or `-H` parameter:
     ```
    @@ -62,33 +81,40 @@ Arguments :
      -d     : decompression
      -D file: use `file` as Dictionary
      -o file: result stored into `file` (only if 1 input file)
    - -f     : overwrite output without prompting
    + -f     : overwrite output without prompting and (de)compress links
     --rm    : remove source file(s) after successful de/compression
      -k     : preserve source file(s) (default)
      -h/-H  : display help/long help and exit
     
     Advanced arguments :
      -V     : display Version number and exit
    - -v     : verbose mode; specify multiple times to increase log level (default:2)
    + -v     : verbose mode; specify multiple times to increase verbosity
      -q     : suppress warnings; specify twice to suppress errors too
      -c     : force write to standard output, even if it is the console
    - -r     : operate recursively on directories
     --ultra : enable levels beyond 19, up to 22 (requires more memory)
    + -T#    : use # threads for compression (default:1)
    + -B#    : select size of each job (default:0==automatic)
     --no-dictID : don't write dictID into header (dictionary compression)
     --[no-]check : integrity check (default:enabled)
    + -r     : operate recursively on directories
    +--format=gzip : compress files to the .gz format
     --test  : test compressed file integrity
    ---[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)
    +--[no-]sparse : sparse mode (default:disabled)
    + -M#    : Set a memory usage limit for decompression
    +--      : All arguments after "--" are treated as files
     
     Dictionary builder :
     --train ## : create a dictionary from a training set of files
    +--train-cover[=k=#,d=#,steps=#] : use the cover algorithm with optional args
    +--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: 9)
      -o file : `file` is dictionary name (default: dictionary)
    ---maxdict ## : limit dictionary to specified size (default : 112640)
    - -s#    : dictionary selectivity level (default: 9)
    ---dictID ## : force dictionary ID to specified value (default: random)
    +--maxdict=# : limit dictionary to specified size (default : 112640)
    +--dictID=# : force dictionary ID to specified value (default: random)
     
     Benchmark arguments :
      -b#    : benchmark file(s), using # compression level (default : 1)
      -e#    : test all compression levels from -bX to # (default: 1)
      -i#    : minimum evaluation time in seconds (default : 3s)
      -B#    : cut file into independent blocks of size # (default: no block)
    - ```
    \ No newline at end of file
    +--priority=rt : set process priority to real-time
    +```
    diff --git a/programs/bench.c b/programs/bench.c
    index 2dd1cfb0fab1..22b871952b8e 100644
    --- a/programs/bench.c
    +++ b/programs/bench.c
    @@ -70,12 +70,12 @@ static U32 g_compressibilityDefault = 50;
     ***************************************/
     #define DISPLAY(...)         fprintf(stderr, __VA_ARGS__)
     #define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
    -static U32 g_displayLevel = 2;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */
    +static int g_displayLevel = 2;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */
     
     #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
                 if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \
                 { g_time = clock(); DISPLAY(__VA_ARGS__); \
    -            if (g_displayLevel>=4) fflush(stdout); } }
    +            if (g_displayLevel>=4) fflush(stderr); } }
     static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
     static clock_t g_time = 0;
     
    @@ -89,7 +89,7 @@ static clock_t g_time = 0;
     #define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__);
     #define EXM_THROW(error, ...)                                             \
     {                                                                         \
    -    DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \
    +    DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \
         DISPLAYLEVEL(1, "Error %i : ", error);                                \
         DISPLAYLEVEL(1, __VA_ARGS__);                                         \
         DISPLAYLEVEL(1, " \n");                                               \
    @@ -146,17 +146,20 @@ typedef struct {
     } blockParam_t;
     
     
    -#define MIN(a,b) ((a)<(b) ? (a) : (b))
    -#define MAX(a,b) ((a)>(b) ? (a) : (b))
    +
    +#undef MIN
    +#undef MAX
    +#define MIN(a,b)    ((a) < (b) ? (a) : (b))
    +#define MAX(a,b)    ((a) > (b) ? (a) : (b))
     
     static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
                             const char* displayName, int cLevel,
                             const size_t* fileSizes, U32 nbFiles,
                             const void* dictBuffer, size_t dictBufferSize,
    -                        ZSTD_compressionParameters *comprParams)
    +                        const ZSTD_compressionParameters* comprParams)
     {
         size_t const blockSize = ((g_blockSize>=32 && !g_decodeOnly) ? g_blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ;
    -    size_t const avgSize = MIN(g_blockSize, (srcSize / nbFiles));
    +    size_t const avgSize = MIN(blockSize, (srcSize / nbFiles));
         U32 const maxNbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize) + nbFiles;
         blockParam_t* const blockTable = (blockParam_t*) malloc(maxNbBlocks * sizeof(blockParam_t));
         size_t const maxCompressedSize = ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024);   /* add some room for safety */
    @@ -176,22 +179,21 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
             EXM_THROW(31, "allocation error : not enough memory");
     
         /* init */
    -    if (strlen(displayName)>17) displayName += strlen(displayName)-17;   /* can only display 17 characters */
    +    if (strlen(displayName)>17) displayName += strlen(displayName)-17;   /* display last 17 characters */
         UTIL_initTimer(&ticksPerSecond);
     
    -    if (g_decodeOnly) {
    -        const char* srcPtr = (const char*) srcBuffer;
    -        U64 dSize64 = 0;
    +    if (g_decodeOnly) {  /* benchmark only decompression : source must be already compressed */
    +        const char* srcPtr = (const char*)srcBuffer;
    +        U64 totalDSize64 = 0;
             U32 fileNb;
             for (fileNb=0; fileNb decodedSize) EXM_THROW(32, "original size is too large");
    -            if (decodedSize==0) EXM_THROW(32, "Impossible to determine original size ");
    +        {   size_t const decodedSize = (size_t)totalDSize64;
    +            if (totalDSize64 > decodedSize) EXM_THROW(32, "original size is too large");   /* size_t overflow */
                 free(resultBuffer);
                 resultBuffer = malloc(decodedSize);
                 if (!resultBuffer) EXM_THROW(33, "not enough memory");
    @@ -260,12 +262,11 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
                     UTIL_getTime(&clockStart);
     
                     if (!cCompleted) {   /* still some time to do compression tests */
    -                    ZSTD_parameters zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize);
                         ZSTD_customMem const cmem = { NULL, NULL, NULL };
    -                    U64 clockLoop = g_nbSeconds ? TIMELOOP_MICROSEC : 1;
    +                    U64 const clockLoop = g_nbSeconds ? TIMELOOP_MICROSEC : 1;
                         U32 nbLoops = 0;
    -                    ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, 1, zparams, cmem);
    -                    if (cdict==NULL) EXM_THROW(1, "ZSTD_createCDict_advanced() allocation failure");
    +                    ZSTD_parameters zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize);
    +                    ZSTD_CDict* cdict;
                         if (comprParams->windowLog) zparams.cParams.windowLog = comprParams->windowLog;
                         if (comprParams->chainLog) zparams.cParams.chainLog = comprParams->chainLog;
                         if (comprParams->hashLog) zparams.cParams.hashLog = comprParams->hashLog;
    @@ -273,6 +274,8 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
                         if (comprParams->searchLength) zparams.cParams.searchLength = comprParams->searchLength;
                         if (comprParams->targetLength) zparams.cParams.targetLength = comprParams->targetLength;
                         if (comprParams->strategy) zparams.cParams.strategy = (ZSTD_strategy)(comprParams->strategy - 1);
    +                    cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, 1, zparams.cParams, cmem);
    +                    if (cdict==NULL) EXM_THROW(1, "ZSTD_createCDict_advanced() allocation failure");
                         do {
                             U32 blockNb;
                             size_t rSize;
    diff --git a/programs/dibio.c b/programs/dibio.c
    index 5ef202c8abad..aac36425cf75 100644
    --- a/programs/dibio.c
    +++ b/programs/dibio.c
    @@ -53,12 +53,12 @@ static const size_t maxMemory = (sizeof(size_t) == 4) ? (2 GB - 64 MB) : ((size_
     ***************************************/
     #define DISPLAY(...)         fprintf(stderr, __VA_ARGS__)
     #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 */
    +static int g_displayLevel = 0;   /* 0 : no display;   1: errors;   2: default;  4: full information */
     
     #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
                 if ((DIB_clockSpan(g_time) > refreshRate) || (g_displayLevel>=4)) \
                 { g_time = clock(); DISPLAY(__VA_ARGS__); \
    -            if (g_displayLevel>=4) fflush(stdout); } }
    +            if (g_displayLevel>=4) fflush(stderr); } }
     static const clock_t refreshRate = CLOCKS_PER_SEC * 2 / 10;
     static clock_t g_time = 0;
     
    @@ -89,7 +89,8 @@ unsigned DiB_isError(size_t errorCode) { return ERR_isError(errorCode); }
     
     const char* DiB_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
     
    -#define MIN(a,b)   ( (a) < (b) ? (a) : (b) )
    +#undef MIN
    +#define MIN(a,b)    ((a) < (b) ? (a) : (b))
     
     
     /* ********************************************************
    diff --git a/programs/fileio.c b/programs/fileio.c
    index e6481f1fa726..e188936b21f5 100644
    --- a/programs/fileio.c
    +++ b/programs/fileio.c
    @@ -31,6 +31,11 @@
     #include        /* clock */
     #include       /* errno */
     
    +#if defined (_MSC_VER)
    +#  include 
    +#  include 
    +#endif
    +
     #include "mem.h"
     #include "fileio.h"
     #define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */
    @@ -48,6 +53,12 @@
     #  include 
     #endif
     
    +#define LZ4_MAGICNUMBER 0x184D2204
    +#if defined(ZSTD_LZ4COMPRESS) || defined(ZSTD_LZ4DECOMPRESS)
    +#  include 
    +#  include 
    +#endif
    +
     
     /*-*************************************
     *  Constants
    @@ -71,7 +82,7 @@
     
     #define CACHELINE 64
     
    -#define MAX_DICT_SIZE (8 MB)   /* protection against large input (attack scenario) */
    +#define DICTSIZE_MAX (32 MB)   /* protection against large input (attack scenario) */
     
     #define FNSPACE 30
     
    @@ -81,18 +92,20 @@
     ***************************************/
     #define DISPLAY(...)         fprintf(stderr, __VA_ARGS__)
     #define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
    -static U32 g_displayLevel = 2;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */
    +static int g_displayLevel = 2;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */
     void FIO_setNotificationLevel(unsigned level) { g_displayLevel=level; }
     
     #define DISPLAYUPDATE(l, ...) { if (g_displayLevel>=l) { \
                 if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \
                 { g_time = clock(); DISPLAY(__VA_ARGS__); \
    -            if (g_displayLevel>=4) fflush(stdout); } } }
    +            if (g_displayLevel>=4) fflush(stderr); } } }
     static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
     static clock_t g_time = 0;
     
    +#undef MIN
     #define MIN(a,b)    ((a) < (b) ? (a) : (b))
     
    +
     /* ************************************************************
     * Avoid fseek()'s 2GiB barrier with MSVC, MacOS, *BSD, MinGW
     ***************************************************************/
    @@ -188,6 +201,18 @@ void FIO_setOverlapLog(unsigned overlapLog){
     /*-*************************************
     *  Functions
     ***************************************/
    +/** FIO_remove() :
    + * @result : Unlink `fileName`, even if it's read-only */
    +static int FIO_remove(const char* path)
    +{
    +#if defined(_WIN32) || defined(WIN32)
    +    /* windows doesn't allow remove read-only files, so try to make it
    +     * writable first */
    +    chmod(path, _S_IWRITE);
    +#endif
    +    return remove(path);
    +}
    +
     /** FIO_openSrcFile() :
      * condition : `dstFileName` must be non-NULL.
      * @result : FILE* to `dstFileName`, or NULL if it fails */
    @@ -227,23 +252,32 @@ static FILE* FIO_openDstFile(const char* dstFileName)
                 DISPLAYLEVEL(4, "Sparse File Support is automatically disabled on stdout ; try --sparse \n");
             }
         } else {
    -        if (!g_overwrite && strcmp (dstFileName, nulmark)) {  /* Check if destination file already exists */
    +        if (g_sparseFileSupport == 1) {
    +            g_sparseFileSupport = ZSTD_SPARSE_DEFAULT;
    +        }
    +        if (strcmp (dstFileName, nulmark)) {  /* Check if destination file already exists */
                 f = fopen( dstFileName, "rb" );
                 if (f != 0) {  /* dest file exists, prompt for overwrite authorization */
                     fclose(f);
    -                if (g_displayLevel <= 1) {
    -                    /* No interaction possible */
    -                    DISPLAY("zstd: %s already exists; not overwritten  \n", dstFileName);
    -                    return NULL;
    -                }
    -                DISPLAY("zstd: %s already exists; do you wish to overwrite (y/N) ? ", dstFileName);
    -                {   int ch = getchar();
    -                    if ((ch!='Y') && (ch!='y')) {
    -                        DISPLAY("    not overwritten  \n");
    +                if (!g_overwrite) {
    +                    if (g_displayLevel <= 1) {
    +                        /* No interaction possible */
    +                        DISPLAY("zstd: %s already exists; not overwritten  \n", dstFileName);
                             return NULL;
                         }
    -                    while ((ch!=EOF) && (ch!='\n')) ch = getchar();  /* flush rest of input line */
    -        }   }   }
    +                    DISPLAY("zstd: %s already exists; do you wish to overwrite (y/N) ? ", dstFileName);
    +                    {   int ch = getchar();
    +                        if ((ch!='Y') && (ch!='y')) {
    +                            DISPLAY("    not overwritten  \n");
    +                            return NULL;
    +                        }
    +                        while ((ch!=EOF) && (ch!='\n')) ch = getchar();  /* flush rest of input line */
    +                    }
    +                }
    +
    +                /* need to unlink */
    +                FIO_remove(dstFileName);
    +        }   }
             f = fopen( dstFileName, "wb" );
             if (f==NULL) DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno));
         }
    @@ -252,13 +286,13 @@ static FILE* FIO_openDstFile(const char* dstFileName)
     }
     
     
    -/*! FIO_loadFile() :
    -*   creates a buffer, pointed by `*bufferPtr`,
    -*   loads `filename` content into it,
    -*   up to MAX_DICT_SIZE bytes.
    -*   @return : loaded size
    -*/
    -static size_t FIO_loadFile(void** bufferPtr, const char* fileName)
    +/*! FIO_createDictBuffer() :
    + *  creates a buffer, pointed by `*bufferPtr`,
    + *  loads `filename` content into it, up to DICTSIZE_MAX bytes.
    + *  @return : loaded size
    + *  if fileName==NULL, returns 0 and a NULL pointer
    + */
    +static size_t FIO_createDictBuffer(void** bufferPtr, const char* fileName)
     {
         FILE* fileHandle;
         U64 fileSize;
    @@ -270,14 +304,7 @@ static size_t FIO_loadFile(void** bufferPtr, const char* fileName)
         fileHandle = fopen(fileName, "rb");
         if (fileHandle==0) EXM_THROW(31, "zstd: %s: %s", fileName, strerror(errno));
         fileSize = UTIL_getFileSize(fileName);
    -    if (fileSize > MAX_DICT_SIZE) {
    -        int seekResult;
    -        if (fileSize > 1 GB) EXM_THROW(32, "Dictionary file %s is too large", fileName);   /* avoid extreme cases */
    -        DISPLAYLEVEL(2,"Dictionary %s is too large : using last %u bytes only \n", fileName, (U32)MAX_DICT_SIZE);
    -        seekResult = fseek(fileHandle, (long int)(fileSize-MAX_DICT_SIZE), SEEK_SET);   /* use end of file */
    -        if (seekResult != 0) EXM_THROW(33, "zstd: %s: %s", fileName, strerror(errno));
    -        fileSize = MAX_DICT_SIZE;
    -    }
    +    if (fileSize > DICTSIZE_MAX) EXM_THROW(32, "Dictionary file %s is too large (> %u MB)", fileName, DICTSIZE_MAX >> 20);   /* avoid extreme cases */
         *bufferPtr = malloc((size_t)fileSize);
         if (*bufferPtr==NULL) EXM_THROW(34, "zstd: %s", strerror(errno));
         { size_t const readSize = fread(*bufferPtr, 1, (size_t)fileSize, fileHandle);
    @@ -330,7 +357,7 @@ static cRess_t FIO_createCResources(const char* dictFileName, int cLevel,
     
         /* dictionary */
         {   void* dictBuffer;
    -        size_t const dictBuffSize = FIO_loadFile(&dictBuffer, dictFileName);
    +        size_t const dictBuffSize = FIO_createDictBuffer(&dictBuffer, dictFileName);   /* works with dictFileName==NULL */
             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 = srcRegFile;
    @@ -342,7 +369,7 @@ static cRess_t FIO_createCResources(const char* dictFileName, int cLevel,
                 if (comprParams->searchLog) params.cParams.searchLog = comprParams->searchLog;
                 if (comprParams->searchLength) params.cParams.searchLength = comprParams->searchLength;
                 if (comprParams->targetLength) params.cParams.targetLength = comprParams->targetLength;
    -            if (comprParams->strategy) params.cParams.strategy = (ZSTD_strategy)(comprParams->strategy - 1);
    +            if (comprParams->strategy) params.cParams.strategy = (ZSTD_strategy)(comprParams->strategy - 1);   /* 0 means : do not change */
     #ifdef ZSTD_MULTITHREAD
                 {   size_t const errorCode = ZSTDMT_initCStream_advanced(ress.cctx, dictBuffer, dictBuffSize, params, srcSize);
                     if (ZSTD_isError(errorCode)) EXM_THROW(33, "Error initializing CStream : %s", ZSTD_getErrorName(errorCode));
    @@ -494,6 +521,84 @@ static unsigned long long FIO_compressLzmaFrame(cRess_t* ress, const char* srcFi
     }
     #endif
     
    +#ifdef ZSTD_LZ4COMPRESS
    +static int FIO_LZ4_GetBlockSize_FromBlockId (int id) { return (1 << (8 + (2 * id))); }
    +static unsigned long long FIO_compressLz4Frame(cRess_t* ress, const char* srcFileName, U64 const srcFileSize, int compressionLevel, U64* readsize)
    +{
    +    unsigned long long inFileSize = 0, outFileSize = 0;
    +
    +    LZ4F_preferences_t prefs;
    +    LZ4F_compressionContext_t ctx;
    +
    +    LZ4F_errorCode_t const errorCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
    +    if (LZ4F_isError(errorCode)) EXM_THROW(31, "zstd: failed to create lz4 compression context");
    +
    +    memset(&prefs, 0, sizeof(prefs));
    +
    +#if LZ4_VERSION_NUMBER <= 10600
    +#define LZ4F_blockIndependent blockIndependent
    +#define LZ4F_max4MB max4MB
    +#endif
    +
    +    prefs.autoFlush = 1;
    +    prefs.compressionLevel = compressionLevel;
    +    prefs.frameInfo.blockMode = LZ4F_blockIndependent; /* stick to defaults for lz4 cli */
    +    prefs.frameInfo.blockSizeID = LZ4F_max4MB;
    +    prefs.frameInfo.contentChecksumFlag = (contentChecksum_t)g_checksumFlag;
    +#if LZ4_VERSION_NUMBER >= 10600
    +    prefs.frameInfo.contentSize = srcFileSize;
    +#endif
    +
    +    {
    +        size_t blockSize = FIO_LZ4_GetBlockSize_FromBlockId(LZ4F_max4MB);
    +        size_t readSize;
    +        size_t headerSize = LZ4F_compressBegin(ctx, ress->dstBuffer, ress->dstBufferSize, &prefs);
    +        if (LZ4F_isError(headerSize)) EXM_THROW(33, "File header generation failed : %s", LZ4F_getErrorName(headerSize));
    +        { size_t const sizeCheck = fwrite(ress->dstBuffer, 1, headerSize, ress->dstFile);
    +          if (sizeCheck!=headerSize) EXM_THROW(34, "Write error : cannot write header"); }
    +        outFileSize += headerSize;
    +
    +        /* Read first block */
    +        readSize  = fread(ress->srcBuffer, (size_t)1, (size_t)blockSize, ress->srcFile);
    +        inFileSize += readSize;
    +
    +        /* Main Loop */
    +        while (readSize>0) {
    +            size_t outSize;
    +
    +            /* Compress Block */
    +            outSize = LZ4F_compressUpdate(ctx, ress->dstBuffer, ress->dstBufferSize, ress->srcBuffer, readSize, NULL);
    +            if (LZ4F_isError(outSize)) EXM_THROW(35, "zstd: %s: lz4 compression failed : %s", srcFileName, LZ4F_getErrorName(outSize));
    +            outFileSize += outSize;
    +            if (!srcFileSize) DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%%", (U32)(inFileSize>>20), (double)outFileSize/inFileSize*100)
    +            else DISPLAYUPDATE(2, "\rRead : %u / %u MB ==> %.2f%%", (U32)(inFileSize>>20), (U32)(srcFileSize>>20), (double)outFileSize/inFileSize*100);
    +
    +            /* Write Block */
    +            { size_t const sizeCheck = fwrite(ress->dstBuffer, 1, outSize, ress->dstFile);
    +              if (sizeCheck!=outSize) EXM_THROW(36, "Write error : cannot write compressed block"); }
    +
    +            /* Read next block */
    +            readSize  = fread(ress->srcBuffer, (size_t)1, (size_t)blockSize, ress->srcFile);
    +            inFileSize += readSize;
    +        }
    +        if (ferror(ress->srcFile)) EXM_THROW(37, "Error reading %s ", srcFileName);
    +
    +        /* End of Stream mark */
    +        headerSize = LZ4F_compressEnd(ctx, ress->dstBuffer, ress->dstBufferSize, NULL);
    +        if (LZ4F_isError(headerSize)) EXM_THROW(38, "zstd: %s: lz4 end of file generation failed : %s", srcFileName, LZ4F_getErrorName(headerSize));
    +
    +        { size_t const sizeCheck = fwrite(ress->dstBuffer, 1, headerSize, ress->dstFile);
    +          if (sizeCheck!=headerSize) EXM_THROW(39, "Write error : cannot write end of stream"); }
    +        outFileSize += headerSize;
    +    }
    +
    +    *readsize = inFileSize;
    +    LZ4F_freeCompressionContext(ctx);
    +
    +    return outFileSize;
    +}
    +#endif
    +
     
     /*! FIO_compressFilename_internal() :
      *  same as FIO_compressFilename_extRess(), with `ress.desFile` already opened.
    @@ -512,6 +617,7 @@ static int FIO_compressFilename_internal(cRess_t ress,
         switch (g_compressionType) {
             case FIO_zstdCompression:
                 break;
    +
             case FIO_gzipCompression:
     #ifdef ZSTD_GZCOMPRESS
                 compressedfilesize = FIO_compressGzFrame(&ress, srcFileName, fileSize, compressionLevel, &readsize);
    @@ -520,6 +626,7 @@ static int FIO_compressFilename_internal(cRess_t ress,
                 EXM_THROW(20, "zstd: %s: file cannot be compressed as gzip (zstd compiled without ZSTD_GZCOMPRESS) -- ignored \n", srcFileName);
     #endif
                 goto finish;
    +
             case FIO_xzCompression:
             case FIO_lzmaCompression:
     #ifdef ZSTD_LZMACOMPRESS
    @@ -527,6 +634,15 @@ static int FIO_compressFilename_internal(cRess_t ress,
     #else
                 (void)compressionLevel;
                 EXM_THROW(20, "zstd: %s: file cannot be compressed as xz/lzma (zstd compiled without ZSTD_LZMACOMPRESS) -- ignored \n", srcFileName);
    +#endif
    +            goto finish;
    +
    +        case FIO_lz4Compression:
    +#ifdef ZSTD_LZ4COMPRESS
    +            compressedfilesize = FIO_compressLz4Frame(&ress, srcFileName, fileSize, compressionLevel, &readsize);
    +#else
    +            (void)compressionLevel;
    +            EXM_THROW(20, "zstd: %s: file cannot be compressed as lz4 (zstd compiled without ZSTD_LZ4COMPRESS) -- ignored \n", srcFileName);
     #endif
                 goto finish;
         }
    @@ -548,8 +664,8 @@ static int FIO_compressFilename_internal(cRess_t ress,
             readsize += inSize;
     
             {   ZSTD_inBuffer  inBuff = { ress.srcBuffer, inSize, 0 };
    -            while (inBuff.pos != inBuff.size) {   /* note : is there any possibility of endless loop ? for example, if outBuff is not large enough ? */
    -                ZSTD_outBuffer outBuff= { ress.dstBuffer, ress.dstBufferSize, 0 };
    +            while (inBuff.pos != inBuff.size) {
    +                ZSTD_outBuffer outBuff = { ress.dstBuffer, ress.dstBufferSize, 0 };
     #ifdef ZSTD_MULTITHREAD
                     size_t const result = ZSTDMT_compressStream(ress.cctx, &outBuff, &inBuff);
     #else
    @@ -563,13 +679,13 @@ static int FIO_compressFilename_internal(cRess_t ress,
                         if (sizeCheck!=outBuff.pos) EXM_THROW(25, "Write error : cannot write compressed block into %s", dstFileName);
                         compressedfilesize += outBuff.pos;
             }   }   }
    -#ifdef ZSTD_MULTITHREAD
    -        if (!fileSize) DISPLAYUPDATE(2, "\rRead : %u MB", (U32)(readsize>>20))
    -        else DISPLAYUPDATE(2, "\rRead : %u / %u MB", (U32)(readsize>>20), (U32)(fileSize>>20));
    -#else
    -        if (!fileSize) DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%%", (U32)(readsize>>20), (double)compressedfilesize/readsize*100)
    -        else DISPLAYUPDATE(2, "\rRead : %u / %u MB ==> %.2f%%", (U32)(readsize>>20), (U32)(fileSize>>20), (double)compressedfilesize/readsize*100);
    -#endif
    +        if (g_nbThreads > 1) {
    +            if (!fileSize) DISPLAYUPDATE(2, "\rRead : %u MB", (U32)(readsize>>20))
    +            else DISPLAYUPDATE(2, "\rRead : %u / %u MB", (U32)(readsize>>20), (U32)(fileSize>>20));
    +        } else {
    +            if (!fileSize) DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%%", (U32)(readsize>>20), (double)compressedfilesize/readsize*100)
    +            else DISPLAYUPDATE(2, "\rRead : %u / %u MB ==> %.2f%%", (U32)(readsize>>20), (U32)(fileSize>>20), (double)compressedfilesize/readsize*100);
    +        }
         }
     
         /* End of Frame */
    @@ -750,7 +866,7 @@ static dRess_t FIO_createDResources(const char* dictFileName)
     
         /* dictionary */
         {   void* dictBuffer;
    -        size_t const dictBufferSize = FIO_loadFile(&dictBuffer, dictFileName);
    +        size_t const dictBufferSize = FIO_createDictBuffer(&dictBuffer, dictFileName);
             size_t const initError = ZSTD_initDStream_usingDict(ress.dctx, dictBuffer, dictBufferSize);
             if (ZSTD_isError(initError)) EXM_THROW(61, "ZSTD_initDStream_usingDict error : %s", ZSTD_getErrorName(initError));
             free(dictBuffer);
    @@ -1019,6 +1135,66 @@ static unsigned long long FIO_decompressLzmaFrame(dRess_t* ress, FILE* srcFile,
     }
     #endif
     
    +#ifdef ZSTD_LZ4DECOMPRESS
    +static unsigned long long FIO_decompressLz4Frame(dRess_t* ress, FILE* srcFile, const char* srcFileName)
    +{
    +    unsigned long long filesize = 0;
    +    LZ4F_errorCode_t nextToLoad;
    +    LZ4F_decompressionContext_t dCtx;
    +    LZ4F_errorCode_t const errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
    +
    +    if (LZ4F_isError(errorCode)) EXM_THROW(61, "zstd: failed to create lz4 decompression context");
    +
    +    /* Init feed with magic number (already consumed from FILE* sFile) */
    +    {   size_t inSize = 4;
    +        size_t outSize= 0;
    +        MEM_writeLE32(ress->srcBuffer, LZ4_MAGICNUMBER);
    +        nextToLoad = LZ4F_decompress(dCtx, ress->dstBuffer, &outSize, ress->srcBuffer, &inSize, NULL);
    +        if (LZ4F_isError(nextToLoad)) EXM_THROW(62, "zstd: %s: lz4 header error : %s", srcFileName, LZ4F_getErrorName(nextToLoad));
    +    }
    +
    +    /* Main Loop */
    +    for (;nextToLoad;) {
    +        size_t readSize;
    +        size_t pos = 0;
    +        size_t decodedBytes = ress->dstBufferSize;
    +
    +        /* Read input */
    +        if (nextToLoad > ress->srcBufferSize) nextToLoad = ress->srcBufferSize;
    +        readSize = fread(ress->srcBuffer, 1, nextToLoad, srcFile);
    +        if (!readSize) break;   /* reached end of file or stream */
    +
    +        while ((pos < readSize) || (decodedBytes == ress->dstBufferSize)) {  /* still to read, or still to flush */
    +            /* Decode Input (at least partially) */
    +            size_t remaining = readSize - pos;
    +            decodedBytes = ress->dstBufferSize;
    +            nextToLoad = LZ4F_decompress(dCtx, ress->dstBuffer, &decodedBytes, (char*)(ress->srcBuffer)+pos, &remaining, NULL);
    +            if (LZ4F_isError(nextToLoad)) EXM_THROW(66, "zstd: %s: decompression error : %s", srcFileName, LZ4F_getErrorName(nextToLoad));
    +            pos += remaining;
    +
    +            /* Write Block */
    +            if (decodedBytes) {
    +                if (fwrite(ress->dstBuffer, 1, decodedBytes, ress->dstFile) != decodedBytes) EXM_THROW(63, "Write error : cannot write to output file");
    +                filesize += decodedBytes;
    +                DISPLAYUPDATE(2, "\rDecompressed : %u MB  ", (unsigned)(filesize>>20));
    +            }
    +
    +            if (!nextToLoad) break;
    +        }
    +    }
    +    /* can be out because readSize == 0, which could be an fread() error */
    +    if (ferror(srcFile)) EXM_THROW(67, "zstd: %s: read error", srcFileName);
    +
    +    if (nextToLoad!=0) EXM_THROW(68, "zstd: %s: unfinished stream", srcFileName);
    +
    +    LZ4F_freeDecompressionContext(dCtx);
    +    ress->srcBufferLoaded = 0; /* LZ4F will go to the frame boundary */
    +
    +    return filesize;
    +}
    +#endif
    +
    +
     
     /** FIO_decompressSrcFile() :
         Decompression `srcFileName` into `ress.dstFile`
    @@ -1070,6 +1246,15 @@ static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const ch
     #else
                 DISPLAYLEVEL(1, "zstd: %s: xz/lzma file cannot be uncompressed (zstd compiled without ZSTD_LZMADECOMPRESS) -- ignored \n", srcFileName);
                 return 1;
    +#endif
    +        } else if (MEM_readLE32(buf) == LZ4_MAGICNUMBER) {
    +#ifdef ZSTD_LZ4DECOMPRESS
    +            unsigned long long const result = FIO_decompressLz4Frame(&ress, srcFile, srcFileName);
    +            if (result == 0) return 1;
    +            filesize += result;
    +#else
    +            DISPLAYLEVEL(1, "zstd: %s: lz4 file cannot be uncompressed (zstd compiled without ZSTD_LZ4DECOMPRESS) -- ignored \n", srcFileName);
    +            return 1;
     #endif
             } else {
                 if (!ZSTD_isFrame(ress.srcBuffer, toRead)) {
    @@ -1179,7 +1364,7 @@ int FIO_decompressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles
                     dstFileName = (char*)malloc(dfnSize);
                     if (dstFileName==NULL) EXM_THROW(74, "not enough memory for dstFileName");
                 }
    -            if (sfnSize <= suffixSize || (strcmp(suffixPtr, GZ_EXTENSION) && strcmp(suffixPtr, XZ_EXTENSION) && strcmp(suffixPtr, ZSTD_EXTENSION) && strcmp(suffixPtr, LZMA_EXTENSION))) {
    +            if (sfnSize <= suffixSize || (strcmp(suffixPtr, GZ_EXTENSION) && strcmp(suffixPtr, XZ_EXTENSION) && strcmp(suffixPtr, ZSTD_EXTENSION) && strcmp(suffixPtr, LZMA_EXTENSION) && strcmp(suffixPtr, LZ4_EXTENSION))) {
                     DISPLAYLEVEL(1, "zstd: %s: unknown suffix (%s/%s/%s/%s expected) -- ignored \n", srcFileName, GZ_EXTENSION, XZ_EXTENSION, ZSTD_EXTENSION, LZMA_EXTENSION);
                     skippedFiles++;
                     continue;
    diff --git a/programs/fileio.h b/programs/fileio.h
    index 0dd58d625d44..65da98d7fa88 100644
    --- a/programs/fileio.h
    +++ b/programs/fileio.h
    @@ -33,12 +33,13 @@ extern "C" {
     #define XZ_EXTENSION    ".xz"
     #define GZ_EXTENSION    ".gz"
     #define ZSTD_EXTENSION  ".zst"
    +#define LZ4_EXTENSION   ".lz4"
     
     
     /*-*************************************
     *  Types
     ***************************************/
    -typedef enum { FIO_zstdCompression, FIO_gzipCompression, FIO_xzCompression, FIO_lzmaCompression } FIO_compressionType_t;
    +typedef enum { FIO_zstdCompression, FIO_gzipCompression, FIO_xzCompression, FIO_lzmaCompression, FIO_lz4Compression } FIO_compressionType_t;
     
     
     /*-*************************************
    diff --git a/programs/platform.h b/programs/platform.h
    index 89a9f6cd42a0..74412cde332e 100644
    --- a/programs/platform.h
    +++ b/programs/platform.h
    @@ -100,9 +100,18 @@ extern "C" {
     #if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 1)) || (PLATFORM_POSIX_VERSION >= 200112L) || defined(__DJGPP__)
     #  include    /* isatty */
     #  define IS_CONSOLE(stdStream) isatty(fileno(stdStream))
    -#elif defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
    +#elif defined(MSDOS) || defined(OS2) || defined(__CYGWIN__)
     #  include        /* _isatty */
     #  define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
    +#elif defined(WIN32) || defined(_WIN32)
    +#  include       /* _isatty */
    +#  include  /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
    +#  include    /* FILE */
    +static __inline int IS_CONSOLE(FILE* stdStream)
    +{
    +    DWORD dummy;
    +    return _isatty(_fileno(stdStream)) && GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdStream)), &dummy);
    +}
     #else
     #  define IS_CONSOLE(stdStream) 0
     #endif
    @@ -129,6 +138,14 @@ extern "C" {
     #endif
     
     
    +#ifndef ZSTD_SPARSE_DEFAULT
    +#  if (defined(__APPLE__) && defined(__MACH__))
    +#    define ZSTD_SPARSE_DEFAULT 0
    +#  else
    +#    define ZSTD_SPARSE_DEFAULT 1
    +#  endif
    +#endif
    +
     
     #if defined (__cplusplus)
     }
    diff --git a/programs/util.h b/programs/util.h
    index 59e19d027ccd..5f437b2b268c 100644
    --- a/programs/util.h
    +++ b/programs/util.h
    @@ -1,6 +1,6 @@
     /**
      * util.h - utility functions
    - * 
    + *
      * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
      * All rights reserved.
      *
    @@ -25,6 +25,7 @@ extern "C" {
     #include        /* malloc */
     #include        /* size_t, ptrdiff_t */
     #include         /* fprintf */
    +#include        /* strncmp */
     #include     /* stat, utime */
     #include      /* stat */
     #if defined(_MSC_VER)
    @@ -166,8 +167,8 @@ UTIL_STATIC void UTIL_waitForNextTick(UTIL_freq_t ticksPerSecond)
     *  File functions
     ******************************************/
     #if defined(_MSC_VER)
    -	#define chmod _chmod
    -	typedef struct __stat64 stat_t;
    +    #define chmod _chmod
    +    typedef struct __stat64 stat_t;
     #else
         typedef struct stat stat_t;
     #endif
    @@ -178,9 +179,9 @@ UTIL_STATIC int UTIL_setFileStat(const char *filename, stat_t *statbuf)
         int res = 0;
         struct utimbuf timebuf;
     
    -	timebuf.actime = time(NULL);
    -	timebuf.modtime = statbuf->st_mtime;
    -	res += utime(filename, &timebuf);  /* set access and modification times */
    +    timebuf.actime = time(NULL);
    +    timebuf.modtime = statbuf->st_mtime;
    +    res += utime(filename, &timebuf);  /* set access and modification times */
     
     #if !defined(_WIN32)
         res += chown(filename, statbuf->st_uid, statbuf->st_gid);  /* Copy ownership */
    @@ -228,6 +229,20 @@ UTIL_STATIC U32 UTIL_isDirectory(const char* infilename)
         return 0;
     }
     
    +UTIL_STATIC U32 UTIL_isLink(const char* infilename)
    +{
    +#if defined(_WIN32)
    +    /* no symlinks on windows */
    +    (void)infilename;
    +#else
    +    int r;
    +    stat_t statbuf;
    +    r = lstat(infilename, &statbuf);
    +    if (!r && S_ISLNK(statbuf.st_mode)) return 1;
    +#endif
    +    return 0;
    +}
    +
     
     UTIL_STATIC U64 UTIL_getFileSize(const char* infilename)
     {
    @@ -271,11 +286,14 @@ UTIL_STATIC void *UTIL_realloc(void *ptr, size_t size)
         return NULL;
     }
     
    +static int g_utilDisplayLevel;
    +#define UTIL_DISPLAY(...)         fprintf(stderr, __VA_ARGS__)
    +#define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } }
     
     #ifdef _WIN32
     #  define UTIL_HAS_CREATEFILELIST
     
    -UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd)
    +UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
     {
         char* path;
         int dirLength, fnameLength, pathLength, nbFiles = 0;
    @@ -311,7 +329,7 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
                 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. */
    +            nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks);  /* Recursively call "UTIL_prepareFileList" with the new path. */
                 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)) {
    @@ -339,7 +357,7 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
     #  include        /* opendir, readdir */
     #  include        /* strerror, memcpy */
     
    -UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd)
    +UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
     {
         DIR *dir;
         struct dirent *entry;
    @@ -360,13 +378,19 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
             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 (!followLinks && UTIL_isLink(path)) {
    +            UTIL_DISPLAYLEVEL(2, "Warning : %s is a symbolic link, ignoring\n", path);
    +            continue;
    +        }
    +
             if (UTIL_isDirectory(path)) {
    -            nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd);  /* Recursively call "UTIL_prepareFileList" with the new path. */
    +            nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks);  /* Recursively call "UTIL_prepareFileList" with the new path. */
                 if (*bufStart == NULL) { free(path); closedir(dir); return 0; }
             } else {
                 if (*bufStart + *pos + pathLength >= *bufEnd) {
    @@ -396,7 +420,7 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
     
     #else
     
    -UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd)
    +UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
     {
         (void)bufStart; (void)bufEnd; (void)pos;
         fprintf(stderr, "Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName);
    @@ -411,7 +435,7 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
      * After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)
      * In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.
      */
    -UTIL_STATIC const char** UTIL_createFileList(const char **inputNames, unsigned inputNamesNb, char** allocatedBuffer, unsigned* allocatedNamesNb)
    +UTIL_STATIC const char** UTIL_createFileList(const char **inputNames, unsigned inputNamesNb, char** allocatedBuffer, unsigned* allocatedNamesNb, int followLinks)
     {
         size_t pos;
         unsigned i, nbFiles;
    @@ -436,7 +460,7 @@ UTIL_STATIC const char** UTIL_createFileList(const char **inputNames, unsigned i
                     nbFiles++;
                 }
             } else {
    -            nbFiles += UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend);
    +            nbFiles += UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend, followLinks);
                 if (buf == NULL) return NULL;
         }   }
     
    @@ -465,6 +489,201 @@ UTIL_STATIC void UTIL_freeFileList(const char** filenameTable, char* allocatedBu
         if (filenameTable) free((void*)filenameTable);
     }
     
    +/* count the number of physical cores */
    +#if defined(_WIN32) || defined(WIN32)
    +
    +#include 
    +
    +typedef BOOL(WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
    +
    +UTIL_STATIC int UTIL_countPhysicalCores(void)
    +{
    +    static int numPhysicalCores = 0;
    +    if (numPhysicalCores != 0) return numPhysicalCores;
    +
    +    {   LPFN_GLPI glpi;
    +        BOOL done = FALSE;
    +        PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
    +        PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
    +        DWORD returnLength = 0;
    +        size_t byteOffset = 0;
    +
    +        glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")),
    +                                         "GetLogicalProcessorInformation");
    +
    +        if (glpi == NULL) {
    +            goto failed;
    +        }
    +
    +        while(!done) {
    +            DWORD rc = glpi(buffer, &returnLength);
    +            if (FALSE == rc) {
    +                if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    +                    if (buffer)
    +                        free(buffer);
    +                    buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength);
    +
    +                    if (buffer == NULL) {
    +                        perror("zstd");
    +                        exit(1);
    +                    }
    +                } else {
    +                    /* some other error */
    +                    goto failed;
    +                }
    +            } else {
    +                done = TRUE;
    +            }
    +        }
    +
    +        ptr = buffer;
    +
    +        while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) {
    +
    +            if (ptr->Relationship == RelationProcessorCore) {
    +                numPhysicalCores++;
    +            }
    +
    +            ptr++;
    +            byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
    +        }
    +
    +        free(buffer);
    +
    +        return numPhysicalCores;
    +    }
    +
    +failed:
    +    /* try to fall back on GetSystemInfo */
    +    {   SYSTEM_INFO sysinfo;
    +        GetSystemInfo(&sysinfo);
    +        numPhysicalCores = sysinfo.dwNumberOfProcessors;
    +        if (numPhysicalCores == 0) numPhysicalCores = 1; /* just in case */
    +    }
    +    return numPhysicalCores;
    +}
    +
    +#elif defined(__APPLE__)
    +
    +#include 
    +
    +/* Use apple-provided syscall
    + * see: man 3 sysctl */
    +UTIL_STATIC int UTIL_countPhysicalCores(void)
    +{
    +    static S32 numPhysicalCores = 0; /* apple specifies int32_t */
    +    if (numPhysicalCores != 0) return numPhysicalCores;
    +
    +    {   size_t size = sizeof(S32);
    +        int const ret = sysctlbyname("hw.physicalcpu", &numPhysicalCores, &size, NULL, 0);
    +        if (ret != 0) {
    +            if (errno == ENOENT) {
    +                /* entry not present, fall back on 1 */
    +                numPhysicalCores = 1;
    +            } else {
    +                perror("zstd: can't get number of physical cpus");
    +                exit(1);
    +            }
    +        }
    +
    +        return numPhysicalCores;
    +    }
    +}
    +
    +#elif defined(__linux__)
    +
    +/* parse /proc/cpuinfo
    + * siblings / cpu cores should give hyperthreading ratio
    + * otherwise fall back on sysconf */
    +UTIL_STATIC int UTIL_countPhysicalCores(void)
    +{
    +    static int numPhysicalCores = 0;
    +
    +    if (numPhysicalCores != 0) return numPhysicalCores;
    +
    +    numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
    +    if (numPhysicalCores == -1) {
    +        /* value not queryable, fall back on 1 */
    +        return numPhysicalCores = 1;
    +    }
    +
    +    /* try to determine if there's hyperthreading */
    +    {   FILE* const cpuinfo = fopen("/proc/cpuinfo", "r");
    +        size_t const BUF_SIZE = 80;
    +        char buff[BUF_SIZE];
    +
    +        int siblings = 0;
    +        int cpu_cores = 0;
    +        int ratio = 1;
    +
    +        if (cpuinfo == NULL) {
    +            /* fall back on the sysconf value */
    +            return numPhysicalCores;
    +        }
    +
    +        /* assume the cpu cores/siblings values will be constant across all
    +         * present processors */
    +        while (!feof(cpuinfo)) {
    +            if (fgets(buff, BUF_SIZE, cpuinfo) != NULL) {
    +                if (strncmp(buff, "siblings", 8) == 0) {
    +                    const char* const sep = strchr(buff, ':');
    +                    if (*sep == '\0') {
    +                        /* formatting was broken? */
    +                        goto failed;
    +                    }
    +
    +                    siblings = atoi(sep + 1);
    +                }
    +                if (strncmp(buff, "cpu cores", 9) == 0) {
    +                    const char* const sep = strchr(buff, ':');
    +                    if (*sep == '\0') {
    +                        /* formatting was broken? */
    +                        goto failed;
    +                    }
    +
    +                    cpu_cores = atoi(sep + 1);
    +                }
    +            } else if (ferror(cpuinfo)) {
    +                /* fall back on the sysconf value */
    +                goto failed;
    +            }
    +        }
    +        if (siblings && cpu_cores) {
    +            ratio = siblings / cpu_cores;
    +        }
    +failed:
    +        fclose(cpuinfo);
    +        return numPhysicalCores = numPhysicalCores / ratio;
    +    }
    +}
    +
    +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
    +
    +/* Use apple-provided syscall
    + * see: man 3 sysctl */
    +UTIL_STATIC int UTIL_countPhysicalCores(void)
    +{
    +    static int numPhysicalCores = 0;
    +
    +    if (numPhysicalCores != 0) return numPhysicalCores;
    +
    +    numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
    +    if (numPhysicalCores == -1) {
    +        /* value not queryable, fall back on 1 */
    +        return numPhysicalCores = 1;
    +    }
    +    return numPhysicalCores;
    +}
    +
    +#else
    +
    +UTIL_STATIC int UTIL_countPhysicalCores(void)
    +{
    +    /* assume 1 */
    +    return 1;
    +}
    +
    +#endif
     
     #if defined (__cplusplus)
     }
    diff --git a/programs/zstd.1 b/programs/zstd.1
    index 684fb868aa30..6cc5f7e9d2f6 100644
    --- a/programs/zstd.1
    +++ b/programs/zstd.1
    @@ -1,408 +1,334 @@
    -\"
    -\" zstd.1: This is a manual page for 'zstd' program. This file is part of the
    -\" zstd  project.
    -\" Author: Yann Collet
    -\"
    -
    -\" No hyphenation
    -.hy 0
    -.nr HY 0
    -
    -.TH zstd "1" "2015-08-22" "zstd" "User Commands"
    -.SH NAME
    -\fBzstd, unzstd, zstdcat\fR - Compress or decompress .zst files
    -
    -.SH SYNOPSIS
    -.TP 5
    -\fBzstd\fR [\fBOPTIONS\fR] [-|INPUT-FILE] [-o ]
    -.PP
    -.B unzstd
    -is equivalent to
    -.BR "zstd \-d"
    -.br
    -.B zstdcat
    -is equivalent to
    -.BR "zstd \-dcf"
    -.br
    -
    -.SH DESCRIPTION
    -.PP
    -\fBzstd\fR is a fast lossless compression algorithm
    -and data compression tool,
    -with command line syntax similar to \fB gzip (1) \fR and \fB xz (1) \fR .
    -It is based on the \fBLZ77\fR family, with further FSE & huff0 entropy stages.
    -\fBzstd\fR offers highly configurable compression speed,
    -with fast modes at > 200 MB/s per core,
    -and strong modes nearing lzma compression ratios.
    -It also features a very fast decoder, with speeds > 500 MB/s per core.
    -
    -\fBzstd\fR command line syntax is generally similar to gzip,
    -but features the following differences :
    - - Source files are preserved by default.
    -   It's possible to remove them automatically by using \fB--rm\fR command.
    - - When compressing a single file, \fBzstd\fR displays progress notifications and result summary by default.
    -   Use \fB-q\fR to turn them off
    -
    -.PP
    -.B zstd
    -compresses or decompresses each
    -.I file
    -according to the selected operation mode.
    -If no
    -.I files
    -are given or
    -.I file
    -is
    -.BR \- ,
    -.B zstd
    -reads from standard input and writes the processed data
    -to standard output.
    -.B zstd
    -will refuse (display an error and skip the
    -.IR file )
    -to write compressed data to standard output if it is a terminal.
    -Similarly,
    -.B zstd
    -will refuse to read compressed data
    -from standard input if it is a terminal.
    -
    -.PP
    -Unless
    -.B \-\-stdout
    -or
    -.B \-o
    -is specified,
    -.I files
    -are written to a new file whose name is derived from the source
    -.I file
    -name:
    -.IP \(bu 3
    -When compressing, the suffix
    -.B .zst
    -is appended to the source filename to get the target filename.
    -.IP \(bu 3
    -When decompressing, the
    -.B .zst
    -suffix is removed from the filename to get the target filename.
    -
    -.SS "Concatenation with .zst files"
    -It is possible to concatenate
    -.B .zst
    -files as is.
    -.B zstd
    -will decompress such files as if they were a single
    -.B .zst
    -file.
    -
    -
    -
    -.SH OPTIONS
    -
    +.
    +.TH "ZSTD" "1" "May 2017" "zstd 1.2.0" "User Commands"
    +.
    +.SH "NAME"
    +\fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files
    +.
    +.SH "SYNOPSIS"
    +\fBzstd\fR [\fIOPTIONS\fR] [\-|\fIINPUT\-FILE\fR] [\-o \fIOUTPUT\-FILE\fR]
    +.
    +.P
    +\fBzstdmt\fR is equivalent to \fBzstd \-T0\fR
    +.
    +.P
    +\fBunzstd\fR is equivalent to \fBzstd \-d\fR
    +.
    +.P
    +\fBzstdcat\fR is equivalent to \fBzstd \-dcf\fR
    +.
    +.SH "DESCRIPTION"
    +\fBzstd\fR is a fast lossless compression algorithm and data compression tool, with command line syntax similar to \fBgzip (1)\fR and \fBxz (1)\fR\. It is based on the \fBLZ77\fR family, with further FSE & huff0 entropy stages\. \fBzstd\fR offers highly configurable compression speed, with fast modes at > 200 MB/s per code, and strong modes nearing lzma compression ratios\. It also features a very fast decoder, with speeds > 500 MB/s per core\.
    +.
    +.P
    +\fBzstd\fR command line syntax is generally similar to gzip, but features the following differences :
    +.
    +.IP "\(bu" 4
    +Source files are preserved by default\. It\'s possible to remove them automatically by using the \fB\-\-rm\fR command\.
    +.
    +.IP "\(bu" 4
    +When compressing a single file, \fBzstd\fR displays progress notifications and result summary by default\. Use \fB\-q\fR to turn them off\.
    +.
    +.IP "\(bu" 4
    +\fBzstd\fR does not accept input from console, but it properly accepts \fBstdin\fR when it\'s not the console\.
    +.
    +.IP "\(bu" 4
    +\fBzstd\fR displays a short help page when command line is an error\. Use \fB\-q\fR to turn it off\.
    +.
    +.IP "" 0
    +.
    +.P
    +\fBzstd\fR compresses or decompresses each \fIfile\fR according to the selected operation mode\. If no \fIfiles\fR are given or \fIfile\fR is \fB\-\fR, \fBzstd\fR reads from standard input and writes the processed data to standard output\. \fBzstd\fR will refuse to write compressed data to standard output if it is a terminal : it will display an error message and skip the \fIfile\fR\. Similarly, \fBzstd\fR will refuse to read compressed data from standard input if it is a terminal\.
    +.
    +.P
    +Unless \fB\-\-stdout\fR or \fB\-o\fR is specified, \fIfiles\fR are written to a new file whose name is derived from the source \fIfile\fR name:
    +.
    +.IP "\(bu" 4
    +When compressing, the suffix \fB\.zst\fR is appended to the source filename to get the target filename\.
    +.
    +.IP "\(bu" 4
    +When decompressing, the \fB\.zst\fR suffix is removed from the source filename to get the target filename
    +.
    +.IP "" 0
    +.
    +.SS "Concatenation with \.zst files"
    +It is possible to concatenate \fB\.zst\fR files as is\. \fBzstd\fR will decompress such files as if they were a single \fB\.zst\fR file\.
    +.
    +.SH "OPTIONS"
     .
     .SS "Integer suffixes and special values"
    -In most places where an integer argument is expected,
    -an optional suffix is supported to easily indicate large integers.
    -There must be no space between the integer and the suffix.
    +In most places where an integer argument is expected, an optional suffix is supported to easily indicate large integers\. There must be no space between the integer and the suffix\.
    +.
     .TP
    -.B KiB
    -Multiply the integer by 1,024 (2^10).
    -.BR Ki ,
    -.BR K ,
    -and
    -.B KB
    -are accepted as synonyms for
    -.BR KiB .
    +\fBKiB\fR
    +Multiply the integer by 1,024 (2^10)\. \fBKi\fR, \fBK\fR, and \fBKB\fR are accepted as synonyms for \fBKiB\fR\.
    +.
     .TP
    -.B MiB
    -Multiply the integer by 1,048,576 (2^20).
    -.BR Mi ,
    -.BR M ,
    -and
    -.B MB
    -are accepted as synonyms for
    -.BR MiB .
    -
    +\fBMiB\fR
    +Multiply the integer by 1,048,576 (2^20)\. \fBMi\fR, \fBM\fR, and \fBMB\fR are accepted as synonyms for \fBMiB\fR\.
     .
     .SS "Operation mode"
    -If multiple operation mode options are given,
    -the last one takes effect.
    +If multiple operation mode options are given, the last one takes effect\.
    +.
     .TP
    -.BR \-z ", " \-\-compress
    -Compress.
    -This is the default operation mode when no operation mode option
    -is specified and no other operation mode is implied from
    -the command name (for example,
    -.B unzstd
    -implies
    -.BR \-\-decompress ).
    +\fB\-z\fR, \fB\-\-compress\fR
    +Compress\. This is the default operation mode when no operation mode option is specified and no other operation mode is implied from the command name (for example, \fBunzstd\fR implies \fB\-\-decompress\fR)\.
    +.
     .TP
    -.BR \-d ", " \-\-decompress ", " \-\-uncompress
    -Decompress.
    +\fB\-d\fR, \fB\-\-decompress\fR, \fB\-\-uncompress\fR
    +Decompress\.
    +.
     .TP
    -.BR \-t ", " \-\-test
    -Test the integrity of compressed
    -.IR files .
    -This option is equivalent to
    -.B "\-\-decompress \-\-stdout"
    -except that the decompressed data is discarded instead of being
    -written to standard output.
    -No files are created or removed.
    +\fB\-t\fR, \fB\-\-test\fR
    +Test the integrity of compressed \fIfiles\fR\. This option is equivalent to \fB\-\-decompress \-\-stdout\fR except that the decompressed data is discarded instead of being written to standard output\. No files are created or removed\.
    +.
     .TP
    -.B \-b#
    - benchmark file(s) using compression level #
    +\fB\-b#\fR
    +Benchmark file(s) using compression level #
    +.
     .TP
    -.B \--train FILEs
    - use FILEs as training set to create a dictionary. The training set should contain a lot of small files (> 100).
    -
    +\fB\-\-train FILEs\fR
    +Use FILEs as a training set to create a dictionary\. The training set should contain a lot of small files (> 100)\.
     .
     .SS "Operation modifiers"
    +.
     .TP
    -.B \-#
    - # compression level [1-19] (default:3)
    +\fB\-#\fR
    +\fB#\fR compression level [1\-19] (default: 3)
    +.
     .TP
    -.BR \--ultra
    - unlocks high compression levels 20+ (maximum 22), using a lot more memory.
    -Note that decompression will also require more memory when using these levels.
    +\fB\-\-ultra\fR
    +unlocks high compression levels 20+ (maximum 22), using a lot more memory\. Note that decompression will also require more memory when using these levels\.
    +.
     .TP
    -.B \-D file
    - use `file` as Dictionary to compress or decompress FILE(s)
    +\fB\-T#\fR, \fB\-\-threads=#\fR
    +Compress using \fB#\fR threads (default: 1)\. If \fB#\fR is 0, attempt to detect and use the number of physical CPU cores\. This modifier does nothing if \fBzstd\fR is compiled without multithread support\.
    +.
     .TP
    -.BR \--no-dictID
    - do not store dictionary ID within frame header (dictionary compression).
    - The decoder will have to rely on implicit knowledge about which dictionary to use,
    -it won't be able to check if it's correct.
    +\fB\-D file\fR
    +use \fBfile\fR as Dictionary to compress or decompress FILE(s)
    +.
     .TP
    -.B \-o file
    - save result into `file` (only possible with a single INPUT-FILE)
    +\fB\-\-nodictID\fR
    +do not store dictionary ID within frame header (dictionary compression)\. The decoder will have to rely on implicit knowledge about which dictionary to use, it won\'t be able to check if it\'s correct\.
    +.
     .TP
    -.BR \-f ", " --force
    - overwrite output without prompting
    +\fB\-o file\fR
    +save result into \fBfile\fR (only possible with a single \fIINPUT\-FILE\fR)
    +.
     .TP
    -.BR \-c ", " --stdout
    - force write to standard output, even if it is the console
    +\fB\-f\fR, \fB\-\-force\fR
    +overwrite output without prompting, and (de)compress symbolic links
    +.
     .TP
    -.BR \--[no-]sparse
    - enable / disable sparse FS support, to make files with many zeroes smaller on disk.
    - Creating sparse files may save disk space and speed up the decompression
    -by reducing the amount of disk I/O.
    - default : enabled when output is into a file, and disabled when output is stdout.
    - This setting overrides default and can force sparse mode over stdout.
    +\fB\-c\fR, \fB\-\-stdout\fR
    +force write to standard output, even if it is the console
    +.
     .TP
    -.BR \--rm
    - remove source file(s) after successful compression or decompression
    +\fB\-\-[no\-]sparse\fR
    +enable / disable sparse FS support, to make files with many zeroes smaller on disk\. Creating sparse files may save disk space and speed up decompression by reducing the amount of disk I/O\. default : enabled when output is into a file, and disabled when output is stdout\. This setting overrides default and can force sparse mode over stdout\.
    +.
     .TP
    -.BR \-k ", " --keep
    - keep source file(s) after successful compression or decompression.
    - This is the default behavior.
    +\fB\-\-rm\fR
    +remove source file(s) after successful compression or decompression
    +.
     .TP
    -.BR \-r
    - operate recursively on directories
    +\fB\-k\fR, \fB\-\-keep\fR
    +keep source file(s) after successful compression or decompression\. This is the default behavior\.
    +.
     .TP
    -.BR \-h/\-H ", " --help
    - display help/long help and exit
    +\fB\-r\fR
    +operate recursively on dictionaries
    +.
     .TP
    -.BR \-V ", " --version
    - display Version number and exit
    +\fB\-h\fR/\fB\-H\fR, \fB\-\-help\fR
    +display help/long help and exit
    +.
     .TP
    -.BR \-v ", " --verbose
    - verbose mode
    +\fB\-V\fR, \fB\-\-version\fR
    +display version number and exit
    +.
     .TP
    -.BR \-q ", " --quiet
    - suppress warnings, interactivity and notifications.
    - specify twice to suppress errors too.
    +\fB\-v\fR
    +verbose mode
    +.
     .TP
    -.BR \-C ", " --[no-]check
    - add integrity check computed from uncompressed data (default : enabled)
    +\fB\-q\fR, \fB\-\-quiet\fR
    +suppress warnings, interactivity, and notifications\. specify twice to suppress errors too\.
    +.
     .TP
    -.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.
    +\fB\-C\fR, \fB\-\-[no\-]check\fR
    +add integrity check computed from uncompressed data (default : enabled)
    +.
     .TP
    -.BR --
    - All arguments after -- are treated as files
    -
    -
    -.SH DICTIONARY BUILDER
    -.PP
    -\fBzstd\fR offers \fIdictionary\fR compression, useful for very small files and messages.
    -It's possible to train \fBzstd\fR with some samples, the result of which is saved into a file called `dictionary`.
    -Then during compression and decompression, make reference to the same dictionary.
    -It will improve compression ratio of small files.
    -Typical gains range from ~10% (at 64KB) to x5 better (at <1KB).
    +\fB\-\-\fR
    +All arguments after \fB\-\-\fR are treated as files
    +.
    +.SH "DICTIONARY BUILDER"
    +\fBzstd\fR offers \fIdictionary\fR compression, useful for very small files and messages\. It\'s possible to train \fBzstd\fR with some samples, the result of which is saved into a file called a \fBdictionary\fR\. Then during compression and decompression, reference the same dictionary\. It will improve compression ratio of small files\. Typical gains range from 10% (at 64KB) to x5 better (at <1KB)\.
    +.
     .TP
    -.B \--train FILEs
    - use FILEs as training set to create a dictionary. The training set should contain a lot of small files (> 100),
    -and weight typically 100x the target dictionary size (for example, 10 MB for a 100 KB dictionary)
    +\fB\-\-train FILEs\fR
    +Use FILEs as training set to create a dictionary\. The training set should contain a lot of small files (> 100), and weight typically 100x the target dictionary size (for example, 10 MB for a 100 KB dictionary)\.
    +.
    +.IP
    +Supports multithreading if \fBzstd\fR is compiled with threading support\. Additional parameters can be specified with \fB\-\-train\-cover\fR\. The legacy dictionary builder can be accessed with \fB\-\-train\-legacy\fR\. Equivalent to \fB\-\-train\-cover=d=8,steps=4\fR\.
    +.
     .TP
    -.B \-o file
    - dictionary saved into `file` (default: dictionary)
    +\fB\-o file\fR
    +Dictionary saved into \fBfile\fR (default name: dictionary)\.
    +.
     .TP
    -.B \--maxdict #
    - limit dictionary to specified size (default : 112640)
    +\fB\-\-maxdict=#\fR
    +Limit dictionary to specified size (default: 112640)\.
    +.
     .TP
    -.B \--dictID #
    - A dictionary ID is a locally unique ID that a decoder can use to verify it is using the right dictionary.
    - By default, zstd will create a 4-bytes random number ID.
    - It's possible to give a precise number instead.
    - Short numbers have an advantage : an ID < 256 will only need 1 byte in the compressed frame header,
    - and an ID < 65536 will only need 2 bytes. This compares favorably to 4 bytes default.
    - However, it's up to the dictionary manager to not assign twice the same ID to 2 different dictionaries.
    +\fB\-\-dictID=#\fR
    +A dictionary ID is a locally unique ID that a decoder can use to verify it is using the right dictionary\. By default, zstd will create a 4\-bytes random number ID\. It\'s possible to give a precise number instead\. Short numbers have an advantage : an ID < 256 will only need 1 byte in the compressed frame header, and an ID < 65536 will only need 2 bytes\. This compares favorably to 4 bytes default\. However, it\'s up to the dictionary manager to not assign twice the same ID to 2 different dictionaries\.
    +.
     .TP
    -.B \-s#
    - dictionary selectivity level (default: 9)
    - the smaller the value, the denser the dictionary, improving its efficiency but reducing its possible maximum size.
    +\fB\-\-train\-cover[=k#,d=#,steps=#]\fR
    +Select parameters for the default dictionary builder algorithm named cover\. If \fId\fR is not specified, then it tries \fId\fR = 6 and \fId\fR = 8\. If \fIk\fR is not specified, then it tries \fIsteps\fR values in the range [50, 2000]\. If \fIsteps\fR is not specified, then the default value of 40 is used\. Requires that \fId\fR <= \fIk\fR\.
    +.
    +.IP
    +Selects segments of size \fIk\fR with highest score to put in the dictionary\. The score of a segment is computed by the sum of the frequencies of all the subsegments of size \fId\fR\. Generally \fId\fR should be in the range [6, 8], occasionally up to 16, but the algorithm will run faster with d <= \fI8\fR\. Good values for \fIk\fR vary widely based on the input data, but a safe range is [2 * \fId\fR, 2000]\. Supports multithreading if \fBzstd\fR is compiled with threading support\.
    +.
    +.IP
    +Examples:
    +.
    +.IP
    +\fBzstd \-\-train\-cover FILEs\fR
    +.
    +.IP
    +\fBzstd \-\-train\-cover=k=50,d=8 FILEs\fR
    +.
    +.IP
    +\fBzstd \-\-train\-cover=d=8,steps=500 FILEs\fR
    +.
    +.IP
    +\fBzstd \-\-train\-cover=k=50 FILEs\fR
    +.
     .TP
    -.B \--cover=k=#,d=#
    - Use alternate dictionary builder algorithm named cover with parameters \fIk\fR and \fId\fR with \fId\fR <= \fIk\fR.
    - Selects segments of size \fIk\fR with the highest score to put in the dictionary.
    - The score of a segment is computed by the sum of the frequencies of all the subsegments of of size \fId\fR.
    - Generally \fId\fR should be in the range [6, 24].
    - Good values for \fIk\fR vary widely based on the input data, but a safe range is [32, 2048].
    - Example: \fB--train --cover=k=64,d=8 FILEs\fR.
    +\fB\-\-train\-legacy[=selectivity=#]\fR
    +Use legacy dictionary builder algorithm with the given dictionary \fIselectivity\fR (default: 9)\. The smaller the \fIselectivity\fR value, the denser the dictionary, improving its efficiency but reducing its possible maximum size\. \fB\-\-train\-legacy=s=#\fR is also accepted\.
    +.
    +.IP
    +Examples:
    +.
    +.IP
    +\fBzstd \-\-train\-legacy FILEs\fR
    +.
    +.IP
    +\fBzstd \-\-train\-legacy=selectivity=8 FILEs\fR
    +.
    +.SH "BENCHMARK"
    +.
     .TP
    -.B \--optimize-cover[=steps=#,k=#,d=#]
    - If \fIsteps\fR is not specified, the default value of 32 is used.
    - If \fIk\fR is not specified, \fIsteps\fR values in [16, 2048] are checked for each value of \fId\fR.
    - If \fId\fR is not specified, the values checked are [6, 8, ..., 16].
    -
    - Runs the cover dictionary builder for each parameter set saves the optimal parameters and dictionary.
    - Prints the optimal parameters and writes the optimal dictionary to the output file.
    - Supports multithreading if \fBzstd\fR is compiled with threading support.
    -
    - The parameter \fIk\fR is more sensitve than \fId\fR, and is faster to optimize over.
    - Suggested use is to run with a \fIsteps\fR <= 32 with neither \fIk\fR nor \fId\fR set.
    - Once it completes, use the value of \fId\fR it selects with a higher \fIsteps\fR (in the range [256, 1024]).
    - \fBzstd --train --optimize-cover FILEs
    - \fBzstd --train --optimize-cover=d=d,steps=512 FILEs
    +\fB\-b#\fR
    +benchmark file(s) using compression level #
    +.
     .TP
    -
    -.SH BENCHMARK
    +\fB\-e#\fR
    +benchmark file(s) using multiple compression levels, from \fB\-b#\fR to \fB\-e#\fR (inclusive)
    +.
     .TP
    -.B \-b#
    - benchmark file(s) using compression level #
    +\fB\-i#\fR
    +minimum evaluation time, in seconds (default : 3s), benchmark mode only
    +.
     .TP
    -.B \-e#
    - benchmark file(s) using multiple compression levels, from -b# to -e# (included).
    +\fB\-B#\fR
    +cut file into independent blocks of size # (default: no block)
    +.
     .TP
    -.B \-i#
    - minimum evaluation time, in seconds (default : 3s), benchmark mode only
    +\fB\-\-priority=rt\fR
    +set process priority to real\-time
    +.
    +.SH "ADVANCED COMPRESSION OPTIONS"
    +.
    +.SS "\-\-zstd[=options]:"
    +\fBzstd\fR provides 22 predefined compression levels\. The selected or default predefined compression level can be changed with advanced compression options\. The \fIoptions\fR are provided as a comma\-separated list\. You may specify only the options you want to change and the rest will be taken from the selected or default compression level\. The list of available \fIoptions\fR:
    +.
     .TP
    -.B \-B#
    - cut file into independent blocks of size # (default: no block)
    -.B \--priority=rt
    - set process priority to real-time
    -
    -.SH ADVANCED COMPRESSION OPTIONS
    +\fBstrategy\fR=\fIstrat\fR, \fBstrat\fR=\fIstrat\fR
    +Specify a strategy used by a match finder\.
    +.
    +.IP
    +There are 8 strategies numbered from 0 to 7, from faster to stronger: 0=ZSTD_fast, 1=ZSTD_dfast, 2=ZSTD_greedy, 3=ZSTD_lazy, 4=ZSTD_lazy2, 5=ZSTD_btlazy2, 6=ZSTD_btopt, 7=ZSTD_btopt2\.
    +.
     .TP
    -.B \--zstd[=\fIoptions\fR]
    -.PD
    -\fBzstd\fR provides 22 predefined compression levels. The selected or default predefined compression level can be changed with advanced compression options.
    -The \fIoptions\fR are provided as a comma-separated list. You may specify only the \fIoptions\fR you want to change and the rest will be taken from the selected or default compression level.
    -The list of available \fIoptions\fR:
    -.RS
    -
    +\fBwindowLog\fR=\fIwlog\fR, \fBwlog\fR=\fIwlog\fR
    +Specify the maximum number of bits for a match distance\.
    +.
    +.IP
    +The higher number of increases the chance to find a match which usually improves compression ratio\. It also increases memory requirements for the compressor and decompressor\. The minimum \fIwlog\fR is 10 (1 KiB) and the maximum is 27 (128 MiB)\.
    +.
     .TP
    -.BI strategy= strat
    -.PD 0
    +\fBhashLog\fR=\fIhlog\fR, \fBhlog\fR=\fIhlog\fR
    +Specify the maximum number of bits for a hash table\.
    +.
    +.IP
    +Bigger hash tables cause less collisions which usually makes compression faster, but requires more memory during compression\.
    +.
    +.IP
    +The minimum \fIhlog\fR is 6 (64 B) and the maximum is 26 (128 MiB)\.
    +.
     .TP
    -.BI strat= strat
    -.PD
    -Specify a strategy used by a match finder.
    -.IP ""
    -There are 8 strategies numbered from 0 to 7, from faster to stronger:
    -0=ZSTD_fast, 1=ZSTD_dfast, 2=ZSTD_greedy, 3=ZSTD_lazy, 4=ZSTD_lazy2, 5=ZSTD_btlazy2, 6=ZSTD_btopt, 7=ZSTD_btopt2.
    -.IP ""
    -
    +\fBchainLog\fR=\fIclog\fR, \fBclog\fR=\fIclog\fR
    +Specify the maximum number of bits for a hash chain or a binary tree\.
    +.
    +.IP
    +Higher numbers of bits increases the chance to find a match which usually improves compression ratio\. It also slows down compression speed and increases memory requirements for compression\. This option is ignored for the ZSTD_fast strategy\.
    +.
    +.IP
    +The minimum \fIclog\fR is 6 (64 B) and the maximum is 28 (256 MiB)\.
    +.
     .TP
    -.BI windowLog= wlog
    -.PD 0
    +\fBsearchLog\fR=\fIslog\fR, \fBslog\fR=\fIslog\fR
    +Specify the maximum number of searches in a hash chain or a binary tree using logarithmic scale\.
    +.
    +.IP
    +More searches increases the chance to find a match which usually increases compression ratio but decreases compression speed\.
    +.
    +.IP
    +The minimum \fIslog\fR is 1 and the maximum is 26\.
    +.
     .TP
    -.BI wlog= wlog
    -.PD
    -Specify the maximum number of bits for a match distance.
    -.IP ""
    -The higher number of bits increases the chance to find a match what usually improves compression ratio.
    -It also increases memory requirements for compressor and decompressor.
    -.IP ""
    -The minimum \fIwlog\fR is 10 (1 KiB) and the maximum is 25 (32 MiB) for 32-bit compilation and 27 (128 MiB) for 64-bit compilation.
    -.IP ""
    -
    +\fBsearchLength\fR=\fIslen\fR, \fBslen\fR=\fIslen\fR
    +Specify the minimum searched length of a match in a hash table\.
    +.
    +.IP
    +Larger search lengths usually decrease compression ratio but improve decompression speed\.
    +.
    +.IP
    +The minimum \fIslen\fR is 3 and the maximum is 7\.
    +.
     .TP
    -.BI hashLog= hlog
    -.PD 0
    +\fBtargetLen\fR=\fItlen\fR, \fBtlen\fR=\fItlen\fR
    +Specify the minimum match length that causes a match finder to stop searching for better matches\.
    +.
    +.IP
    +A larger minimum match length usually improves compression ratio but decreases compression speed\. This option is only used with strategies ZSTD_btopt and ZSTD_btopt2\.
    +.
    +.IP
    +The minimum \fItlen\fR is 4 and the maximum is 999\.
    +.
     .TP
    -.BI hlog= hlog
    -.PD
    -Specify the maximum number of bits for a hash table.
    -.IP ""
    -The bigger hash table causes less collisions what usually make compression faster but requires more memory during compression.
    -.IP ""
    -The minimum \fIhlog\fR is 6 (64 B) and the maximum is 25 (32 MiB) for 32-bit compilation and 27 (128 MiB) for 64-bit compilation.
    -
    -.TP
    -.BI chainLog= clog
    -.PD 0
    -.TP
    -.BI clog= clog
    -.PD
    -Specify the maximum number of bits for a hash chain or a binary tree.
    -.IP ""
    -The higher number of bits increases the chance to find a match what usually improves compression ratio.
    -It also slows down compression speed and increases memory requirements for compression.
    -This option is ignored for the ZSTD_fast strategy.
    -.IP ""
    -The minimum \fIclog\fR is 6 (64 B) and the maximum is 26 (64 MiB) for 32-bit compilation and 28 (256 MiB) for 64-bit compilation.
    -.IP ""
    -
    -.TP
    -.BI searchLog= slog
    -.PD 0
    -.TP
    -.BI slog= slog
    -.PD
    -Specify the maximum number of searches in a hash chain or a binary tree using logarithmic scale.
    -.IP ""
    -The bigger number of searches increases the chance to find a match what usually improves compression ratio but decreases compression speed.
    -.IP ""
    -The minimum \fIslog\fR is 1 and the maximum is 24 for 32-bit compilation and 26 for 64-bit compilation.
    -.IP ""
    -
    -.TP
    -.BI searchLength= slen
    -.PD 0
    -.TP
    -.BI slen= slen
    -.PD
    -Specify the minimum searched length of a match in a hash table.
    -.IP ""
    -The bigger search length usually decreases compression ratio but improves decompression speed.
    -.IP ""
    -The minimum \fIslen\fR is 3 and the maximum is 7.
    -.IP ""
    -
    -.TP
    -.BI targetLength= tlen
    -.PD 0
    -.TP
    -.BI tlen= tlen
    -.PD
    -Specify the minimum match length that causes a match finder to interrupt searching of better matches.
    -.IP ""
    -The bigger minimum match length usually improves compression ratio but decreases compression speed.
    -This option is used only with ZSTD_btopt and ZSTD_btopt2 strategies.
    -.IP ""
    -The minimum \fItlen\fR is 4 and the maximum is 999.
    -.IP ""
    -
    -.PP
    -.B An example
    -.br
    -The following parameters sets advanced compression options to predefined level 19 for files bigger than 256 KB:
    -.IP ""
    -\fB--zstd=\fRwindowLog=23,chainLog=23,hashLog=22,searchLog=6,searchLength=3,targetLength=48,strategy=6
    -
    -.SH BUGS
    -Report bugs at:- https://github.com/facebook/zstd/issues
    -
    -.SH AUTHOR
    +\fBoverlapLog\fR=\fIovlog\fR, \fBovlog\fR=\fIovlog\fR
    +Determine \fBoverlapSize\fR, amount of data reloaded from previous job\. This parameter is only available when multithreading is enabled\. Reloading more data improves compression ratio, but decreases speed\.
    +.
    +.IP
    +The minimum \fIovlog\fR is 0, and the maximum is 9\. 0 means "no overlap", hence completely independent jobs\. 9 means "full overlap", meaning up to \fBwindowSize\fR is reloaded from previous job\. Reducing \fIovlog\fR by 1 reduces the amount of reload by a factor 2\. Default \fIovlog\fR is 6, which means "reload \fBwindowSize / 8\fR"\. Exception : the maximum compression level (22) has a default \fIovlog\fR of 9\.
    +.
    +.SS "\-B#:"
    +Select the size of each compression job\. This parameter is available only when multi\-threading is enabled\. Default value is \fB4 * windowSize\fR, which means it varies depending on compression level\. \fB\-B#\fR makes it possible to select a custom value\. Note that job size must respect a minimum value which is enforced transparently\. This minimum is either 1 MB, or \fBoverlapSize\fR, whichever is largest\.
    +.
    +.SS "Example"
    +The following parameters sets advanced compression options to those of predefined level 19 for files bigger than 256 KB:
    +.
    +.P
    +\fB\-\-zstd\fR=windowLog=23,chainLog=23,hashLog=22,searchLog=6,searchLength=3,targetLength=48,strategy=6
    +.
    +.SH "BUGS"
    +Report bugs at: https://github\.com/facebook/zstd/issues
    +.
    +.SH "AUTHOR"
     Yann Collet
    diff --git a/programs/zstd.1.md b/programs/zstd.1.md
    new file mode 100644
    index 000000000000..118c9f2f8ee5
    --- /dev/null
    +++ b/programs/zstd.1.md
    @@ -0,0 +1,343 @@
    +zstd(1) -- zstd, zstdmt, unzstd, zstdcat - Compress or decompress .zst files
    +============================================================================
    +
    +SYNOPSIS
    +--------
    +
    +`zstd` [*OPTIONS*] [-|_INPUT-FILE_] [-o _OUTPUT-FILE_]
    +
    +`zstdmt` is equivalent to `zstd -T0`
    +
    +`unzstd` is equivalent to `zstd -d`
    +
    +`zstdcat` is equivalent to `zstd -dcf`
    +
    +
    +DESCRIPTION
    +-----------
    +`zstd` is a fast lossless compression algorithm and data compression tool,
    +with command line syntax similar to `gzip (1)` and `xz (1)`.
    +It is based on the **LZ77** family, with further FSE & huff0 entropy stages.
    +`zstd` offers highly configurable compression speed,
    +with fast modes at > 200 MB/s per code,
    +and strong modes nearing lzma compression ratios.
    +It also features a very fast decoder, with speeds > 500 MB/s per core.
    +
    +`zstd` command line syntax is generally similar to gzip,
    +but features the following differences :
    +
    +  - Source files are preserved by default.
    +    It's possible to remove them automatically by using the `--rm` command.
    +  - When compressing a single file, `zstd` displays progress notifications
    +    and result summary by default.
    +    Use `-q` to turn them off.
    +  - `zstd` does not accept input from console,
    +    but it properly accepts `stdin` when it's not the console.
    +  - `zstd` displays a short help page when command line is an error.
    +    Use `-q` to turn it off.
    +
    +`zstd` compresses or decompresses each _file_ according to the selected
    +operation mode.
    +If no _files_ are given or _file_ is `-`, `zstd` reads from standard input
    +and writes the processed data to standard output.
    +`zstd` will refuse to write compressed data to standard output
    +if it is a terminal : it will display an error message and skip the _file_.
    +Similarly, `zstd` will refuse to read compressed data from standard input
    +if it is a terminal.
    +
    +Unless `--stdout` or `-o` is specified, _files_ are written to a new file
    +whose name is derived from the source _file_ name:
    +
    +* When compressing, the suffix `.zst` is appended to the source filename to
    +  get the target filename.
    +* When decompressing, the `.zst` suffix is removed from the source filename to
    +  get the target filename
    +
    +### Concatenation with .zst files
    +It is possible to concatenate `.zst` files as is.
    +`zstd` will decompress such files as if they were a single `.zst` file.
    +
    +OPTIONS
    +-------
    +
    +### Integer suffixes and special values
    +In most places where an integer argument is expected,
    +an optional suffix is supported to easily indicate large integers.
    +There must be no space between the integer and the suffix.
    +
    +* `KiB`:
    +    Multiply the integer by 1,024 (2\^10).
    +    `Ki`, `K`, and `KB` are accepted as synonyms for `KiB`.
    +* `MiB`:
    +    Multiply the integer by 1,048,576 (2\^20).
    +    `Mi`, `M`, and `MB` are accepted as synonyms for `MiB`.
    +
    +### Operation mode
    +If multiple operation mode options are given,
    +the last one takes effect.
    +
    +* `-z`, `--compress`:
    +    Compress.
    +    This is the default operation mode when no operation mode option is specified
    +    and no other operation mode is implied from the command name
    +    (for example, `unzstd` implies `--decompress`).
    +* `-d`, `--decompress`, `--uncompress`:
    +    Decompress.
    +* `-t`, `--test`:
    +    Test the integrity of compressed _files_.
    +    This option is equivalent to `--decompress --stdout` except that the
    +    decompressed data is discarded instead of being written to standard output.
    +    No files are created or removed.
    +* `-b#`:
    +    Benchmark file(s) using compression level #
    +* `--train FILEs`:
    +    Use FILEs as a training set to create a dictionary.
    +    The training set should contain a lot of small files (> 100).
    +
    +### Operation modifiers
    +
    +* `-#`:
    +    `#` compression level \[1-19] (default: 3)
    +* `--ultra`:
    +    unlocks high compression levels 20+ (maximum 22), using a lot more memory.
    +    Note that decompression will also require more memory when using these levels.
    +* `-T#`, `--threads=#`:
    +    Compress using `#` threads (default: 1).
    +    If `#` is 0, attempt to detect and use the number of physical CPU cores.
    +    This modifier does nothing if `zstd` is compiled without multithread support.
    +* `-D file`:
    +    use `file` as Dictionary to compress or decompress FILE(s)
    +* `--nodictID`:
    +    do not store dictionary ID within frame header (dictionary compression).
    +    The decoder will have to rely on implicit knowledge about which dictionary to use,
    +    it won't be able to check if it's correct.
    +* `-o file`:
    +    save result into `file` (only possible with a single _INPUT-FILE_)
    +* `-f`, `--force`:
    +    overwrite output without prompting, and (de)compress symbolic links
    +* `-c`, `--stdout`:
    +    force write to standard output, even if it is the console
    +* `--[no-]sparse`:
    +    enable / disable sparse FS support,
    +    to make files with many zeroes smaller on disk.
    +    Creating sparse files may save disk space and speed up decompression by
    +    reducing the amount of disk I/O.
    +    default : enabled when output is into a file,
    +    and disabled when output is stdout.
    +    This setting overrides default and can force sparse mode over stdout.
    +* `--rm`:
    +    remove source file(s) after successful compression or decompression
    +* `-k`, `--keep`:
    +    keep source file(s) after successful compression or decompression.
    +    This is the default behavior.
    +* `-r`:
    +    operate recursively on dictionaries
    +* `-h`/`-H`, `--help`:
    +    display help/long help and exit
    +* `-V`, `--version`:
    +    display version number and exit
    +* `-v`:
    +    verbose mode
    +* `-q`, `--quiet`:
    +    suppress warnings, interactivity, and notifications.
    +    specify twice to suppress errors too.
    +* `-C`, `--[no-]check`:
    +    add integrity check computed from uncompressed data (default : enabled)
    +* `--`:
    +    All arguments after `--` are treated as files
    +
    +
    +DICTIONARY BUILDER
    +------------------
    +`zstd` offers _dictionary_ compression,
    +useful for very small files and messages.
    +It's possible to train `zstd` with some samples,
    +the result of which is saved into a file called a `dictionary`.
    +Then during compression and decompression, reference the same dictionary.
    +It will improve compression ratio of small files.
    +Typical gains range from 10% (at 64KB) to x5 better (at <1KB).
    +
    +* `--train FILEs`:
    +    Use FILEs as training set to create a dictionary.
    +    The training set should contain a lot of small files (> 100),
    +    and weight typically 100x the target dictionary size
    +    (for example, 10 MB for a 100 KB dictionary).
    +
    +    Supports multithreading if `zstd` is compiled with threading support.
    +    Additional parameters can be specified with `--train-cover`.
    +    The legacy dictionary builder can be accessed with `--train-legacy`.
    +    Equivalent to `--train-cover=d=8,steps=4`.
    +* `-o file`:
    +    Dictionary saved into `file` (default name: dictionary).
    +* `--maxdict=#`:
    +    Limit dictionary to specified size (default: 112640).
    +* `--dictID=#`:
    +    A dictionary ID is a locally unique ID that a decoder can use to verify it is
    +    using the right dictionary.
    +    By default, zstd will create a 4-bytes random number ID.
    +    It's possible to give a precise number instead.
    +    Short numbers have an advantage : an ID < 256 will only need 1 byte in the
    +    compressed frame header, and an ID < 65536 will only need 2 bytes.
    +    This compares favorably to 4 bytes default.
    +    However, it's up to the dictionary manager to not assign twice the same ID to
    +    2 different dictionaries.
    +* `--train-cover[=k#,d=#,steps=#]`:
    +    Select parameters for the default dictionary builder algorithm named cover.
    +    If _d_ is not specified, then it tries _d_ = 6 and _d_ = 8.
    +    If _k_ is not specified, then it tries _steps_ values in the range [50, 2000].
    +    If _steps_ is not specified, then the default value of 40 is used.
    +    Requires that _d_ <= _k_.
    +
    +    Selects segments of size _k_ with highest score to put in the dictionary.
    +    The score of a segment is computed by the sum of the frequencies of all the
    +    subsegments of size _d_.
    +    Generally _d_ should be in the range [6, 8], occasionally up to 16, but the
    +    algorithm will run faster with d <= _8_.
    +    Good values for _k_ vary widely based on the input data, but a safe range is
    +    [2 * _d_, 2000].
    +    Supports multithreading if `zstd` is compiled with threading support.
    +
    +    Examples:
    +
    +    `zstd --train-cover FILEs`
    +
    +    `zstd --train-cover=k=50,d=8 FILEs`
    +
    +    `zstd --train-cover=d=8,steps=500 FILEs`
    +
    +    `zstd --train-cover=k=50 FILEs`
    +
    +* `--train-legacy[=selectivity=#]`:
    +    Use legacy dictionary builder algorithm with the given dictionary
    +    _selectivity_ (default: 9).
    +    The smaller the _selectivity_ value, the denser the dictionary,
    +    improving its efficiency but reducing its possible maximum size.
    +    `--train-legacy=s=#` is also accepted.
    +
    +    Examples:
    +
    +    `zstd --train-legacy FILEs`
    +
    +    `zstd --train-legacy=selectivity=8 FILEs`
    +
    +
    +BENCHMARK
    +---------
    +
    +* `-b#`:
    +    benchmark file(s) using compression level #
    +* `-e#`:
    +    benchmark file(s) using multiple compression levels, from `-b#` to `-e#` (inclusive)
    +* `-i#`:
    +    minimum evaluation time, in seconds (default : 3s), benchmark mode only
    +* `-B#`:
    +    cut file into independent blocks of size # (default: no block)
    +* `--priority=rt`:
    +    set process priority to real-time
    +
    +
    +ADVANCED COMPRESSION OPTIONS
    +----------------------------
    +### --zstd[=options]:
    +`zstd` provides 22 predefined compression levels.
    +The selected or default predefined compression level can be changed with
    +advanced compression options.
    +The _options_ are provided as a comma-separated list.
    +You may specify only the options you want to change and the rest will be
    +taken from the selected or default compression level.
    +The list of available _options_:
    +
    +- `strategy`=_strat_, `strat`=_strat_:
    +    Specify a strategy used by a match finder.
    +
    +    There are 8 strategies numbered from 0 to 7, from faster to stronger:
    +    0=ZSTD\_fast, 1=ZSTD\_dfast, 2=ZSTD\_greedy, 3=ZSTD\_lazy,
    +    4=ZSTD\_lazy2, 5=ZSTD\_btlazy2, 6=ZSTD\_btopt, 7=ZSTD\_btopt2.
    +
    +- `windowLog`=_wlog_, `wlog`=_wlog_:
    +    Specify the maximum number of bits for a match distance.
    +
    +    The higher number of increases the chance to find a match which usually
    +    improves compression ratio.
    +    It also increases memory requirements for the compressor and decompressor.
    +    The minimum _wlog_ is 10 (1 KiB) and the maximum is 27 (128 MiB).
    +
    +- `hashLog`=_hlog_, `hlog`=_hlog_:
    +    Specify the maximum number of bits for a hash table.
    +
    +    Bigger hash tables cause less collisions which usually makes compression
    +    faster, but requires more memory during compression.
    +
    +    The minimum _hlog_ is 6 (64 B) and the maximum is 26 (128 MiB).
    +
    +- `chainLog`=_clog_, `clog`=_clog_:
    +    Specify the maximum number of bits for a hash chain or a binary tree.
    +
    +    Higher numbers of bits increases the chance to find a match which usually
    +    improves compression ratio.
    +    It also slows down compression speed and increases memory requirements for
    +    compression.
    +    This option is ignored for the ZSTD_fast strategy.
    +
    +    The minimum _clog_ is 6 (64 B) and the maximum is 28 (256 MiB).
    +
    +- `searchLog`=_slog_, `slog`=_slog_:
    +    Specify the maximum number of searches in a hash chain or a binary tree
    +    using logarithmic scale.
    +
    +    More searches increases the chance to find a match which usually increases
    +    compression ratio but decreases compression speed.
    +
    +    The minimum _slog_ is 1 and the maximum is 26.
    +
    +- `searchLength`=_slen_, `slen`=_slen_:
    +    Specify the minimum searched length of a match in a hash table.
    +
    +    Larger search lengths usually decrease compression ratio but improve
    +    decompression speed.
    +
    +    The minimum _slen_ is 3 and the maximum is 7.
    +
    +- `targetLen`=_tlen_, `tlen`=_tlen_:
    +    Specify the minimum match length that causes a match finder to stop
    +    searching for better matches.
    +
    +    A larger minimum match length usually improves compression ratio but
    +    decreases compression speed.
    +    This option is only used with strategies ZSTD_btopt and ZSTD_btopt2.
    +
    +    The minimum _tlen_ is 4 and the maximum is 999.
    +
    +- `overlapLog`=_ovlog_,  `ovlog`=_ovlog_:
    +    Determine `overlapSize`, amount of data reloaded from previous job.
    +    This parameter is only available when multithreading is enabled.
    +    Reloading more data improves compression ratio, but decreases speed.
    +
    +    The minimum _ovlog_ is 0, and the maximum is 9.
    +    0 means "no overlap", hence completely independent jobs.
    +    9 means "full overlap", meaning up to `windowSize` is reloaded from previous job.
    +    Reducing _ovlog_ by 1 reduces the amount of reload by a factor 2.
    +    Default _ovlog_ is 6, which means "reload `windowSize / 8`".
    +    Exception : the maximum compression level (22) has a default _ovlog_ of 9.
    +
    +### -B#:
    +Select the size of each compression job.
    +This parameter is available only when multi-threading is enabled.
    +Default value is `4 * windowSize`, which means it varies depending on compression level.
    +`-B#` makes it possible to select a custom value.
    +Note that job size must respect a minimum value which is enforced transparently.
    +This minimum is either 1 MB, or `overlapSize`, whichever is largest.
    +
    +### Example
    +The following parameters sets advanced compression options to those of
    +predefined level 19 for files bigger than 256 KB:
    +
    +`--zstd`=windowLog=23,chainLog=23,hashLog=22,searchLog=6,searchLength=3,targetLength=48,strategy=6
    +
    +BUGS
    +----
    +Report bugs at: https://github.com/facebook/zstd/issues
    +
    +AUTHOR
    +------
    +Yann Collet
    diff --git a/programs/zstdcli.c b/programs/zstdcli.c
    index ae49da7b1e72..32fef99930e9 100644
    --- a/programs/zstdcli.c
    +++ b/programs/zstdcli.c
    @@ -49,6 +49,7 @@
     #define AUTHOR "Yann Collet"
     #define WELCOME_MESSAGE "*** %s %i-bits %s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(size_t)*8), ZSTD_VERSION, AUTHOR
     
    +#define ZSTD_ZSTDMT "zstdmt"
     #define ZSTD_UNZSTD "unzstd"
     #define ZSTD_CAT "zstdcat"
     #define ZSTD_GZ "gzip"
    @@ -74,10 +75,10 @@ static U32 g_overlapLog = OVERLAP_LOG_DEFAULT;
     /*-************************************
     *  Display Macros
     **************************************/
    -#define DISPLAY(...)           fprintf(displayOut, __VA_ARGS__)
    -#define DISPLAYLEVEL(l, ...)   if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
    -static FILE* displayOut;
    -static unsigned displayLevel = DEFAULT_DISPLAY_LEVEL;   /* 0 : no display,  1: errors,  2 : + result + interaction + warnings,  3 : + progression,  4 : + information */
    +#define DISPLAY(...)         fprintf(g_displayOut, __VA_ARGS__)
    +#define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
    +static int g_displayLevel = DEFAULT_DISPLAY_LEVEL;   /* 0 : no display,  1: errors,  2 : + result + interaction + warnings,  3 : + progression,  4 : + information */
    +static FILE* g_displayOut;
     
     
     /*-************************************
    @@ -99,7 +100,7 @@ static int usage(const char* programName)
     #endif
         DISPLAY( " -D file: use `file` as Dictionary \n");
         DISPLAY( " -o file: result stored into `file` (only if 1 input file) \n");
    -    DISPLAY( " -f     : overwrite output without prompting \n");
    +    DISPLAY( " -f     : overwrite output without prompting and (de)compress links \n");
         DISPLAY( "--rm    : remove source file(s) after successful de/compression \n");
         DISPLAY( " -k     : preserve source file(s) (default) \n");
         DISPLAY( " -h/-H  : display help/long help and exit\n");
    @@ -113,19 +114,20 @@ static int usage_advanced(const char* programName)
         DISPLAY( "\n");
         DISPLAY( "Advanced arguments :\n");
         DISPLAY( " -V     : display Version number and exit\n");
    -    DISPLAY( " -v     : verbose mode; specify multiple times to increase log level (default:%d)\n", DEFAULT_DISPLAY_LEVEL);
    +    DISPLAY( " -v     : verbose mode; specify multiple times to increase verbosity\n");
         DISPLAY( " -q     : suppress warnings; specify twice to suppress errors too\n");
         DISPLAY( " -c     : force write to standard output, even if it is the console\n");
    -#ifdef UTIL_HAS_CREATEFILELIST
    -    DISPLAY( " -r     : operate recursively on directories \n");
    -#endif
     #ifndef ZSTD_NOCOMPRESS
         DISPLAY( "--ultra : enable levels beyond %i, up to %i (requires more memory)\n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel());
    -    DISPLAY( "--no-dictID : don't write dictID into header (dictionary compression)\n");
    -    DISPLAY( "--[no-]check : integrity check (default:enabled) \n");
     #ifdef ZSTD_MULTITHREAD
         DISPLAY( " -T#    : use # threads for compression (default:1) \n");
    -    DISPLAY( " -B#    : select size of independent sections (default:0==automatic) \n");
    +    DISPLAY( " -B#    : select size of each job (default:0==automatic) \n");
    +#endif
    +    DISPLAY( "--no-dictID : don't write dictID into header (dictionary compression)\n");
    +    DISPLAY( "--[no-]check : integrity check (default:enabled) \n");
    +#endif
    +#ifdef UTIL_HAS_CREATEFILELIST
    +    DISPLAY( " -r     : operate recursively on directories \n");
     #endif
     #ifdef ZSTD_GZCOMPRESS
         DISPLAY( "--format=gzip : compress files to the .gz format \n");
    @@ -134,10 +136,16 @@ static int usage_advanced(const char* programName)
         DISPLAY( "--format=xz : compress files to the .xz format \n");
         DISPLAY( "--format=lzma : compress files to the .lzma format \n");
     #endif
    +#ifdef ZSTD_LZ4COMPRESS
    +    DISPLAY( "--format=lz4 : compress files to the .lz4 format \n");
     #endif
     #ifndef ZSTD_NODECOMPRESS
         DISPLAY( "--test  : test compressed file integrity \n");
    +#if ZSTD_SPARSE_DEFAULT
         DISPLAY( "--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)\n");
    +#else
    +    DISPLAY( "--[no-]sparse : sparse mode (default:disabled)\n");
    +#endif
     #endif
         DISPLAY( " -M#    : Set a memory usage limit for decompression \n");
         DISPLAY( "--      : All arguments after \"--\" are treated as files \n");
    @@ -145,12 +153,11 @@ static int usage_advanced(const char* programName)
         DISPLAY( "\n");
         DISPLAY( "Dictionary builder :\n");
         DISPLAY( "--train ## : create a dictionary from a training set of files \n");
    -    DISPLAY( "--cover=k=#,d=# : use the cover algorithm with parameters k and d \n");
    -    DISPLAY( "--optimize-cover[=steps=#,k=#,d=#] : optimize cover parameters with optional parameters\n");
    +    DISPLAY( "--train-cover[=k=#,d=#,steps=#] : use the cover algorithm with optional args\n");
    +    DISPLAY( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u)\n", g_defaultSelectivityLevel);
         DISPLAY( " -o file : `file` is dictionary name (default: %s) \n", g_defaultDictName);
    -    DISPLAY( "--maxdict ## : limit dictionary to specified size (default : %u) \n", g_defaultMaxDictSize);
    -    DISPLAY( " -s#    : dictionary selectivity level (default: %u)\n", g_defaultSelectivityLevel);
    -    DISPLAY( "--dictID ## : force dictionary ID to specified value (default: random)\n");
    +    DISPLAY( "--maxdict=# : limit dictionary to specified size (default : %u) \n", g_defaultMaxDictSize);
    +    DISPLAY( "--dictID=# : force dictionary ID to specified value (default: random)\n");
     #endif
     #ifndef ZSTD_NOBENCH
         DISPLAY( "\n");
    @@ -167,7 +174,7 @@ static int usage_advanced(const char* programName)
     static int badusage(const char* programName)
     {
         DISPLAYLEVEL(1, "Incorrect parameters\n");
    -    if (displayLevel >= 1) usage(programName);
    +    if (g_displayLevel >= 2) usage(programName);
         return 1;
     }
     
    @@ -179,6 +186,23 @@ static void waitEnter(void)
         (void)unused;
     }
     
    +static const char* lastNameFromPath(const char* path)
    +{
    +    const char* name = path;
    +    if (strrchr(name, '/')) name = strrchr(name, '/') + 1;
    +    if (strrchr(name, '\\')) name = strrchr(name, '\\') + 1; /* windows */
    +    return name;
    +}
    +
    +/*! exeNameMatch() :
    +    @return : a non-zero value if exeName matches test, excluding the extension
    +   */
    +static int exeNameMatch(const char* exeName, const char* test)
    +{
    +    return !strncmp(exeName, test, strlen(test)) &&
    +        (exeName[strlen(test)] == '\0' || exeName[strlen(test)] == '.');
    +}
    +
     /*! readU32FromChar() :
         @return : unsigned integer value read from input in `char` format
         allows and interprets K, KB, KiB, M, MB and MiB suffix.
    @@ -216,11 +240,11 @@ static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
     #ifndef ZSTD_NODICT
     /**
      * parseCoverParameters() :
    - * reads cover parameters from *stringPtr (e.g. "--cover=smoothing=100,kmin=48,kstep=4,kmax=64,d=8") into *params
    + * reads cover parameters from *stringPtr (e.g. "--train-cover=k=48,d=8,steps=32") into *params
      * @return 1 means that cover parameters were correct
      * @return 0 in case of malformed parameters
      */
    -static unsigned parseCoverParameters(const char* stringPtr, COVER_params_t *params)
    +static unsigned parseCoverParameters(const char* stringPtr, COVER_params_t* params)
     {
         memset(params, 0, sizeof(*params));
         for (; ;) {
    @@ -230,9 +254,33 @@ static unsigned parseCoverParameters(const char* stringPtr, COVER_params_t *para
             return 0;
         }
         if (stringPtr[0] != 0) return 0;
    -    DISPLAYLEVEL(4, "k=%u\nd=%u\nsteps=%u\n", params->k, params->d, params->steps);
    +    DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nsteps=%u\n", params->k, params->d, params->steps);
         return 1;
     }
    +
    +/**
    + * parseLegacyParameters() :
    + * reads legacy dictioanry builter parameters from *stringPtr (e.g. "--train-legacy=selectivity=8") into *selectivity
    + * @return 1 means that legacy dictionary builder parameters were correct
    + * @return 0 in case of malformed parameters
    + */
    +static unsigned parseLegacyParameters(const char* stringPtr, unsigned* selectivity)
    +{
    +    if (!longCommandWArg(&stringPtr, "s=") && !longCommandWArg(&stringPtr, "selectivity=")) { return 0; }
    +    *selectivity = readU32FromChar(&stringPtr);
    +    if (stringPtr[0] != 0) return 0;
    +    DISPLAYLEVEL(4, "legacy: selectivity=%u\n", *selectivity);
    +    return 1;
    +}
    +
    +static COVER_params_t defaultCoverParams(void)
    +{
    +    COVER_params_t params;
    +    memset(¶ms, 0, sizeof(params));
    +    params.d = 8;
    +    params.steps = 4;
    +    return params;
    +}
     #endif
     
     
    @@ -270,6 +318,7 @@ int main(int argCount, const char* argv[])
     {
         int argNb,
             forceStdout=0,
    +        followLinks=0,
             main_pause=0,
             nextEntryIsDictionary=0,
             operationResult=0,
    @@ -305,8 +354,8 @@ int main(int argCount, const char* argv[])
         unsigned fileNamesNb;
     #endif
     #ifndef ZSTD_NODICT
    -    COVER_params_t coverParams;
    -    int cover = 0;
    +    COVER_params_t coverParams = defaultCoverParams();
    +    int cover = 1;
     #endif
     
         /* init */
    @@ -316,21 +365,19 @@ int main(int argCount, const char* argv[])
         (void)memLimit;   /* not used when ZSTD_NODECOMPRESS set */
         if (filenameTable==NULL) { DISPLAY("zstd: %s \n", strerror(errno)); exit(1); }
         filenameTable[0] = stdinmark;
    -    displayOut = stderr;
    -    /* Pick out program name from path. Don't rely on stdlib because of conflicting behavior */
    -    {   size_t pos;
    -        for (pos = (int)strlen(programName); pos > 0; pos--) { if (programName[pos] == '/') { pos++; break; } }
    -        programName += pos;
    -    }
    +    g_displayOut = stderr;
    +
    +    programName = lastNameFromPath(programName);
     
         /* preset behaviors */
    -    if (!strcmp(programName, ZSTD_UNZSTD)) operation=zom_decompress;
    -    if (!strcmp(programName, ZSTD_CAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; displayLevel=1; }
    -    if (!strcmp(programName, ZSTD_GZ)) { suffix = GZ_EXTENSION; FIO_setCompressionType(FIO_gzipCompression); FIO_setRemoveSrcFile(1); }    /* behave like gzip */
    -    if (!strcmp(programName, ZSTD_GUNZIP)) { operation=zom_decompress; FIO_setRemoveSrcFile(1); }                                          /* behave like gunzip */
    -    if (!strcmp(programName, ZSTD_GZCAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; displayLevel=1; }  /* behave like gzcat */
    -    if (!strcmp(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; FIO_setCompressionType(FIO_lzmaCompression); FIO_setRemoveSrcFile(1); }    /* behave like lzma */
    -    if (!strcmp(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; FIO_setCompressionType(FIO_xzCompression); FIO_setRemoveSrcFile(1); }    /* behave like xz */
    +    if (exeNameMatch(programName, ZSTD_ZSTDMT)) nbThreads=0;
    +    if (exeNameMatch(programName, ZSTD_UNZSTD)) operation=zom_decompress;
    +    if (exeNameMatch(programName, ZSTD_CAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; }
    +    if (exeNameMatch(programName, ZSTD_GZ)) { suffix = GZ_EXTENSION; FIO_setCompressionType(FIO_gzipCompression); FIO_setRemoveSrcFile(1); }    /* behave like gzip */
    +    if (exeNameMatch(programName, ZSTD_GUNZIP)) { operation=zom_decompress; FIO_setRemoveSrcFile(1); }                                          /* behave like gunzip */
    +    if (exeNameMatch(programName, ZSTD_GZCAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; }  /* behave like gzcat */
    +    if (exeNameMatch(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; FIO_setCompressionType(FIO_lzmaCompression); FIO_setRemoveSrcFile(1); }    /* behave like lzma */
    +    if (exeNameMatch(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; FIO_setCompressionType(FIO_xzCompression); FIO_setRemoveSrcFile(1); }    /* behave like xz */
         memset(&compressionParams, 0, sizeof(compressionParams));
     
         /* command switches */
    @@ -344,7 +391,7 @@ int main(int argCount, const char* argv[])
                     if (!filenameIdx) {
                         filenameIdx=1, filenameTable[0]=stdinmark;
                         outFileName=stdoutmark;
    -                    displayLevel-=(displayLevel==2);
    +                    g_displayLevel-=(g_displayLevel==2);
                         continue;
                 }   }
     
    @@ -357,12 +404,12 @@ int main(int argCount, const char* argv[])
                         if (!strcmp(argument, "--compress")) { operation=zom_compress; continue; }
                         if (!strcmp(argument, "--decompress")) { operation=zom_decompress; continue; }
                         if (!strcmp(argument, "--uncompress")) { operation=zom_decompress; continue; }
    -                    if (!strcmp(argument, "--force")) { FIO_overwriteMode(); continue; }
    -                    if (!strcmp(argument, "--version")) { displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); }
    -                    if (!strcmp(argument, "--help")) { displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); }
    -                    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, "--force")) { FIO_overwriteMode(); forceStdout=1; followLinks=1; continue; }
    +                    if (!strcmp(argument, "--version")) { g_displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); }
    +                    if (!strcmp(argument, "--help")) { g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); }
    +                    if (!strcmp(argument, "--verbose")) { g_displayLevel++; continue; }
    +                    if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; }
    +                    if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; g_displayLevel-=(g_displayLevel==2); 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; }
    @@ -370,8 +417,8 @@ int main(int argCount, const char* argv[])
                         if (!strcmp(argument, "--no-sparse")) { FIO_setSparseWrite(0); continue; }
                         if (!strcmp(argument, "--test")) { operation=zom_test; continue; }
                         if (!strcmp(argument, "--train")) { operation=zom_train; outFileName=g_defaultDictName; continue; }
    -                    if (!strcmp(argument, "--maxdict")) { nextArgumentIsMaxDict=1; lastCommand=1; continue; }
    -                    if (!strcmp(argument, "--dictID")) { nextArgumentIsDictID=1; lastCommand=1; continue; }
    +                    if (!strcmp(argument, "--maxdict")) { nextArgumentIsMaxDict=1; lastCommand=1; continue; }  /* kept available for compatibility with old syntax ; will be removed one day */
    +                    if (!strcmp(argument, "--dictID")) { nextArgumentIsDictID=1; lastCommand=1; continue; }  /* kept available for compatibility with old syntax ; will be removed one day */
                         if (!strcmp(argument, "--no-dictID")) { FIO_setDictIDFlag(0); continue; }
                         if (!strcmp(argument, "--keep")) { FIO_setRemoveSrcFile(0); continue; }
                         if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(1); continue; }
    @@ -383,26 +430,40 @@ int main(int argCount, const char* argv[])
                         if (!strcmp(argument, "--format=lzma")) { suffix = LZMA_EXTENSION; FIO_setCompressionType(FIO_lzmaCompression);  continue; }
                         if (!strcmp(argument, "--format=xz")) { suffix = XZ_EXTENSION; FIO_setCompressionType(FIO_xzCompression);  continue; }
     #endif
    +#ifdef ZSTD_LZ4COMPRESS
    +                    if (!strcmp(argument, "--format=lz4")) { suffix = LZ4_EXTENSION; FIO_setCompressionType(FIO_lz4Compression);  continue; }
    +#endif
     
                         /* long commands with arguments */
     #ifndef ZSTD_NODICT
    -                    if (longCommandWArg(&argument, "--cover=")) {
    -                      cover=1; if (!parseCoverParameters(argument, &coverParams)) CLEAN_RETURN(badusage(programName));
    -                      continue;
    -                    }
    -                    if (longCommandWArg(&argument, "--optimize-cover")) {
    -                      cover=2;
    +                    if (longCommandWArg(&argument, "--train-cover")) {
    +                      operation = zom_train;
    +                      outFileName = g_defaultDictName;
    +                      cover = 1;
                           /* Allow optional arguments following an = */
                           if (*argument == 0) { memset(&coverParams, 0, sizeof(coverParams)); }
                           else if (*argument++ != '=') { CLEAN_RETURN(badusage(programName)); }
                           else if (!parseCoverParameters(argument, &coverParams)) { CLEAN_RETURN(badusage(programName)); }
                           continue;
                         }
    +                    if (longCommandWArg(&argument, "--train-legacy")) {
    +                      operation = zom_train;
    +                      outFileName = g_defaultDictName;
    +                      cover = 0;
    +                      /* Allow optional arguments following an = */
    +                      if (*argument == 0) { continue; }
    +                      else if (*argument++ != '=') { CLEAN_RETURN(badusage(programName)); }
    +                      else if (!parseLegacyParameters(argument, &dictSelect)) { CLEAN_RETURN(badusage(programName)); }
    +                      continue;
    +                    }
     #endif
    +                    if (longCommandWArg(&argument, "--threads=")) { nbThreads = readU32FromChar(&argument); continue; }
                         if (longCommandWArg(&argument, "--memlimit=")) { memLimit = readU32FromChar(&argument); continue; }
                         if (longCommandWArg(&argument, "--memory=")) { memLimit = readU32FromChar(&argument); continue; }
                         if (longCommandWArg(&argument, "--memlimit-decompress=")) { memLimit = readU32FromChar(&argument); continue; }
                         if (longCommandWArg(&argument, "--block-size=")) { blockSize = readU32FromChar(&argument); continue; }
    +                    if (longCommandWArg(&argument, "--maxdict=")) { maxDictSize = readU32FromChar(&argument); continue; }
    +                    if (longCommandWArg(&argument, "--dictID=")) { dictID = readU32FromChar(&argument); continue; }
                         if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) CLEAN_RETURN(badusage(programName)); continue; }
                         /* fall-through, will trigger bad_usage() later on */
                     }
    @@ -424,9 +485,9 @@ int main(int argCount, const char* argv[])
                         switch(argument[0])
                         {
                             /* Display help */
    -                    case 'V': displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0);   /* Version Only */
    +                    case 'V': g_displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0);   /* Version Only */
                         case 'H':
    -                    case 'h': displayOut=stdout; CLEAN_RETURN(usage_advanced(programName));
    +                    case 'h': g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName));
     
                              /* Compress */
                         case 'z': operation=zom_compress; argument++; break;
    @@ -445,19 +506,19 @@ int main(int argCount, const char* argv[])
                         case 'D': nextEntryIsDictionary = 1; lastCommand = 1; argument++; break;
     
                             /* Overwrite */
    -                    case 'f': FIO_overwriteMode(); forceStdout=1; argument++; break;
    +                    case 'f': FIO_overwriteMode(); forceStdout=1; followLinks=1; argument++; break;
     
                             /* Verbose mode */
    -                    case 'v': displayLevel++; argument++; break;
    +                    case 'v': g_displayLevel++; argument++; break;
     
                             /* Quiet mode */
    -                    case 'q': displayLevel--; argument++; break;
    +                    case 'q': g_displayLevel--; argument++; break;
     
    -                        /* keep source file (default); for gzip/xz compatibility */
    +                        /* keep source file (default) */
                         case 'k': FIO_setRemoveSrcFile(0); argument++; break;
     
                             /* Checksum */
    -                    case 'C': argument++; FIO_setChecksumFlag(2); break;
    +                    case 'C': FIO_setChecksumFlag(2); argument++; break;
     
                             /* test compressed file */
                         case 't': operation=zom_test; argument++; break;
    @@ -532,14 +593,14 @@ int main(int argCount, const char* argv[])
                     continue;
                 }   /* if (argument[0]=='-') */
     
    -            if (nextArgumentIsMaxDict) {
    +            if (nextArgumentIsMaxDict) {  /* kept available for compatibility with old syntax ; will be removed one day */
                     nextArgumentIsMaxDict = 0;
                     lastCommand = 0;
                     maxDictSize = readU32FromChar(&argument);
                     continue;
                 }
     
    -            if (nextArgumentIsDictID) {
    +            if (nextArgumentIsDictID) {  /* kept available for compatibility with old syntax ; will be removed one day */
                     nextArgumentIsDictID = 0;
                     lastCommand = 0;
                     dictID = readU32FromChar(&argument);
    @@ -581,9 +642,27 @@ int main(int argCount, const char* argv[])
         DISPLAYLEVEL(4, "PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION);
     #endif
     
    +    if (nbThreads == 0) {
    +        /* try to guess */
    +        nbThreads = UTIL_countPhysicalCores();
    +        DISPLAYLEVEL(3, "Note: %d physical core(s) detected\n", nbThreads);
    +    }
    +
    +    g_utilDisplayLevel = g_displayLevel;
    +    if (!followLinks) {
    +        unsigned u;
    +        for (u=0, fileNamesNb=0; u1) & (displayLevel==2)) displayLevel=1;
    +    if (!strcmp(filenameTable[0], stdinmark) && outFileName && !strcmp(outFileName,stdoutmark) && (g_displayLevel==2)) g_displayLevel=1;
    +    if ((filenameIdx>1) & (g_displayLevel==2)) g_displayLevel=1;
     
         /* IO Stream/File */
    -    FIO_setNotificationLevel(displayLevel);
    +    FIO_setNotificationLevel(g_displayLevel);
         if (operation==zom_compress) {
     #ifndef ZSTD_NOCOMPRESS
             FIO_setNbThreads(nbThreads);
    diff --git a/tests/Makefile b/tests/Makefile
    index 9382fe80ddc2..ea58c0fe5119 100644
    --- a/tests/Makefile
    +++ b/tests/Makefile
    @@ -26,9 +26,12 @@ PYTHON ?= python3
     TESTARTEFACT := versionsTest namespaceTest
     
     
    -CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress -I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR)
    +DEBUGFLAGS=-g -DZSTD_DEBUG=1
    +CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
    +           -I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR) \
    +           $(DEBUGFLAG)
     CFLAGS  ?= -O3
    -CFLAGS  += -g -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
    +CFLAGS  += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
                -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
                -Wstrict-prototypes -Wundef -Wformat-security
     CFLAGS  += $(MOREFLAGS)
    @@ -65,14 +68,16 @@ FUZZERTEST ?= -T5mn
     ZSTDRTTEST = --test-large-data
     DECODECORPUS_TESTTIME ?= -T30
     
    -.PHONY: default all all32 dll clean test test32 test-all namespaceTest versionsTest
    +.PHONY: default all all32 allnothread dll clean test test32 test-all namespaceTest versionsTest
     
     default: fullbench
     
    -all: fullbench fuzzer zstreamtest paramgrill datagen zbufftest
    +all: fullbench fuzzer zstreamtest paramgrill datagen zbufftest decodecorpus
     
     all32: fullbench32 fuzzer32 zstreamtest32 zbufftest32
     
    +allnothread: fullbench fuzzer paramgrill datagen zbufftest decodecorpus
    +
     dll: fuzzer-dll zstreamtest-dll zbufftest-dll
     
     zstd:
    @@ -152,6 +157,7 @@ zstreamtest-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/datagen.c zstreamtest.c
     	$(MAKE) -C $(ZSTDDIR) libzstd
     	$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@$(EXT)
     
    +paramgrill : DEBUGFLAG =
     paramgrill : $(ZSTD_FILES) $(PRGDIR)/datagen.c paramgrill.c
     	$(CC)      $(FLAGS) $^ -lm -o $@$(EXT)
     
    @@ -300,10 +306,10 @@ test-fullbench32: fullbench32 datagen
     	$(QEMU_SYS) ./fullbench32 -i1 -P0
     
     test-fuzzer: fuzzer
    -	$(QEMU_SYS) ./fuzzer $(FUZZERTEST)
    +	$(QEMU_SYS) ./fuzzer $(FUZZERTEST) $(FUZZER_FLAGS)
     
     test-fuzzer32: fuzzer32
    -	$(QEMU_SYS) ./fuzzer32 $(FUZZERTEST)
    +	$(QEMU_SYS) ./fuzzer32 $(FUZZERTEST) $(FUZZER_FLAGS)
     
     test-zbuff: zbufftest
     	$(QEMU_SYS) ./zbufftest $(ZSTREAM_TESTTIME)
    @@ -312,10 +318,10 @@ test-zbuff32: zbufftest32
     	$(QEMU_SYS) ./zbufftest32 $(ZSTREAM_TESTTIME)
     
     test-zstream: zstreamtest
    -	$(QEMU_SYS) ./zstreamtest $(ZSTREAM_TESTTIME)
    +	$(QEMU_SYS) ./zstreamtest $(ZSTREAM_TESTTIME) $(FUZZER_FLAGS)
     
     test-zstream32: zstreamtest32
    -	$(QEMU_SYS) ./zstreamtest32 $(ZSTREAM_TESTTIME)
    +	$(QEMU_SYS) ./zstreamtest32 $(ZSTREAM_TESTTIME) $(FUZZER_FLAGS)
     
     test-longmatch: longmatch
     	$(QEMU_SYS) ./longmatch
    diff --git a/tests/decodecorpus.c b/tests/decodecorpus.c
    index 183d20f749e6..f7b3c854fdb2 100644
    --- a/tests/decodecorpus.c
    +++ b/tests/decodecorpus.c
    @@ -98,7 +98,7 @@ static void RAND_bufferMaxSymb(U32* seed, void* ptr, size_t size, int maxSymb)
         BYTE* op = ptr;
     
         for (i = 0; i < size; i++) {
    -        op[i] = RAND(seed) % (maxSymb + 1);
    +        op[i] = (BYTE) (RAND(seed) % (maxSymb + 1));
         }
     }
     
    @@ -134,8 +134,8 @@ static void RAND_genDist(U32* seed, BYTE* dist, double weight)
     {
         size_t i = 0;
         size_t statesLeft = DISTSIZE;
    -    BYTE symb = RAND(seed) % 256;
    -    BYTE step = (RAND(seed) % 256) | 1; /* force it to be odd so it's relatively prime to 256 */
    +    BYTE symb = (BYTE) (RAND(seed) % 256);
    +    BYTE step = (BYTE) ((RAND(seed) % 256) | 1); /* force it to be odd so it's relatively prime to 256 */
     
         while (i < DISTSIZE) {
             size_t states = ((size_t)(weight * statesLeft)) + 1;
    @@ -259,7 +259,7 @@ static void writeFrameHeader(U32* seed, frame_t* frame)
             /* Follow window algorithm from specification */
             int const exponent = RAND(seed) % (MAX_WINDOW_LOG - 10);
             int const mantissa = RAND(seed) % 8;
    -        windowByte = (exponent << 3) | mantissa;
    +        windowByte = (BYTE) ((exponent << 3) | mantissa);
             fh.windowSize = (1U << (exponent + 10));
             fh.windowSize += fh.windowSize / 8 * mantissa;
         }
    @@ -284,7 +284,7 @@ static void writeFrameHeader(U32* seed, frame_t* frame)
     
             if (contentSizeFlag && (fh.contentSize == 0 || !(RAND(seed) & 7))) {
                 /* do single segment sometimes */
    -            fh.windowSize = fh.contentSize;
    +            fh.windowSize = (U32) fh.contentSize;
                 singleSegment = 1;
             }
         }
    @@ -307,7 +307,7 @@ static void writeFrameHeader(U32* seed, frame_t* frame)
     
         {
             BYTE const frameHeaderDescriptor =
    -                (fcsCode << 6) | (singleSegment << 5) | (1 << 2);
    +                (BYTE) ((fcsCode << 6) | (singleSegment << 5) | (1 << 2));
             op[pos++] = frameHeaderDescriptor;
         }
     
    @@ -318,14 +318,14 @@ static void writeFrameHeader(U32* seed, frame_t* frame)
         if (contentSizeFlag) {
             switch (fcsCode) {
             default: /* Impossible */
    -        case 0: op[pos++] = fh.contentSize; break;
    -        case 1: MEM_writeLE16(op + pos, fh.contentSize - 256); pos += 2; break;
    -        case 2: MEM_writeLE32(op + pos, fh.contentSize); pos += 4; break;
    -        case 3: MEM_writeLE64(op + pos, fh.contentSize); pos += 8; break;
    +        case 0: op[pos++] = (BYTE) fh.contentSize; break;
    +        case 1: MEM_writeLE16(op + pos, (U16) (fh.contentSize - 256)); pos += 2; break;
    +        case 2: MEM_writeLE32(op + pos, (U32) fh.contentSize); pos += 4; break;
    +        case 3: MEM_writeLE64(op + pos, (U64) fh.contentSize); pos += 8; break;
             }
         }
     
    -    DISPLAYLEVEL(2, " frame content size:\t%zu\n", fh.contentSize);
    +    DISPLAYLEVEL(2, " frame content size:\t%u\n", (U32)fh.contentSize);
         DISPLAYLEVEL(2, " frame window size:\t%u\n", fh.windowSize);
         DISPLAYLEVEL(2, " content size flag:\t%d\n", contentSizeFlag);
         DISPLAYLEVEL(2, " single segment flag:\t%d\n", singleSegment);
    @@ -385,7 +385,7 @@ static size_t writeLiteralsBlockSimple(U32* seed, frame_t* frame, size_t content
             op += litSize;
         } else {
             /* RLE literals */
    -        BYTE const symb = RAND(seed) % 256;
    +        BYTE const symb = (BYTE) (RAND(seed) % 256);
     
             DISPLAYLEVEL(4, "   rle literals: 0x%02x\n", (U32)symb);
     
    @@ -542,8 +542,8 @@ static size_t writeLiteralsBlockCompressed(U32* seed, frame_t* frame, size_t con
             op += compressedSize;
     
             compressedSize += hufHeaderSize;
    -        DISPLAYLEVEL(5, "    regenerated size: %zu\n", litSize);
    -        DISPLAYLEVEL(5, "    compressed size: %zu\n", compressedSize);
    +        DISPLAYLEVEL(5, "    regenerated size: %u\n", (U32)litSize);
    +        DISPLAYLEVEL(5, "    compressed size: %u\n", (U32)compressedSize);
             if (compressedSize >= litSize) {
                 DISPLAYLEVEL(5, "     trying again\n");
                 /* if we have to try again, reset the stats so we don't accidentally
    @@ -611,7 +611,7 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
         size_t const remainingMatch = contentSize - literalsSize;
         size_t excessMatch = 0;
         U32 numSequences = 0;
    -  
    +
         U32 i;
     
     
    @@ -628,7 +628,7 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
             excessMatch = remainingMatch - numSequences * MIN_SEQ_LEN;
         }
     
    -    DISPLAYLEVEL(5, "    total match lengths: %zu\n", remainingMatch);
    +    DISPLAYLEVEL(5, "    total match lengths: %u\n", (U32)remainingMatch);
     
         for (i = 0; i < numSequences; i++) {
             /* Generate match and literal lengths by exponential distribution to
    @@ -647,10 +647,10 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
             U32 offset, offsetCode, repIndex;
     
             /* bounds checks */
    -        matchLen = MIN(matchLen, excessMatch + MIN_SEQ_LEN);
    -        literalLen = MIN(literalLen, literalsSize);
    +        matchLen = (U32) MIN(matchLen, excessMatch + MIN_SEQ_LEN);
    +        literalLen = MIN(literalLen, (U32) literalsSize);
             if (i == 0 && srcPtr == frame->srcStart && literalLen == 0) literalLen = 1;
    -        if (i + 1 == numSequences) matchLen = MIN_SEQ_LEN + excessMatch;
    +        if (i + 1 == numSequences) matchLen = MIN_SEQ_LEN + (U32) excessMatch;
     
             memcpy(srcPtr, literals, literalLen);
             srcPtr += literalLen;
    @@ -694,8 +694,8 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
             }
     
             DISPLAYLEVEL(6, "      LL: %5u OF: %5u ML: %5u", literalLen, offset, matchLen);
    -        DISPLAYLEVEL(7, " srcPos: %8tu seqNb: %3u",
    -                     (BYTE*)srcPtr - (BYTE*)frame->srcStart, i);
    +        DISPLAYLEVEL(7, " srcPos: %8u seqNb: %3u",
    +                     (U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart), i);
             DISPLAYLEVEL(6, "\n");
             if (offsetCode < 3) {
                 DISPLAYLEVEL(7, "        repeat offset: %d\n", repIndex);
    @@ -711,8 +711,8 @@ static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
     
         memcpy(srcPtr, literals, literalsSize);
         srcPtr += literalsSize;
    -    DISPLAYLEVEL(6, "      excess literals: %5zu", literalsSize);
    -    DISPLAYLEVEL(7, " srcPos: %8tu", (BYTE*)srcPtr - (BYTE*)frame->srcStart);
    +    DISPLAYLEVEL(6, "      excess literals: %5u", (U32)literalsSize);
    +    DISPLAYLEVEL(7, " srcPos: %8u", (U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart));
         DISPLAYLEVEL(6, "\n");
     
         return numSequences;
    @@ -957,11 +957,11 @@ static size_t writeCompressedBlock(U32* seed, frame_t* frame, size_t contentSize
     
         literalsSize = writeLiteralsBlock(seed, frame, contentSize);
     
    -    DISPLAYLEVEL(4, "   literals size: %zu\n", literalsSize);
    +    DISPLAYLEVEL(4, "   literals size: %u\n", (U32)literalsSize);
     
         nbSeq = writeSequencesBlock(seed, frame, contentSize, literalsSize);
     
    -    DISPLAYLEVEL(4, "   number of sequences: %zu\n", nbSeq);
    +    DISPLAYLEVEL(4, "   number of sequences: %u\n", (U32)nbSeq);
     
         return (BYTE*)frame->data - blockStart;
     }
    @@ -977,7 +977,7 @@ static void writeBlock(U32* seed, frame_t* frame, size_t contentSize,
         BYTE *op = header + 3;
     
         DISPLAYLEVEL(3, " block:\n");
    -    DISPLAYLEVEL(3, "  block content size: %zu\n", contentSize);
    +    DISPLAYLEVEL(3, "  block content size: %u\n", (U32)contentSize);
         DISPLAYLEVEL(3, "  last block: %s\n", lastBlock ? "yes" : "no");
     
         if (blockTypeDesc == 0) {
    @@ -1025,10 +1025,10 @@ static void writeBlock(U32* seed, frame_t* frame, size_t contentSize,
         frame->src = (BYTE*)frame->src + contentSize;
     
         DISPLAYLEVEL(3, "  block type: %s\n", BLOCK_TYPES[blockType]);
    -    DISPLAYLEVEL(3, "  block size field: %zu\n", blockSize);
    +    DISPLAYLEVEL(3, "  block size field: %u\n", (U32)blockSize);
     
    -    header[0] = (lastBlock | (blockType << 1) | (blockSize << 3)) & 0xff;
    -    MEM_writeLE16(header + 1, blockSize >> 5);
    +    header[0] = (BYTE) ((lastBlock | (blockType << 1) | (blockSize << 3)) & 0xff);
    +    MEM_writeLE16(header + 1, (U16) (blockSize >> 5));
     
         frame->data = op;
     }
    @@ -1300,7 +1300,7 @@ static int generateCorpus(U32 seed, unsigned numFiles, const char* const path,
     *********************************************************/
     static U32 makeSeed(void)
     {
    -    U32 t = time(NULL);
    +    U32 t = (U32) time(NULL);
         return XXH32(&t, sizeof(t), 0) % 65536;
     }
     
    diff --git a/tests/fullbench.c b/tests/fullbench.c
    index 940d315a7cd4..38cf22fa7ebc 100644
    --- a/tests/fullbench.c
    +++ b/tests/fullbench.c
    @@ -251,14 +251,14 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb)
         case 13:
             benchFunction = local_ZSTD_decompressContinue; benchName = "ZSTD_decompressContinue";
             break;
    -	case 31:
    +    case 31:
             benchFunction = local_ZSTD_decodeLiteralsBlock; benchName = "ZSTD_decodeLiteralsBlock";
             break;
         case 32:
             benchFunction = local_ZSTD_decodeSeqHeaders; benchName = "ZSTD_decodeSeqHeaders";
             break;
     #endif
    -	case 41:
    +    case 41:
             benchFunction = local_ZSTD_compressStream; benchName = "ZSTD_compressStream";
             break;
         case 42:
    diff --git a/tests/fuzzer.c b/tests/fuzzer.c
    index def7542b5f0b..a9dcf12e0702 100644
    --- a/tests/fuzzer.c
    +++ b/tests/fuzzer.c
    @@ -28,6 +28,7 @@
     #define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_compressContinue, ZSTD_compressBlock */
     #include "zstd.h"         /* ZSTD_VERSION_STRING */
     #include "zstd_errors.h"  /* ZSTD_getErrorCode */
    +#include "zstdmt_compress.h"
     #define ZDICT_STATIC_LINKING_ONLY
     #include "zdict.h"        /* ZDICT_trainFromBuffer */
     #include "datagen.h"      /* RDG_genBuffer */
    @@ -57,7 +58,7 @@ static U32 g_displayLevel = 2;
     #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
                 if ((FUZ_clockSpan(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \
                 { g_displayClock = clock(); DISPLAY(__VA_ARGS__); \
    -            if (g_displayLevel>=4) fflush(stdout); } }
    +            if (g_displayLevel>=4) fflush(stderr); } }
     static const clock_t g_refreshRate = CLOCKS_PER_SEC / 6;
     static clock_t g_displayClock = 0;
     
    @@ -133,13 +134,21 @@ static int basicUnitTests(U32 seed, double compressibility)
             DISPLAYLEVEL(4, "OK : %s \n", errorString);
         }
     
    +
         DISPLAYLEVEL(4, "test%3i : compress %u bytes : ", testNb++, (U32)CNBuffSize);
         CHECKPLUS(r, ZSTD_compress(compressedBuffer, ZSTD_compressBound(CNBuffSize),
                                    CNBuffer, CNBuffSize, 1),
                   cSize=r );
         DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100);
     
    -    DISPLAYLEVEL(4, "test%3i : decompressed size test : ", testNb++);
    +
    +    DISPLAYLEVEL(4, "test%3i : ZSTD_getFrameContentSize test : ", testNb++);
    +    {   unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize);
    +        if (rSize != CNBuffSize) goto _output_error;
    +    }
    +    DISPLAYLEVEL(4, "OK \n");
    +
    +    DISPLAYLEVEL(4, "test%3i : ZSTD_findDecompressedSize test : ", testNb++);
         {   unsigned long long const rSize = ZSTD_findDecompressedSize(compressedBuffer, cSize);
             if (rSize != CNBuffSize) goto _output_error;
         }
    @@ -157,6 +166,7 @@ static int basicUnitTests(U32 seed, double compressibility)
         }   }
         DISPLAYLEVEL(4, "OK \n");
     
    +
         DISPLAYLEVEL(4, "test%3i : decompress with null dict : ", testNb++);
         { size_t const r = ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, NULL, 0);
           if (r != CNBuffSize) goto _output_error; }
    @@ -179,6 +189,49 @@ static int basicUnitTests(U32 seed, double compressibility)
           if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; }
         DISPLAYLEVEL(4, "OK \n");
     
    +
    +    /* ZSTDMT simple MT compression test */
    +    DISPLAYLEVEL(4, "test%3i : create ZSTDMT CCtx : ", testNb++);
    +    {   ZSTDMT_CCtx* mtctx = ZSTDMT_createCCtx(2);
    +        if (mtctx==NULL) {
    +            DISPLAY("mtctx : mot enough memory, aborting \n");
    +            testResult = 1;
    +            goto _end;
    +        }
    +        DISPLAYLEVEL(4, "OK \n");
    +
    +        DISPLAYLEVEL(4, "test%3i : compress %u bytes with 2 threads : ", testNb++, (U32)CNBuffSize);
    +        CHECKPLUS(r, ZSTDMT_compressCCtx(mtctx,
    +                                compressedBuffer, ZSTD_compressBound(CNBuffSize),
    +                                CNBuffer, CNBuffSize,
    +                                1),
    +                  cSize=r );
    +        DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBuffSize*100);
    +
    +        DISPLAYLEVEL(4, "test%3i : decompressed size test : ", testNb++);
    +        {   unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize);
    +            if (rSize != CNBuffSize)  {
    +                DISPLAY("ZSTD_getFrameContentSize incorrect : %u != %u \n", (U32)rSize, (U32)CNBuffSize);
    +                goto _output_error;
    +        }   }
    +        DISPLAYLEVEL(4, "OK \n");
    +
    +        DISPLAYLEVEL(4, "test%3i : decompress %u bytes : ", testNb++, (U32)CNBuffSize);
    +        { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);
    +          if (r != CNBuffSize) goto _output_error; }
    +        DISPLAYLEVEL(4, "OK \n");
    +
    +        DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
    +        {   size_t u;
    +            for (u=0; u "); DISPLAY(__VA_ARGS__); \
                              DISPLAY(" (seed %u, test nb %u)  \n", seed, testNb); goto _output_error; }
     
    -static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxDurationS, double compressibility)
    +static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxDurationS, double compressibility, int bigTests)
     {
         static const U32 maxSrcLog = 23;
         static const U32 maxSampleLog = 22;
    @@ -636,6 +766,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD
         U32 coreSeed = seed, lseed = 0;
         clock_t const startClock = clock();
         clock_t const maxClockSpan = maxDurationS * CLOCKS_PER_SEC;
    +    int const cLevelLimiter = bigTests ? 3 : 2;
     
         /* allocation */
         cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
    @@ -662,7 +793,6 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD
         for ( ; (testNb <= nbTests) || (FUZ_clockSpan(startClock) < maxClockSpan); testNb++ ) {
             size_t sampleSize, maxTestSize, totalTestSize;
             size_t cSize, totalCSize, totalGenSize;
    -        XXH64_state_t xxhState;
             U64 crcOrig;
             BYTE* sampleBuffer;
             const BYTE* dict;
    @@ -701,7 +831,10 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD
             crcOrig = XXH64(sampleBuffer, sampleSize, 0);
     
             /* compression tests */
    -        {   unsigned const cLevel = (FUZ_rand(&lseed) % (ZSTD_maxCLevel() - (FUZ_highbit32((U32)sampleSize)/3))) + 1;
    +        {   unsigned const cLevel =
    +                    ( FUZ_rand(&lseed) %
    +                     (ZSTD_maxCLevel() - (FUZ_highbit32((U32)sampleSize) / cLevelLimiter)) )
    +                     + 1;
                 cSize = ZSTD_compressCCtx(ctx, cBuffer, cBufferSize, sampleBuffer, sampleSize, cLevel);
                 CHECK(ZSTD_isError(cSize), "ZSTD_compressCCtx failed : %s", ZSTD_getErrorName(cSize));
     
    @@ -801,7 +934,10 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD
     
             {   U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;
                 U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;
    -            int const cLevel = (FUZ_rand(&lseed) % (ZSTD_maxCLevel() - (MAX(testLog, dictLog)/3))) + 1;
    +            int const cLevel = (FUZ_rand(&lseed) %
    +                                (ZSTD_maxCLevel() -
    +                                 (MAX(testLog, dictLog) / cLevelLimiter))) +
    +                               1;
                 maxTestSize = FUZ_rLogLength(&lseed, testLog);
                 if (maxTestSize >= dstBufferSize) maxTestSize = dstBufferSize-1;
     
    @@ -813,22 +949,22 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD
                     CHECK (ZSTD_isError(errorCode), "ZSTD_compressBegin_usingDict error : %s", ZSTD_getErrorName(errorCode));
                 } else {
                     ZSTD_compressionParameters const cPar = ZSTD_getCParams(cLevel, 0, dictSize);
    -                ZSTD_frameParameters const fpar = { FUZ_rand(&lseed)&1 /* contentSizeFlag */,
    +                ZSTD_frameParameters const fPar = { FUZ_rand(&lseed)&1 /* contentSizeFlag */,
                                                         !(FUZ_rand(&lseed)&3) /* contentChecksumFlag*/,
                                                         0 /*NodictID*/ };   /* note : since dictionary is fake, dictIDflag has no impact */
    -                ZSTD_parameters p;
    -                size_t errorCode;
    -                p.cParams = cPar; p.fParams = fpar;
    -                errorCode = ZSTD_compressBegin_advanced(refCtx, dict, dictSize, p, 0);
    +                ZSTD_parameters const p = FUZ_makeParams(cPar, fPar);
    +                size_t const errorCode = ZSTD_compressBegin_advanced(refCtx, dict, dictSize, p, 0);
                     CHECK (ZSTD_isError(errorCode), "ZSTD_compressBegin_advanced error : %s", ZSTD_getErrorName(errorCode));
                 }
                 {   size_t const errorCode = ZSTD_copyCCtx(ctx, refCtx, 0);
                     CHECK (ZSTD_isError(errorCode), "ZSTD_copyCCtx error : %s", ZSTD_getErrorName(errorCode));
             }   }
    -        XXH64_reset(&xxhState, 0);
             ZSTD_setCCtxParameter(ctx, ZSTD_p_forceWindow, FUZ_rand(&lseed) & 1);
    +
             {   U32 const nbChunks = (FUZ_rand(&lseed) & 127) + 2;
                 U32 n;
    +            XXH64_state_t xxhState;
    +            XXH64_reset(&xxhState, 0);
                 for (totalTestSize=0, cSize=0, n=0 ; n MAX_UINT */
    +static unsigned readU32FromChar(const char** stringPtr)
    +{
    +    unsigned result = 0;
    +    while ((**stringPtr >='0') && (**stringPtr <='9'))
    +        result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
    +    if ((**stringPtr=='K') || (**stringPtr=='M')) {
    +        result <<= 10;
    +        if (**stringPtr=='M') result <<= 10;
    +        (*stringPtr)++ ;
    +        if (**stringPtr=='i') (*stringPtr)++;
    +        if (**stringPtr=='B') (*stringPtr)++;
    +    }
    +    return result;
    +}
     
     int main(int argc, const char** argv)
     {
    -    U32 seed=0;
    -    int seedset=0;
    +    U32 seed = 0;
    +    int seedset = 0;
         int argNb;
         int nbTests = nbTestsDefault;
         int testNb = 0;
         U32 proba = FUZ_compressibility_default;
    -    int result=0;
    +    int result = 0;
         U32 mainPause = 0;
         U32 maxDuration = 0;
    -    const char* programName = argv[0];
    +    int bigTests = 1;
    +    const char* const programName = argv[0];
     
         /* Check command line */
         for (argNb=1; argNb='0') && (*argument<='9')) {
    -                        nbTests *= 10;
    -                        nbTests += *argument - '0';
    -                        argument++;
    -                    }
    +                    argument++; maxDuration = 0;
    +                    nbTests = readU32FromChar(&argument);
                         break;
     
                     case 'T':
                         argument++;
    -                    nbTests=0; maxDuration=0;
    -                    while ((*argument>='0') && (*argument<='9')) {
    -                        maxDuration *= 10;
    -                        maxDuration += *argument - '0';
    -                        argument++;
    -                    }
    -                    if (*argument=='m') maxDuration *=60, argument++;
    +                    nbTests = 0;
    +                    maxDuration = readU32FromChar(&argument);
    +                    if (*argument=='s') argument++;   /* seconds */
    +                    if (*argument=='m') maxDuration *= 60, argument++;   /* minutes */
                         if (*argument=='n') argument++;
                         break;
     
                     case 's':
                         argument++;
    -                    seed=0;
    -                    seedset=1;
    -                    while ((*argument>='0') && (*argument<='9')) {
    -                        seed *= 10;
    -                        seed += *argument - '0';
    -                        argument++;
    -                    }
    +                    seedset = 1;
    +                    seed = readU32FromChar(&argument);
                         break;
     
                     case 't':
                         argument++;
    -                    testNb=0;
    -                    while ((*argument>='0') && (*argument<='9')) {
    -                        testNb *= 10;
    -                        testNb += *argument - '0';
    -                        argument++;
    -                    }
    +                    testNb = readU32FromChar(&argument);
                         break;
     
                     case 'P':   /* compressibility % */
                         argument++;
    -                    proba=0;
    -                    while ((*argument>='0') && (*argument<='9')) {
    -                        proba *= 10;
    -                        proba += *argument - '0';
    -                        argument++;
    -                    }
    -                    if (proba>100) proba=100;
    +                    proba = readU32FromChar(&argument);
    +                    if (proba>100) proba = 100;
                         break;
     
                     default:
    -                    return FUZ_usage(programName);
    +                    return (FUZ_usage(programName), 1);
         }   }   }   }   /* for (argNb=1; argNb (b) ? (a) : (b) )
    +
     
     /*-************************************
     *  Benchmark Parameters
    @@ -106,7 +111,11 @@ static size_t BMK_findMaxMem(U64 requiredMem)
     }
     
     
    -#  define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
    +static U32 FUZ_rotl32(U32 x, U32 r)
    +{
    +    return ((x << r) | (x >> (32 - r)));
    +}
    +
     U32 FUZ_rand(U32* src)
     {
         const U32 prime1 = 2654435761U;
    @@ -125,7 +134,7 @@ U32 FUZ_rand(U32* src)
     *********************************************************/
     typedef struct {
         size_t cSize;
    -    double cSpeed;
    +    double cSpeed;   /* bytes / sec */
         double dSpeed;
     } BMK_result_t;
     
    @@ -141,8 +150,6 @@ typedef struct
     } blockParam_t;
     
     
    -#define MIN(a,b)  ( (a) < (b) ? (a) : (b) )
    -
     static size_t BMK_benchParam(BMK_result_t* resultPtr,
                                  const void* srcBuffer, size_t srcSize,
                                  ZSTD_CCtx* ctx,
    @@ -165,6 +172,11 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr,
         char name[30] = { 0 };
         U64 crcOrig;
     
    +    /* init result for early exit */
    +    resultPtr->cSize = srcSize;
    +    resultPtr->cSpeed = 0.;
    +    resultPtr->dSpeed = 0.;
    +
         /* Memory allocation & restrictions */
         snprintf(name, 30, "Sw%02uc%02uh%02us%02ul%1ut%03uS%1u", Wlog, Clog, Hlog, Slog, Slength, Tlength, strat);
         if (!compressedBuffer || !resultBuffer || !blockTable) {
    @@ -206,7 +218,6 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr,
             size_t cSize = 0;
             double fastestC = 100000000., fastestD = 100000000.;
             double ratio = 0.;
    -        U64 crcCheck = 0;
             clock_t const benchStart = clock();
     
             DISPLAY("\r%79s\r", "");
    @@ -242,8 +253,8 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr,
                 cSize = 0;
                 for (blockNb=0; blockNb", loopNb, name, (U32)srcSize);
                 DISPLAY(" %9u (%4.3f),%7.1f MB/s", (U32)cSize, ratio, (double)srcSize / fastestC / 1000000.);
    @@ -273,18 +284,18 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr,
                 resultPtr->dSpeed = (double)srcSize / fastestD;
     
                 /* CRC Checking */
    -            crcCheck = XXH64(resultBuffer, srcSize, 0);
    -            if (crcOrig!=crcCheck) {
    -                unsigned u;
    -                unsigned eBlockSize = (unsigned)(MIN(65536*2, blockSize));
    -                DISPLAY("\n!!! WARNING !!! Invalid Checksum : %x != %x\n", (unsigned)crcOrig, (unsigned)crcCheck);
    -                for (u=0; u> 3) & PARAMTABLEMASK]
     
     
    -#define MAX(a,b)   ( (a) > (b) ? (a) : (b) )
    -
     static void playAround(FILE* f, winnerInfo_t* winners,
                            ZSTD_compressionParameters params,
                            const void* srcBuffer, size_t srcSize,
    @@ -711,6 +720,14 @@ int benchFiles(const char** fileNamesTable, int nbFiles)
     }
     
     
    +static void BMK_translateAdvancedParams(ZSTD_compressionParameters params)
    +{
    +    DISPLAY("--zstd=windowLog=%u,chainLog=%u,hashLog=%u,searchLog=%u,searchLength=%u,targetLength=%u,strategy=%u \n",
    +             params.windowLog, params.chainLog, params.hashLog, params.searchLog, params.searchLength, params.targetLength, (U32)(params.strategy));
    +}
    +
    +/* optimizeForSize():
    + * targetSpeed : expressed in MB/s */
     int optimizeForSize(const char* inFileName, U32 targetSpeed)
     {
         FILE* const inFile = fopen( inFileName, "rb" );
    @@ -723,8 +740,11 @@ int optimizeForSize(const char* inFileName, U32 targetSpeed)
     
         /* Memory allocation & restrictions */
         if ((U64)benchedSize > inFileSize) benchedSize = (size_t)inFileSize;
    -    if (benchedSize < inFileSize)
    -        DISPLAY("Not enough memory for '%s' full size; testing %i MB only...\n", inFileName, (int)(benchedSize>>20));
    +    if (benchedSize < inFileSize) {
    +        DISPLAY("Not enough memory for '%s' \n", inFileName);
    +        fclose(inFile);
    +        return 11;
    +    }
     
         /* Alloc */
         origBuff = malloc(benchedSize);
    @@ -747,10 +767,9 @@ int optimizeForSize(const char* inFileName, U32 targetSpeed)
         /* bench */
         DISPLAY("\r%79s\r", "");
         DISPLAY("optimizing for %s - limit speed %u MB/s \n", inFileName, targetSpeed);
    -    targetSpeed *= 1000;
    +    targetSpeed *= 1000000;
     
         {   ZSTD_CCtx* const ctx = ZSTD_createCCtx();
    -        ZSTD_compressionParameters params;
             winnerInfo_t winner;
             BMK_result_t candidate;
             const size_t blockSize = g_blockSize ? g_blockSize : benchedSize;
    @@ -764,26 +783,28 @@ int optimizeForSize(const char* inFileName, U32 targetSpeed)
             {   const int maxSeeds = g_noSeed ? 1 : ZSTD_maxCLevel();
                 int i;
                 for (i=1; i<=maxSeeds; i++) {
    -                params = ZSTD_getCParams(i, blockSize, 0);
    -                BMK_benchParam(&candidate, origBuff, benchedSize, ctx, params);
    +                ZSTD_compressionParameters const CParams = ZSTD_getCParams(i, blockSize, 0);
    +                BMK_benchParam(&candidate, origBuff, benchedSize, ctx, CParams);
                     if (candidate.cSpeed < targetSpeed)
                         break;
                     if ( (candidate.cSize < winner.result.cSize)
                        | ((candidate.cSize == winner.result.cSize) & (candidate.cSpeed > winner.result.cSpeed)) )
                     {
    -                    winner.params = params;
    +                    winner.params = CParams;
                         winner.result = candidate;
                         BMK_printWinner(stdout, i, winner.result, winner.params, benchedSize);
                 }   }
             }
             BMK_printWinner(stdout, 99, winner.result, winner.params, benchedSize);
    +        BMK_translateAdvancedParams(winner.params);
     
             /* start tests */
             {   time_t const grillStart = time(NULL);
                 do {
    -                params = winner.params;
    +                ZSTD_compressionParameters params = winner.params;
                     paramVariation(¶ms);
    -                if ((FUZ_rand(&g_rand) & 15) == 3) params = randomParams();
    +                if ((FUZ_rand(&g_rand) & 31) == 3) params = randomParams();  /* totally random config to improve search space */
    +                params = ZSTD_adjustCParams(params, blockSize, 0);
     
                     /* exclude faster if already played set of params */
                     if (FUZ_rand(&g_rand) & ((1 << NB_TESTS_PLAYED(params))-1)) continue;
    @@ -800,6 +821,7 @@ int optimizeForSize(const char* inFileName, U32 targetSpeed)
                         winner.params = params;
                         winner.result = candidate;
                         BMK_printWinner(stdout, 99, winner.result, winner.params, benchedSize);
    +                    BMK_translateAdvancedParams(winner.params);
                     }
                 } while (BMK_timeSpan(grillStart) < g_grillDuration_s);
             }
    @@ -833,7 +855,7 @@ static int usage_advanced(void)
         DISPLAY( " -T#    : set level 1 speed objective \n");
         DISPLAY( " -B#    : cut input into blocks of size # (default : single block) \n");
         DISPLAY( " -i#    : iteration loops [1-9](default : %i) \n", NBLOOPS);
    -    DISPLAY( " -O#    : find Optimized parameters for # target speed (default : 0) \n");
    +    DISPLAY( " -O#    : find Optimized parameters for # MB/s compression speed (default : 0) \n");
         DISPLAY( " -S     : Single run \n");
         DISPLAY( " -P#    : generated sample compressibility (default : %.1f%%) \n", COMPRESSIBILITY_DEFAULT * 100);
         return 0;
    diff --git a/tests/playTests.sh b/tests/playTests.sh
    index c493fed55358..021fd59fe2af 100755
    --- a/tests/playTests.sh
    +++ b/tests/playTests.sh
    @@ -11,6 +11,7 @@ roundTripTest() {
             local_p="$2"
         else
             local_c="$2"
    +        local_p=""
         fi
     
         rm -f tmp1 tmp2
    @@ -20,13 +21,36 @@ roundTripTest() {
         $DIFF -q tmp1 tmp2
     }
     
    +fileRoundTripTest() {
    +    if [ -n "$3" ]; then
    +        local_c="$3"
    +        local_p="$2"
    +    else
    +        local_c="$2"
    +        local_p=""
    +    fi
    +
    +    rm -f tmp.zstd tmp.md5.1 tmp.md5.2
    +    $ECHO "fileRoundTripTest: ./datagen $1 $local_p > tmp && $ZSTD -v$local_c -c tmp | $ZSTD -d"
    +    ./datagen $1 $local_p > tmp
    +    cat tmp | $MD5SUM > tmp.md5.1
    +    $ZSTD --ultra -v$local_c -c tmp | $ZSTD -d | $MD5SUM > tmp.md5.2
    +    $DIFF -q tmp.md5.1 tmp.md5.2
    +}
    +
    +isTerminal=false
    +if [ -t 0 ] && [ -t 1 ]
    +then
    +    isTerminal=true
    +fi
    +
     isWindows=false
    -ECHO="echo"
    +ECHO="echo -e"
     INTOVOID="/dev/null"
     case "$OS" in
       Windows*)
         isWindows=true
    -    ECHO="echo -e"
    +    INTOVOID="NUL"
         ;;
     esac
     
    @@ -42,11 +66,17 @@ case "$UNAME" in
       SunOS) DIFF="gdiff" ;;
     esac
     
    -
     $ECHO "\nStarting playTests.sh isWindows=$isWindows ZSTD='$ZSTD'"
     
     [ -n "$ZSTD" ] || die "ZSTD variable must be defined!"
     
    +if [ -n "$(echo hello | $ZSTD -v -T2 2>&1 > $INTOVOID | grep 'multi-threading is disabled')" ]
    +then
    +    hasMT=""
    +else
    +    hasMT="true"
    +fi
    +
     $ECHO "\n**** simple tests **** "
     
     ./datagen > tmp
    @@ -72,6 +102,12 @@ cp tmp tmp2
     $ZSTD tmp2 -fo && die "-o must be followed by filename "
     $ECHO "test : implied stdout when input is stdin"
     $ECHO bob | $ZSTD | $ZSTD -d
    +if [ "$isTerminal" = true ]; then
    +$ECHO "test : compressed data to terminal"
    +$ECHO bob | $ZSTD && die "should have refused : compressed data to terminal"
    +$ECHO "test : compressed data from terminal (a hang here is a test fail, zstd is wrongly waiting on data from terminal)"
    +$ZSTD -d > $INTOVOID && die "should have refused : compressed data from terminal"
    +fi
     $ECHO "test : null-length file roundtrip"
     $ECHO -n '' | $ZSTD - --stdout | $ZSTD -d --stdout
     $ECHO "test : decompress file with wrong suffix (must fail)"
    @@ -96,6 +132,14 @@ $ZSTD -q tmp && die "overwrite check failed!"
     $ECHO "test : force overwrite"
     $ZSTD -q -f tmp
     $ZSTD -q --force tmp
    +$ECHO "test : overwrite readonly file"
    +rm -f tmpro tmpro.zst
    +$ECHO foo > tmpro.zst
    +$ECHO foo > tmpro
    +chmod 400 tmpro.zst
    +$ZSTD -q tmpro && die "should have refused to overwrite read-only file"
    +$ZSTD -q -f tmpro
    +rm -f tmpro tmpro.zst
     $ECHO "test : file removal"
     $ZSTD -f --rm tmp
     ls tmp && die "tmp should no longer be present"
    @@ -156,6 +200,19 @@ $ECHO "$ECHO foo | $ZSTD > /dev/full"
     $ECHO foo | $ZSTD > /dev/full && die "write error not detected!"
     $ECHO "$ECHO foo | $ZSTD | $ZSTD -d > /dev/full"
     $ECHO foo | $ZSTD | $ZSTD -d > /dev/full && die "write error not detected!"
    +
    +$ECHO "\n**** symbolic link test **** "
    +
    +rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst
    +$ECHO "hello world" > hello.tmp
    +ln -s hello.tmp world.tmp
    +$ZSTD world.tmp hello.tmp
    +ls hello.tmp.zst || die "regular file should have been compressed!"
    +ls world.tmp.zst && die "symbolic link should not have been compressed!"
    +$ZSTD world.tmp hello.tmp -f
    +ls world.tmp.zst || die "symbol link should have been compressed with --force"
    +rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst
    +
     fi
     
     
    @@ -227,12 +284,12 @@ $ECHO "- Create second (different) dictionary "
     $ZSTD --train *.c ../programs/*.c ../programs/*.h -o tmpDictC
     $ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
     $ECHO "- Create dictionary with short dictID"
    -$ZSTD --train *.c ../programs/*.c --dictID 1 -o tmpDict1
    +$ZSTD --train *.c ../programs/*.c --dictID=1 -o tmpDict1
     cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
     $ECHO "- Create dictionary with wrong dictID parameter order (must fail)"
     $ZSTD --train *.c ../programs/*.c --dictID -o 1 tmpDict1 && die "wrong order : --dictID must be followed by argument "
     $ECHO "- Create dictionary with size limit"
    -$ZSTD --train *.c ../programs/*.c -o tmpDict2 --maxdict 4K -v
    +$ZSTD --train *.c ../programs/*.c -o tmpDict2 --maxdict=4K -v
     $ECHO "- Create dictionary with wrong parameter order (must fail)"
     $ZSTD --train *.c ../programs/*.c -o tmpDict2 --maxdict -v 4K && die "wrong order : --maxdict must be followed by argument "
     $ECHO "- Compress without dictID"
    @@ -240,7 +297,7 @@ $ZSTD -f tmp -D tmpDict1 --no-dictID
     $ZSTD -d tmp.zst -D tmpDict -fo result
     $DIFF $TESTFILE result
     $ECHO "- Compress with wrong argument order (must fail)"
    -$ZSTD tmp -Df tmpDict1 -c > /dev/null && die "-D must be followed by dictionary name "
    +$ZSTD tmp -Df tmpDict1 -c > $INTOVOID && die "-D must be followed by dictionary name "
     $ECHO "- Compress multiple files with dictionary"
     rm -rf dirTestDict
     mkdir dirTestDict
    @@ -255,6 +312,11 @@ case "$UNAME" in
       *) $MD5SUM -c tmph1 ;;
     esac
     rm -rf dirTestDict
    +$ECHO "- dictionary builder on bogus input"
    +$ECHO "Hello World" > tmp
    +$ZSTD --train-legacy -q tmp && die "Dictionary training should fail : not enough input source"
    +./datagen -P0 -g10M > tmp
    +$ZSTD --train-legacy -q tmp && die "Dictionary training should fail : source is pure noise"
     rm tmp*
     
     
    @@ -263,19 +325,39 @@ $ECHO "\n**** cover dictionary tests **** "
     TESTFILE=../programs/zstdcli.c
     ./datagen > tmpDict
     $ECHO "- Create first dictionary"
    -$ZSTD --train --cover=k=46,d=8 *.c ../programs/*.c -o tmpDict
    +$ZSTD --train-cover=k=46,d=8 *.c ../programs/*.c -o tmpDict
     cp $TESTFILE tmp
     $ZSTD -f tmp -D tmpDict
     $ZSTD -d tmp.zst -D tmpDict -fo result
     $DIFF $TESTFILE result
     $ECHO "- Create second (different) dictionary"
    -$ZSTD --train --cover=k=56,d=8 *.c ../programs/*.c ../programs/*.h -o tmpDictC
    +$ZSTD --train-cover=k=56,d=8 *.c ../programs/*.c ../programs/*.h -o tmpDictC
     $ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
     $ECHO "- Create dictionary with short dictID"
    -$ZSTD --train --cover=k=46,d=8 *.c ../programs/*.c --dictID 1 -o tmpDict1
    +$ZSTD --train-cover=k=46,d=8 *.c ../programs/*.c --dictID=1 -o tmpDict1
     cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
     $ECHO "- Create dictionary with size limit"
    -$ZSTD --train --optimize-cover=steps=8 *.c ../programs/*.c -o tmpDict2 --maxdict 4K
    +$ZSTD --train-cover=steps=8 *.c ../programs/*.c -o tmpDict2 --maxdict=4K
    +rm tmp*
    +
    +$ECHO "\n**** legacy dictionary tests **** "
    +
    +TESTFILE=../programs/zstdcli.c
    +./datagen > tmpDict
    +$ECHO "- Create first dictionary"
    +$ZSTD --train-legacy=selectivity=8 *.c ../programs/*.c -o tmpDict
    +cp $TESTFILE tmp
    +$ZSTD -f tmp -D tmpDict
    +$ZSTD -d tmp.zst -D tmpDict -fo result
    +$DIFF $TESTFILE result
    +$ECHO "- Create second (different) dictionary"
    +$ZSTD --train-legacy=s=5 *.c ../programs/*.c ../programs/*.h -o tmpDictC
    +$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
    +$ECHO "- Create dictionary with short dictID"
    +$ZSTD --train-legacy -s5 *.c ../programs/*.c --dictID=1 -o tmpDict1
    +cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
    +$ECHO "- Create dictionary with size limit"
    +$ZSTD --train-legacy -s9 *.c ../programs/*.c -o tmpDict2 --maxdict=4K
     rm tmp*
     
     
    @@ -341,7 +423,7 @@ if [ $GZIPMODE -eq 1 ]; then
         $ZSTD -f --format=gzip tmp
         $ZSTD -f tmp
         cat tmp.gz tmp.zst tmp.gz tmp.zst | $ZSTD -d -f -o tmp
    -    head -c -1 tmp.gz | $ZSTD -t && die "incomplete frame not detected !"
    +    head -c -1 tmp.gz | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
         rm tmp*
     else
         $ECHO "gzip mode not supported"
    @@ -383,13 +465,48 @@ if [ $LZMAMODE -eq 1 ]; then
         $ZSTD -f --format=lzma tmp
         $ZSTD -f tmp
         cat tmp.xz tmp.lzma tmp.zst tmp.lzma tmp.xz tmp.zst | $ZSTD -d -f -o tmp
    -    head -c -1 tmp.xz | $ZSTD -t && die "incomplete frame not detected !"
    -    head -c -1 tmp.lzma | $ZSTD -t && die "incomplete frame not detected !"
    +    head -c -1 tmp.xz | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
    +    head -c -1 tmp.lzma | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
         rm tmp*
     else
         $ECHO "xz mode not supported"
     fi
     
    +$ECHO "\n**** lz4 compatibility tests **** "
    +
    +LZ4MODE=1
    +$ZSTD --format=lz4 -V || LZ4MODE=0
    +if [ $LZ4MODE -eq 1 ]; then
    +    $ECHO "lz4 support detected"
    +    LZ4EXE=1
    +    lz4 -V || LZ4EXE=0
    +    if [ $LZ4EXE -eq 1 ]; then
    +        ./datagen > tmp
    +        $ZSTD --format=lz4 -f tmp
    +        lz4 -t -v tmp.lz4
    +        lz4 -f tmp
    +        $ZSTD -d -f -v tmp.lz4
    +        rm tmp*
    +    else
    +        $ECHO "lz4 binary not detected"
    +    fi
    +else
    +    $ECHO "lz4 mode not supported"
    +fi
    +
    +
    +$ECHO "\n**** lz4 frame tests **** "
    +
    +if [ $LZ4MODE -eq 1 ]; then
    +    ./datagen > tmp
    +    $ZSTD -f --format=lz4 tmp
    +    $ZSTD -f tmp
    +    cat tmp.lz4 tmp.zst tmp.lz4 tmp.zst | $ZSTD -d -f -o tmp
    +    head -c -1 tmp.lz4 | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
    +    rm tmp*
    +else
    +    $ECHO "lz4 mode not supported"
    +fi
     
     $ECHO "\n**** zstd round-trip tests **** "
     
    @@ -402,6 +519,19 @@ roundTripTest -g519K 6    # greedy, hash chain
     roundTripTest -g517K 16   # btlazy2
     roundTripTest -g516K 19   # btopt
     
    +fileRoundTripTest -g500K
    +
    +if [ -n "$hasMT" ]
    +then
    +    $ECHO "\n**** zstdmt round-trip tests **** "
    +    roundTripTest -g4M "1 -T0"
    +    roundTripTest -g8M "3 -T2"
    +    roundTripTest -g8000K "2 --threads=2"
    +    fileRoundTripTest -g4M "19 -T2 -B1M"
    +else
    +    $ECHO "\n**** no multithreading, skipping zstdmt tests **** "
    +fi
    +
     rm tmp*
     
     if [ "$1" != "--test-large-data" ]; then
    @@ -437,4 +567,16 @@ roundTripTest -g50000000 -P94 19
     roundTripTest -g99000000 -P99 20
     roundTripTest -g6000000000 -P99 1
     
    +fileRoundTripTest -g4193M -P99 1
    +
    +if [ -n "$hasMT" ]
    +then
    +    $ECHO "\n**** zstdmt long round-trip tests **** "
    +    roundTripTest -g99000000 -P99 "20 -T2"
    +    roundTripTest -g6000000000 -P99 "1 -T2"
    +    fileRoundTripTest -g4193M -P98 " -T0"
    +else
    +    $ECHO "\n**** no multithreading, skipping zstdmt tests **** "
    +fi
    +
     rm tmp*
    diff --git a/tests/test-zstd-speed.py b/tests/test-zstd-speed.py
    index 23d4f477c7f3..56108a5cae4c 100755
    --- a/tests/test-zstd-speed.py
    +++ b/tests/test-zstd-speed.py
    @@ -14,14 +14,15 @@
     # - dir1/zstd and dir2/zstd will be merged in a single results file
     
     import argparse
    -import os
    +import os           # getloadavg
     import string
     import subprocess
    -import time
    +import time         # strftime
     import traceback
     import hashlib
    +import platform     # system
     
    -script_version = 'v1.1.1 (2016-10-28)'
    +script_version = 'v1.1.2 (2017-03-26)'
     default_repo_url = 'https://github.com/facebook/zstd.git'
     working_dir_name = 'speedTest'
     working_path = os.getcwd() + '/' + working_dir_name     # /path/to/zstd/tests/speedTest
    @@ -152,10 +153,15 @@ def benchmark_and_compare(branch, commit, last_commit, args, executableName, md5
                 % (os.getloadavg()[0], args.maxLoadAvg, sleepTime))
             time.sleep(sleepTime)
         start_load = str(os.getloadavg())
    -    if args.dictionary:
    -        result = execute('programs/%s -rqi5b1e%s -D %s %s' % (executableName, args.lastCLevel, args.dictionary, testFilePath), print_output=True)
    +    osType = platform.system()
    +    if osType == 'Linux':
    +        cpuSelector = "taskset --cpu-list 0"
         else:
    -        result = execute('programs/%s -rqi5b1e%s %s' % (executableName, args.lastCLevel, testFilePath), print_output=True)   
    +        cpuSelector = ""
    +    if args.dictionary:
    +        result = execute('%s programs/%s -rqi5b1e%s -D %s %s' % (cpuSelector, executableName, args.lastCLevel, args.dictionary, testFilePath), print_output=True)
    +    else:
    +        result = execute('%s programs/%s -rqi5b1e%s %s' % (cpuSelector, executableName, args.lastCLevel, testFilePath), print_output=True)
         end_load = str(os.getloadavg())
         linesExpected = args.lastCLevel + 1
         if len(result) != linesExpected:
    @@ -291,7 +297,7 @@ def test_commit(branch, commit, last_commit, args, testFilePaths, have_mutt, hav
             log("ERROR: e-mail senders 'mail' or 'mutt' not found")
             exit(1)
     
    -    clang_version = execute("clang -v 2>&1 | grep 'clang version' | sed -e 's:.*version \\([0-9.]*\\).*:\\1:' -e 's:\\.\\([0-9][0-9]\\):\\1:g'", verbose)[0];
    +    clang_version = execute("clang -v 2>&1 | grep ' version ' | sed -e 's:.*version \\([0-9.]*\\).*:\\1:' -e 's:\\.\\([0-9][0-9]\\):\\1:g'", verbose)[0];
         gcc_version = execute("gcc -dumpversion", verbose)[0];
     
         if verbose:
    diff --git a/tests/zbufftest.c b/tests/zbufftest.c
    index 14b73923311d..601aa808d027 100644
    --- a/tests/zbufftest.c
    +++ b/tests/zbufftest.c
    @@ -60,7 +60,7 @@ static U32 g_displayLevel = 2;
     #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
                 if ((FUZ_GetClockSpan(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \
                 { g_displayClock = clock(); DISPLAY(__VA_ARGS__); \
    -            if (g_displayLevel>=4) fflush(stdout); } }
    +            if (g_displayLevel>=4) fflush(stderr); } }
     static const clock_t g_refreshRate = CLOCKS_PER_SEC * 15 / 100;
     static clock_t g_displayClock = 0;
     
    diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c
    index aa7367bcfd31..0e09e185642b 100644
    --- a/tests/zstreamtest.c
    +++ b/tests/zstreamtest.c
    @@ -59,7 +59,7 @@ static U32 g_displayLevel = 2;
     #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
                 if ((FUZ_GetClockSpan(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \
                 { g_displayClock = clock(); DISPLAY(__VA_ARGS__); \
    -            if (g_displayLevel>=4) fflush(stdout); } }
    +            if (g_displayLevel>=4) fflush(stderr); } }
     static const clock_t g_refreshRate = CLOCKS_PER_SEC / 6;
     static clock_t g_displayClock = 0;
     
    @@ -131,7 +131,7 @@ static buffer_t FUZ_createDictionary(const void* src, size_t srcSize, size_t blo
         }
         {   size_t const dictSize = ZDICT_trainFromBuffer(dict.start, requestedDictSize, src, blockSizes, (unsigned)nbBlocks);
             free(blockSizes);
    -        if (ZDICT_isError(dictSize)) { free(dict.start); return (buffer_t){ NULL, 0, 0 }; }
    +        if (ZDICT_isError(dictSize)) { free(dict.start); return g_nullBuffer; }
             dict.size = requestedDictSize;
             dict.filled = dictSize;
             return dict;   /* how to return dictSize ? */
    @@ -207,6 +207,16 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
           DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
         }
     
    +    /* Attempt bad compression parameters */
    +    DISPLAYLEVEL(3, "test%3i : use bad compression parameters : ", testNb++);
    +    {   size_t r;
    +        ZSTD_parameters params = ZSTD_getParams(1, 0, 0);
    +        params.cParams.searchLength = 2;
    +        r = ZSTD_initCStream_advanced(zc, NULL, 0, params, 0);
    +        if (!ZSTD_isError(r)) goto _output_error;
    +        DISPLAYLEVEL(3, "init error : %s \n", ZSTD_getErrorName(r));
    +    }
    +
         /* skippable frame test */
         DISPLAYLEVEL(3, "test%3i : decompress skippable frame : ", testNb++);
         ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
    @@ -438,11 +448,64 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
           if (!ZSTD_isError(r)) goto _output_error;  /* must fail : frame requires > 100 bytes */
           DISPLAYLEVEL(3, "OK (%s)\n", ZSTD_getErrorName(r)); }
     
    -    /* Unknown srcSize */
    +    DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_usingCDict_advanced with masked dictID : ", testNb++);
    +    {   ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictionary.filled);
    +        ZSTD_frameParameters const fParams = { 1 /* contentSize */, 1 /* checksum */, 1 /* noDictID */};
    +        ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, 1 /* byReference */, cParams, customMem);
    +        size_t const initError = ZSTD_initCStream_usingCDict_advanced(zc, cdict, CNBufferSize, fParams);
    +        if (ZSTD_isError(initError)) goto _output_error;
    +        cSize = 0;
    +        outBuff.dst = compressedBuffer;
    +        outBuff.size = compressedBufferSize;
    +        outBuff.pos = 0;
    +        inBuff.src = CNBuffer;
    +        inBuff.size = CNBufferSize;
    +        inBuff.pos = 0;
    +        { size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff);
    +          if (ZSTD_isError(r)) goto _output_error; }
    +        if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */
    +        { size_t const r = ZSTD_endStream(zc, &outBuff);
    +          if (r != 0) goto _output_error; }  /* error, or some data not flushed */
    +        cSize = outBuff.pos;
    +        ZSTD_freeCDict(cdict);
    +        DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/CNBufferSize*100);
    +    }
    +
    +    DISPLAYLEVEL(3, "test%3i : try retrieving dictID from frame : ", testNb++);
    +    {   U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize);
    +        if (did != 0) goto _output_error;
    +    }
    +    DISPLAYLEVEL(3, "OK (not detected) \n");
    +
    +    DISPLAYLEVEL(3, "test%3i : decompress without dictionary : ", testNb++);
    +    {   size_t const r = ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize);
    +        if (!ZSTD_isError(r)) goto _output_error;  /* must fail : dictionary not used */
    +        DISPLAYLEVEL(3, "OK (%s)\n", ZSTD_getErrorName(r));
    +    }
    +
    +    /* Empty srcSize */
    +    DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_advanced with pledgedSrcSize=0 and dict : ", testNb++);
    +    {   ZSTD_parameters params = ZSTD_getParams(5, 0, 0);
    +        params.fParams.contentSizeFlag = 1;
    +        ZSTD_initCStream_advanced(zc, dictionary.start, dictionary.filled, params, 0);
    +    } /* cstream advanced shall write content size = 0 */
    +    inBuff.src = CNBuffer;
    +    inBuff.size = 0;
    +    inBuff.pos = 0;
    +    outBuff.dst = compressedBuffer;
    +    outBuff.size = compressedBufferSize;
    +    outBuff.pos = 0;
    +    if (ZSTD_isError(ZSTD_compressStream(zc, &outBuff, &inBuff))) goto _output_error;
    +    if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error;
    +    cSize = outBuff.pos;
    +    if (ZSTD_findDecompressedSize(compressedBuffer, cSize) != 0) goto _output_error;
    +    DISPLAYLEVEL(3, "OK \n");
    +
         DISPLAYLEVEL(3, "test%3i : pledgedSrcSize == 0 behaves properly : ", testNb++);
         {   ZSTD_parameters params = ZSTD_getParams(5, 0, 0);
             params.fParams.contentSizeFlag = 1;
    -        ZSTD_initCStream_advanced(zc, NULL, 0, params, 0); } /* cstream advanced should write the 0 size field */
    +        ZSTD_initCStream_advanced(zc, NULL, 0, params, 0);
    +    } /* cstream advanced shall write content size = 0 */
         inBuff.src = CNBuffer;
         inBuff.size = 0;
         inBuff.pos = 0;
    @@ -552,7 +615,7 @@ static size_t FUZ_randomLength(U32* seed, U32 maxLog)
     #define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
                              DISPLAY(" (seed %u, test nb %u)  \n", seed, testNb); goto _output_error; }
     
    -static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibility)
    +static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibility, int bigTests)
     {
         static const U32 maxSrcLog = 24;
         static const U32 maxSampleLog = 19;
    @@ -574,6 +637,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
         const BYTE* dict=NULL;   /* can keep same dict on 2 consecutive tests */
         size_t dictSize = 0;
         U32 oldTestLog = 0;
    +    int const cLevelLimiter = bigTests ? 3 : 2;
     
         /* allocations */
         cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
    @@ -638,7 +702,8 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
             if ((FUZ_rand(&lseed)&1) /* at beginning, to keep same nb of rand */
                 && oldTestLog /* at least one test happened */ && resetAllowed) {
                 maxTestSize = FUZ_randomLength(&lseed, oldTestLog+2);
    -            if (maxTestSize >= srcBufferSize) maxTestSize = srcBufferSize-1;
    +            if (maxTestSize >= srcBufferSize)
    +                maxTestSize = srcBufferSize-1;
                 {   U64 const pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? 0 : maxTestSize;
                     size_t const resetError = ZSTD_resetCStream(zc, pledgedSrcSize);
                     CHECK(ZSTD_isError(resetError), "ZSTD_resetCStream error : %s", ZSTD_getErrorName(resetError));
    @@ -646,11 +711,14 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
             } else {
                 U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;
                 U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;
    -            U32 const cLevel = (FUZ_rand(&lseed) % (ZSTD_maxCLevel() - (MAX(testLog, dictLog)/3))) + 1;
    +            U32 const cLevel = ( FUZ_rand(&lseed) %
    +                                (ZSTD_maxCLevel() -
    +                                (MAX(testLog, dictLog) / cLevelLimiter)))
    +                                 + 1;
                 maxTestSize = FUZ_rLogLength(&lseed, testLog);
                 oldTestLog = testLog;
                 /* random dictionary selection */
    -            dictSize  = ((FUZ_rand(&lseed)&63)==1) ? FUZ_rLogLength(&lseed, dictLog) : 0;
    +            dictSize  = ((FUZ_rand(&lseed)&1)==1) ? FUZ_rLogLength(&lseed, dictLog) : 0;
                 {   size_t const dictStart = FUZ_rand(&lseed) % (srcBufferSize - dictSize);
                     dict = srcBuffer + dictStart;
                 }
    @@ -785,7 +853,7 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
     
     
     /* Multi-threading version of fuzzer Tests */
    -static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double compressibility)
    +static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double compressibility, int bigTests)
     {
         static const U32 maxSrcLog = 24;
         static const U32 maxSampleLog = 19;
    @@ -807,6 +875,7 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
         const BYTE* dict=NULL;   /* can keep same dict on 2 consecutive tests */
         size_t dictSize = 0;
         U32 oldTestLog = 0;
    +    int const cLevelLimiter = bigTests ? 3 : 2;
     
         /* allocations */
         cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
    @@ -851,6 +920,7 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
             /* some issues can only happen when reusing states */
             if ((FUZ_rand(&lseed) & 0xFF) == 131) {
                 U32 const nbThreads = (FUZ_rand(&lseed) % 6) + 1;
    +            DISPLAYLEVEL(5, "Creating new context with %u threads \n", nbThreads);
                 ZSTDMT_freeCCtx(zc);
                 zc = ZSTDMT_createCCtx(nbThreads);
                 resetAllowed=0;
    @@ -888,7 +958,10 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
             } else {
                 U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;
                 U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;
    -            U32 const cLevel = (FUZ_rand(&lseed) % (ZSTD_maxCLevel() - (MAX(testLog, dictLog)/3))) + 1;
    +            U32 const cLevel = (FUZ_rand(&lseed) %
    +                                (ZSTD_maxCLevel() -
    +                                 (MAX(testLog, dictLog) / cLevelLimiter))) +
    +                               1;
                 maxTestSize = FUZ_rLogLength(&lseed, testLog);
                 oldTestLog = testLog;
                 /* random dictionary selection */
    @@ -898,9 +971,12 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
                 }
                 {   U64 const pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? 0 : maxTestSize;
                     ZSTD_parameters params = ZSTD_getParams(cLevel, pledgedSrcSize, dictSize);
    -                DISPLAYLEVEL(5, "Init with windowLog = %u \n", params.cParams.windowLog);
    +                DISPLAYLEVEL(5, "Init with windowLog = %u and pledgedSrcSize = %u \n",
    +                    params.cParams.windowLog, (U32)pledgedSrcSize);
                     params.fParams.checksumFlag = FUZ_rand(&lseed) & 1;
                     params.fParams.noDictIDFlag = FUZ_rand(&lseed) & 1;
    +                params.fParams.contentSizeFlag = pledgedSrcSize>0;
    +                DISPLAYLEVEL(5, "checksumFlag : %u \n", params.fParams.checksumFlag);
                     { size_t const initError = ZSTDMT_initCStream_advanced(zc, dict, dictSize, params, pledgedSrcSize);
                       CHECK (ZSTD_isError(initError),"ZSTDMT_initCStream_advanced error : %s", ZSTD_getErrorName(initError)); }
                     ZSTDMT_setMTCtxParameter(zc, ZSTDMT_p_overlapSectionLog, FUZ_rand(&lseed) % 12);
    @@ -938,7 +1014,7 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
                         outBuff.size = outBuff.pos + adjustedDstSize;
                         DISPLAYLEVEL(5, "Flushing into dst buffer of size %u \n", (U32)adjustedDstSize);
                         {   size_t const flushError = ZSTDMT_flushStream(zc, &outBuff);
    -                        CHECK (ZSTD_isError(flushError), "flush error : %s", ZSTD_getErrorName(flushError));
    +                        CHECK (ZSTD_isError(flushError), "ZSTDMT_flushStream error : %s", ZSTD_getErrorName(flushError));
                 }   }   }
     
                 /* final frame epilogue */
    @@ -949,12 +1025,12 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
                         outBuff.size = outBuff.pos + adjustedDstSize;
                         DISPLAYLEVEL(5, "Ending into dst buffer of size %u \n", (U32)adjustedDstSize);
                         remainingToFlush = ZSTDMT_endStream(zc, &outBuff);
    -                    CHECK (ZSTD_isError(remainingToFlush), "flush error : %s", ZSTD_getErrorName(remainingToFlush));
    +                    CHECK (ZSTD_isError(remainingToFlush), "ZSTDMT_endStream error : %s", ZSTD_getErrorName(remainingToFlush));
                         DISPLAYLEVEL(5, "endStream : remainingToFlush : %u \n", (U32)remainingToFlush);
                 }   }
    -            DISPLAYLEVEL(5, "Frame completed \n");
                 crcOrig = XXH64_digest(&xxhState);
                 cSize = outBuff.pos;
    +            DISPLAYLEVEL(5, "Frame completed : %u bytes \n", (U32)cSize);
             }
     
             /* multi - fragments decompression test */
    @@ -972,8 +1048,10 @@ static int fuzzerTests_MT(U32 seed, U32 nbTests, unsigned startTest, double comp
                     size_t const dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize);
                     inBuff.size = inBuff.pos + readCSrcSize;
                     outBuff.size = inBuff.pos + dstBuffSize;
    +                DISPLAYLEVEL(5, "ZSTD_decompressStream input %u bytes \n", (U32)readCSrcSize);
                     decompressionResult = ZSTD_decompressStream(zd, &outBuff, &inBuff);
                     CHECK (ZSTD_isError(decompressionResult), "decompression error : %s", ZSTD_getErrorName(decompressionResult));
    +                DISPLAYLEVEL(5, "inBuff.pos = %u \n", (U32)readCSrcSize);
                 }
                 CHECK (outBuff.pos != totalTestSize, "decompressed data : wrong size (%u != %u)", (U32)outBuff.pos, (U32)totalTestSize);
                 CHECK (inBuff.pos != cSize, "compressed data should be fully read (%u != %u)", (U32)inBuff.pos, (U32)cSize);
    @@ -1063,6 +1141,7 @@ int main(int argc, const char** argv)
         int result=0;
         int mainPause = 0;
         int mtOnly = 0;
    +    int bigTests = 1;
         const char* const programName = argv[0];
         ZSTD_customMem const customMem = { allocFunction, freeFunction, NULL };
         ZSTD_customMem const customNULL = { NULL, NULL, NULL };
    @@ -1076,6 +1155,7 @@ int main(int argc, const char** argv)
             if (argument[0]=='-') {
     
                 if (!strcmp(argument, "--mt")) { mtOnly=1; continue; }
    +            if (!strcmp(argument, "--no-big-tests")) { bigTests=0; continue; }
     
                 argument++;
                 while (*argument!=0) {
    @@ -1181,8 +1261,8 @@ int main(int argc, const char** argv)
                 result = basicUnitTests(0, ((double)proba) / 100, customMem);  /* use custom memory allocation functions */
         }   }
     
    -    if (!result && !mtOnly) result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
    -    if (!result) result = fuzzerTests_MT(seed, nbTests, testNb, ((double)proba) / 100);
    +    if (!result && !mtOnly) result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100, bigTests);
    +    if (!result) result = fuzzerTests_MT(seed, nbTests, testNb, ((double)proba) / 100, bigTests);
     
         if (mainPause) {
             int unused;
    diff --git a/zlibWrapper/examples/zwrapbench.c b/zlibWrapper/examples/zwrapbench.c
    index 23c3ca4dab8f..a57ed51ec141 100644
    --- a/zlibWrapper/examples/zwrapbench.c
    +++ b/zlibWrapper/examples/zwrapbench.c
    @@ -73,13 +73,13 @@ static U32 g_compressibilityDefault = 50;
     #define DEFAULT_DISPLAY_LEVEL 2
     #define DISPLAY(...)         fprintf(displayOut, __VA_ARGS__)
     #define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
    -static U32 g_displayLevel = DEFAULT_DISPLAY_LEVEL;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */
    +static int g_displayLevel = DEFAULT_DISPLAY_LEVEL;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */
     static FILE* displayOut;
     
     #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
                 if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \
                 { g_time = clock(); DISPLAY(__VA_ARGS__); \
    -            if (g_displayLevel>=4) fflush(stdout); } }
    +            if (g_displayLevel>=4) fflush(displayOut); } }
     static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
     static clock_t g_time = 0;
     
    @@ -128,6 +128,11 @@ void BMK_SetBlockSize(size_t blockSize)
     /* ********************************************************
     *  Bench functions
     **********************************************************/
    +#undef MIN
    +#undef MAX
    +#define MIN(a,b) ((a)<(b) ? (a) : (b))
    +#define MAX(a,b) ((a)>(b) ? (a) : (b))
    +
     typedef struct
     {
         z_const char* srcPtr;
    @@ -142,9 +147,6 @@ typedef struct
     typedef enum { BMK_ZSTD, BMK_ZSTD_STREAM, BMK_ZLIB, BMK_ZWRAP_ZLIB, BMK_ZWRAP_ZSTD, BMK_ZLIB_REUSE, BMK_ZWRAP_ZLIB_REUSE, BMK_ZWRAP_ZSTD_REUSE } BMK_compressor;
     
     
    -#define MIN(a,b) ((a)<(b) ? (a) : (b))
    -#define MAX(a,b) ((a)>(b) ? (a) : (b))
    -
     static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
                             const char* displayName, int cLevel,
                             const size_t* fileSizes, U32 nbFiles,
    @@ -234,7 +236,7 @@ static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
                     if (compressor == BMK_ZSTD) {
                         ZSTD_parameters const zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize);
                         ZSTD_customMem const cmem = { NULL, NULL, NULL };
    -                    ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, 1, zparams, cmem);
    +                    ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, 1, zparams.cParams, cmem);
                         if (cdict==NULL) EXM_THROW(1, "ZSTD_createCDict_advanced() allocation failure");
     
                         do {
    @@ -982,7 +984,7 @@ int main(int argCount, char** argv)
     
     #ifdef UTIL_HAS_CREATEFILELIST
         if (recursive) {
    -        fileNamesTable = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, &fileNamesNb);
    +        fileNamesTable = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, &fileNamesNb, 1);
             if (fileNamesTable) {
                 unsigned u;
                 for (u=0; u