Compare commits

...

367 commits

Author SHA1 Message Date
Yann Collet
82d322c497
Merge pull request #4721 from facebook/dependabot/github_actions/actions/setup-java-5.6.0
Some checks failed
facebook/zstd/commit / short-tests-1 (push) Failing after 27s
facebook/zstd/commit / regression-test (push) Failing after 26s
facebook/zstd/commit / short-tests-0 (push) Failing after 31s
Scorecards supply-chain security / Scorecards analysis (push) Failing after 1s
facebook/zstd/nightly / regression-test (push) Failing after 3s
Bump actions/setup-java from 5.2.0 to 5.6.0
2026-08-01 06:13:34 -08:00
Yann Collet
1345d2008d
Merge pull request #4722 from facebook/dependabot/github_actions/msys2/setup-msys2-2.32.0
Bump msys2/setup-msys2 from 2.31.1 to 2.32.0
2026-08-01 06:02:39 -08:00
Yann Collet
8223abf92f
Merge pull request #4719 from facebook/dependabot/github_actions/actions/cache-6
Bump actions/cache from 5 to 6
2026-08-01 06:01:31 -08:00
dependabot[bot]
af48fb967f
Bump msys2/setup-msys2 from 2.31.1 to 2.32.0
Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.31.1 to 2.32.0.
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](e9898307ac...66cd2cce69)

---
updated-dependencies:
- dependency-name: msys2/setup-msys2
  dependency-version: 2.32.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-01 05:32:58 +00:00
dependabot[bot]
e076449205
Bump actions/setup-java from 5.2.0 to 5.6.0
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.2.0 to 5.6.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](be666c2fcd...03ad4de099)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-01 05:32:52 +00:00
dependabot[bot]
a1ddcdae2d
Bump actions/cache from 5 to 6
Bumps [actions/cache](https://github.com/actions/cache) from 5 to 6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-01 05:32:35 +00:00
Yann Collet
5c7b7bad26
Merge pull request #4703 from facebook/dependabot/github_actions/cygwin/cygwin-install-action-6.0.2
Bump cygwin/cygwin-install-action from 6.0.1 to 6.0.2
2026-07-01 08:22:56 +02:00
Yann Collet
b1796e4580
Merge pull request #4702 from facebook/dependabot/github_actions/github/codeql-action/upload-sarif-4.36.2
Bump github/codeql-action/upload-sarif from 4.35.1 to 4.36.2
2026-07-01 08:22:17 +02:00
dependabot[bot]
61b9912eec
Bump cygwin/cygwin-install-action from 6.0.1 to 6.0.2
Bumps [cygwin/cygwin-install-action](https://github.com/cygwin/cygwin-install-action) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/cygwin/cygwin-install-action/releases)
- [Commits](711d29f3da...3f0a3f9f98)

---
updated-dependencies:
- dependency-name: cygwin/cygwin-install-action
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-01 05:32:46 +00:00
dependabot[bot]
a20ab7436f
Bump github/codeql-action/upload-sarif from 4.35.1 to 4.36.2
Bumps [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) from 4.35.1 to 4.36.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](c10b8064de...8aad20d150)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.36.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-01 05:32:43 +00:00
Nick Terrell
5233c58e6c [doc] Clarify requirements around Block_Maximum_Size in spec
Clarify that it is legal to send compressed blocks that are larger than the
uncompressed size so long as their `Block_Content` is no larger than
`Block_Maximum_Size`.

See https://github.com/facebook/zstd/issues/4667
2026-05-14 18:45:42 -04:00
Yann Collet
c367e0c149
Merge pull request #4657 from facebook/dependabot/github_actions/msys2/setup-msys2-2.31.1
Bump msys2/setup-msys2 from 2.31.0 to 2.31.1
2026-05-14 15:11:55 -07:00
Yann Collet
885c79ba4a
Merge pull request #4658 from facebook/dependabot/github_actions/actions/upload-artifact-7.0.1
Bump actions/upload-artifact from 7.0.0 to 7.0.1
2026-05-05 14:19:30 -07:00
dependabot[bot]
cb6b844cb5
Bump actions/upload-artifact from 7.0.0 to 7.0.1
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v7...v7.0.1)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-01 06:18:35 +00:00
dependabot[bot]
c770d993fb
Bump msys2/setup-msys2 from 2.31.0 to 2.31.1
Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.31.0 to 2.31.1.
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](cafece8e6b...e9898307ac)

---
updated-dependencies:
- dependency-name: msys2/setup-msys2
  dependency-version: 2.31.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-01 06:18:32 +00:00
Yann Collet
0cdce55f2f
Merge pull request #4648 from eyupcanakman/fix/valgrind-test-no-arg
Pass invalid argument in valgrindTest to force failure
2026-04-24 22:35:25 -07:00
Eyüp Can Akman
44ebbde6a3
Fake console stdin in valgrindTest to force failure 2026-04-20 20:12:21 +03:00
Yann Collet
48c0ed7362
Merge pull request #4635 from facebook/dependabot/github_actions/msys2/setup-msys2-2.31.0
Bump msys2/setup-msys2 from 2.30.0 to 2.31.0
2026-04-01 15:07:14 -07:00
Yann Collet
b3a648a204
Merge pull request #4636 from facebook/dependabot/github_actions/github/codeql-action-4.35.1
Bump github/codeql-action from 4.31.2 to 4.35.1
2026-04-01 15:06:22 -07:00
Yann Collet
6d6eff1008
Merge pull request #4634 from facebook/dependabot/github_actions/android-actions/setup-android-4.0.0
Bump android-actions/setup-android from 3.2.2 to 4.0.0
2026-04-01 15:05:28 -07:00
Yann Collet
c0ec909bde
Merge pull request #4633 from facebook/dependabot/github_actions/microsoft/setup-msbuild-3.0.0
Bump microsoft/setup-msbuild from 2.0.0 to 3.0.0
2026-04-01 15:04:29 -07:00
dependabot[bot]
0d815ad877
Bump github/codeql-action from 4.31.2 to 4.35.1
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.2 to 4.35.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](0499de31b9...c10b8064de)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.35.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-01 05:50:47 +00:00
dependabot[bot]
a23bf84362
Bump msys2/setup-msys2 from 2.30.0 to 2.31.0
Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.30.0 to 2.31.0.
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](4f806de0a5...cafece8e6b)

---
updated-dependencies:
- dependency-name: msys2/setup-msys2
  dependency-version: 2.31.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-01 05:50:38 +00:00
dependabot[bot]
497a433e01
Bump android-actions/setup-android from 3.2.2 to 4.0.0
Bumps [android-actions/setup-android](https://github.com/android-actions/setup-android) from 3.2.2 to 4.0.0.
- [Release notes](https://github.com/android-actions/setup-android/releases)
- [Commits](9fc6c4e906...651bceb6f9)

---
updated-dependencies:
- dependency-name: android-actions/setup-android
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-01 05:50:32 +00:00
dependabot[bot]
5fc4931c04
Bump microsoft/setup-msbuild from 2.0.0 to 3.0.0
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 2.0.0 to 3.0.0.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Commits](6fb0222098...30375c66a4)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-version: 3.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-01 05:50:27 +00:00
kevinjzhang
3ae099b48d
Merge pull request #4626 from kevinjzhang/fix-high-memory-usage
Fix unintended high memory usage
2026-03-17 16:16:04 -07:00
Kevin Zhang
cef5a5611a Fix unintended high memory usage 2026-03-17 13:11:22 -07:00
Yann Collet
e56865641e
Merge pull request #4613 from nidu-ninja/null-deref-custom-calloc
Fix potential NULL pointer dereference in ZSTD_customCalloc when cust…
2026-03-16 09:37:07 -07:00
Yann Collet
c84c8fb47f
Merge pull request #4606 from jlee303/update_manual
Update manual/error message
2026-03-13 10:37:36 -07:00
Yann Collet
ff25783fcb
Merge pull request #4619 from jlee303/display_option_c
Promote -c flag
2026-03-13 10:34:03 -07:00
Yann Collet
155046f3ac
Merge pull request #4620 from jlee303/defineable_cflags
Make DISPLAY_LEVEL_DEFAULT configurable at compile time
2026-03-13 10:33:46 -07:00
Yann Collet
ee0af93e1c
Merge pull request #4609 from Integral-Tech/memory-g-suffix
Accept G, GB and GiB suffixes for options
2026-03-13 10:33:24 -07:00
Jennifer Lee
e374fc76fe fix display format 2026-03-12 11:34:43 -07:00
Jennifer Lee
3f565b731e rever -q 2026-03-12 11:32:48 -07:00
Jennifer Lee
3041c8e539 Update #define format 2026-03-11 08:29:06 -07:00
Integral
488b3a7e37
Add tests for options with G, GB and GiB suffixes 2026-03-10 10:16:53 +08:00
Jennifer Lee
2293e9601f init commit 2026-03-09 17:17:13 -07:00
Jennifer Lee
13ea076d3b Update tests 2026-03-09 16:40:42 -07:00
Jennifer Lee
043426b3e2 Promote flag 2026-03-09 16:30:41 -07:00
NiDU-NINJA
3f8f9b3f89 Fix potential NULL pointer dereference in ZSTD_customCalloc when custom allocator fails 2026-03-07 08:27:15 +00:00
Integral
f1e77ab2ba
Accept G, GB and GiB suffixes for options 2026-03-07 14:49:39 +08:00
Jennifer Lee
7b04e6dd1e Retry CI 2026-03-06 09:47:03 -08:00
Nick Terrell
d7ee3207cc Remove LICENSE file in build/ dir 2026-03-05 19:00:23 -05:00
jlee303
1bd8e55363
Update programs/zstd.1.md
Co-authored-by: Nick Terrell <nickrterrell@gmail.com>
2026-03-05 15:12:33 -08:00
Jennifer Lee
6a8715f8d4 update man 2026-03-04 13:29:20 -08:00
Sergey G. Brester (sebres)
6e1e545916 avoid potential RC on ctx->threadLimit, code review;
closes gh-4547; replaces gh-4558
2026-03-02 14:39:17 -05:00
Yann Collet
0532fe3e8a
Merge pull request #4598 from facebook/dependabot/github_actions/cygwin/cygwin-install-action-6.1
Bump cygwin/cygwin-install-action from 6.0 to 6.1
2026-03-01 00:39:29 -08:00
Yann Collet
9468cace38
Merge pull request #4597 from facebook/dependabot/github_actions/actions/upload-artifact-7.0.0
Bump actions/upload-artifact from 6.0.0 to 7.0.0
2026-03-01 00:38:57 -08:00
dependabot[bot]
1c140a86a1
Bump cygwin/cygwin-install-action from 6.0 to 6.1
Bumps [cygwin/cygwin-install-action](https://github.com/cygwin/cygwin-install-action) from 6.0 to 6.1.
- [Release notes](https://github.com/cygwin/cygwin-install-action/releases)
- [Commits](f200932376...711d29f3da)

---
updated-dependencies:
- dependency-name: cygwin/cygwin-install-action
  dependency-version: '6.1'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-01 05:32:44 +00:00
dependabot[bot]
d9b10820f8
Bump actions/upload-artifact from 6.0.0 to 7.0.0
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-01 05:32:41 +00:00
richardsonnick
bb1eedcf86 correct mmap error check
Update mmap error validation to check for MAP_FAILED instead of NULL.
POSIX specifies that mmap returns MAP_FAILED (-1) on failure.
2026-02-27 17:40:26 -05:00
Alexander Moch
2107c8f189 bitstream: fix BIT_readBits and BIT_reloadDStream prototypes
Align the declarations of BIT_readBits() and BIT_reloadDStream() in
bitstream.h with their FORCE_INLINE_TEMPLATE definitions.

The previous MEM_STATIC declarations caused an attribute mismatch
between the header and the definitions, which can lead to incorrect
compiler assumptions under certain toolchains and optimization levels.

Signed-off-by: Alexander Moch <mail@alexmoch.com>
2026-02-27 16:37:40 -05:00
Radek Zikmund
bce1ec6b07 Make explicit ptrdiff_t to int casts in divsufsort.c to avoid compiler warnings. 2026-02-27 16:32:11 -05:00
Cody
81cf153bce fix: adjust LDM params in estimate functions to prevent SIGFPE (issue #4590) 2026-02-27 16:14:28 -05:00
Briar Campbell
117b0edfae Fix formatting of lz4 option in zstdcli.c 2026-02-27 16:10:41 -05:00
Briar Campbell
a90d7e7689 Fix formatting of lz4 option in README 2026-02-27 16:10:41 -05:00
Yann Collet
1168da0e56
Merge pull request #4575 from Cyan4973/depend_monthly
extend dependabot period to monthly
2026-01-26 10:03:13 -08:00
Yann Collet
a380d30b20 extend dependabot period to monthly 2026-01-26 09:01:27 -08:00
Yann Collet
4b8d87a8c3
Merge pull request #4574 from facebook/dependabot/github_actions/actions/checkout-6.0.2
Bump actions/checkout from 6.0.1 to 6.0.2
2026-01-26 08:57:23 -08:00
Yann Collet
deb898b541
Merge pull request #4573 from facebook/dependabot/github_actions/actions/setup-java-5.2.0
Bump actions/setup-java from 5.1.0 to 5.2.0
2026-01-26 08:56:49 -08:00
dependabot[bot]
a46bec0fba
Bump actions/checkout from 6.0.1 to 6.0.2
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v6.0.1...v6.0.2)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-26 05:51:10 +00:00
dependabot[bot]
a8319c39de
Bump actions/setup-java from 5.1.0 to 5.2.0
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](f2beeb24e1...be666c2fcd)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-26 05:50:49 +00:00
Yann Collet
ae9f20ca27
Merge pull request #4554 from facebook/no_legacy
Remove legacy support by default
2025-12-18 16:46:12 -08:00
Yann Collet
e00ddf63b2
Merge pull request #4555 from facebook/fix4553
Fix #4553
2025-12-18 16:30:23 -08:00
Yann Collet
1dae4f0188 test: fix versionsTest build for old zstd versions
Summary:
Some old zstd versions (notably v0.6.x) have a bug in fileio.c where header includes check for `ZSTD_LEGACY_SUPPORT==1` but code usage checks for `ZSTD_LEGACY_SUPPORT>=1`. Using value 5 causes compilation failure because headers aren't included but the code tries to use legacy functions.

Changing to `ZSTD_LEGACY_SUPPORT=1` for old version builds fixes the compilation while still enabling legacy format support.

Test Plan:
Run `make versionsTest` or `python3 tests/test-zstd-versions.py` to verify all old versions compile and cross-version decompression works correctly.
2025-12-18 16:13:53 -08:00
Yann Collet
3a3c506b51 Fix #4553
This is a bug in the streaming implementation of the v0.5 decoder.
The bug has always been there.
It requires an uncommon block configuration, which wasn't tested at the time.

v0.5 is deprecated now,
latest version to produce such format is v0.5.1 from February 2016.
It was superceded in April 2016.
So it's both short lived and very old.

Another PR will remove support of this format,
but it will still be possible to explicitely request this support on demand,
so better fix the issue.
2025-12-18 15:52:11 -08:00
Yann Collet
a87d0cc476 test: enable legacy support in version compatibility test
Summary:
The version compatibility test needs to decode legacy frames (v0.5.x - v0.7.x) to verify cross-version interoperability. Since legacy support is now disabled by default (v1.6.0), head must be built with ZSTD_LEGACY_SUPPORT=5 for this test.

Test Plan:
Run `python3 tests/test-zstd-versions.py` to verify cross-version compatibility testing works correctly.
2025-12-18 14:42:41 -08:00
Yann Collet
8ba2f20a90 test: update libzstd_builds.sh for disabled legacy default
Summary:
Updates the library build tests to reflect that legacy format support is now disabled by default. Also adds a new test case to verify that legacy support can still be explicitly enabled via ZSTD_LEGACY_SUPPORT=5.

Test Plan:
Run `bash tests/libzstd_builds.sh` on a Linux environment.
2025-12-18 13:39:28 -08:00
Yann Collet
f818f97be6 build: set ZSTD_LEGACY_SUPPORT=0 in remaining build systems
Summary:
Completes the transition to disabled legacy support by default across all build systems. This follows up on the previous Makefile and CMake changes to ensure consistent default behavior regardless of the build system used.

Updated build configurations: Meson, tests/Makefile, Visual Studio 2008/2010 projects, and BUCK.

Test Plan:
Verified changes compile correctly via `make lib-release`. Build system configurations have been updated consistently across all platforms.
2025-12-18 13:25:47 -08:00
Yann Collet
6c3e805e50 doc: legacy support is now disabled by default 2025-12-18 13:19:11 -08:00
Yann Collet
073c7fb6ea update dev version number to v1.6.0
to reflect the relatively big scope change by removing support of legacy formats.
2025-12-18 13:13:56 -08:00
Yann Collet
b79e86291b [cmake] disable legacy support by default
can still be explicitly enabled
2025-12-18 13:11:37 -08:00
Yann Collet
38cce02684 Makefile: remove support of legacy formats by default
can still be changed manually by setting `ZSTD_LEGACY_SUPPORT` to a different value
2025-12-18 12:59:14 -08:00
Yann Collet
ebc93b0c91
Merge pull request #4545 from facebook/cirrusci_bsd_fix
[ci] update freebsd image
2025-12-18 09:53:59 -08:00
Yann Collet
85c5fa09fd changed to freebsd 15
since the image 16 does not seem to work
2025-12-18 09:40:47 -08:00
Yann Collet
af850cd44e
Merge pull request #4551 from facebook/dependabot/github_actions/actions/upload-artifact-6.0.0
Bump actions/upload-artifact from 5.0.0 to 6.0.0
2025-12-18 09:39:37 -08:00
Yann Collet
5b51447734
Merge pull request #4552 from facebook/dependabot/github_actions/actions/cache-5
Bump actions/cache from 4 to 5
2025-12-16 07:24:01 -08:00
Yann Collet
9873a01368
Merge pull request #4550 from facebook/dependabot/github_actions/msys2/setup-msys2-2.30.0
Bump msys2/setup-msys2 from 2.29.0 to 2.30.0
2025-12-15 01:11:42 -08:00
dependabot[bot]
de9b0810ec
Bump actions/cache from 4 to 5
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 05:04:57 +00:00
dependabot[bot]
c26db2d0e8
Bump actions/upload-artifact from 5.0.0 to 6.0.0
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5.0.0 to 6.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 05:04:53 +00:00
dependabot[bot]
1e06c42eec
Bump msys2/setup-msys2 from 2.29.0 to 2.30.0
Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.29.0 to 2.30.0.
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](fb197b72ce...4f806de0a5)

---
updated-dependencies:
- dependency-name: msys2/setup-msys2
  dependency-version: 2.30.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 05:04:44 +00:00
Yann Collet
bfd8ad886f
Merge pull request #4544 from facebook/dependabot/github_actions/actions/setup-java-5.1.0
Bump actions/setup-java from 5.0.0 to 5.1.0
2025-12-10 18:25:33 +09:00
Yann Collet
c7c29693c9 [ci] update freebsd image 2025-12-09 08:30:24 +09:00
dependabot[bot]
f28b1173df
Bump actions/setup-java from 5.0.0 to 5.1.0
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](dded088883...f2beeb24e1)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 23:25:45 +00:00
Yann Collet
94117e39ca
Merge pull request #4543 from facebook/dependabot/github_actions/actions/checkout-6.0.1
Bump actions/checkout from 6.0.0 to 6.0.1
2025-12-09 08:24:47 +09:00
dependabot[bot]
757f1bf465
Bump actions/checkout from 6.0.0 to 6.0.1
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v6...v6.0.1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 05:05:30 +00:00
Yann Collet
92505deb29
Merge pull request #4525 from Polaris-911/new-feature
Add RISC-V 64-bit architecture detection
2025-12-02 10:38:48 -08:00
Yann Collet
f567f38b73
Merge pull request #4531 from lukaskollmer/lukas/fix-swift-build
modulemap: remove `config_macros`
2025-12-02 10:37:35 -08:00
Yann Collet
9e23edcf1e
Merge pull request #4494 from LecrisUT/maint-cmake
Split lib target types in their own export groups
2025-12-01 15:29:12 -08:00
Lukas Kollmer
88ff5c2769
modulemap: remove config_macros 2025-11-25 16:38:08 +01:00
Yann Collet
d462f691ba
Merge pull request #4529 from facebook/dependabot/github_actions/actions/checkout-6.0.0
Bump actions/checkout from 5.0.0 to 6.0.0
2025-11-24 03:01:17 -08:00
dependabot[bot]
e23477ce3e
Bump actions/checkout from 5.0.0 to 6.0.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 6.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 05:05:06 +00:00
Yann Collet
448cd34087
Merge pull request #4522 from facebook/dependabot/github_actions/github/codeql-action-4.31.2
Bump github/codeql-action from 3.30.1 to 4.31.2
2025-11-03 15:51:17 +01:00
黄尚诚10330306
71146f5b6d Add RISC-V 64-bit architecture detection 2025-11-03 16:37:05 +08:00
dependabot[bot]
273ab1bbdf
Bump github/codeql-action from 3.30.1 to 4.31.2
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.1 to 4.31.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](f1f6e5f6af...0499de31b9)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 05:08:56 +00:00
Yann Collet
a25c1fc96f
Merge pull request #4519 from facebook/dependabot/github_actions/actions/upload-artifact-5
Bump actions/upload-artifact from 4 to 5
2025-10-27 06:15:00 -08:00
dependabot[bot]
129769d04c
Bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 05:18:47 +00:00
Yann Collet
711e17da98
Merge pull request #4491 from facebook/cmake_root
[cmake] propose a root wrapper
2025-10-26 13:40:00 -08:00
Yann Collet
57d4949098
Merge pull request #4517 from Cyan4973/asyncio_revisit
Remove asyncio from the compression path
2025-10-26 13:39:25 -08:00
Yann Collet
7a3c940e7f syncio interface only enabled when compression is enabled 2025-10-26 09:48:45 -07:00
Yann Collet
41f2673acd changed name to syncIO for clarity 2025-10-25 11:23:16 -07:00
Yann Collet
ccadc33a59 minor: use init/destroy pair naming convention 2025-10-25 11:11:48 -07:00
Yann Collet
d1dd7e1481 removed asyncio completely for compression path
this does not provide speed benefits,
since most of the leverage happens internally within the library,
and can even become detrimental in certain scenario, due to complex and wasteful memory management.
At a minimum, it makes the logic simpler, easier to debug, at essentially the same performance.
2025-10-25 11:02:51 -07:00
Yann Collet
44cd3c8451 disable asyncio during compression
it's not helpful for performance, and can in some times be detrimental.
the synchronous mode is also much easier to follow and debug.
2025-10-25 00:50:55 -07:00
Yann Collet
4944d2c461
Merge pull request #4515 from cclauss/patch-1
Fix undefined names in automated_benchmarking.py
2025-10-23 08:57:19 -08:00
Christian Clauss
c72eea13bf Fix undefined names in automated_benchmarking.py
Fix variable name typos in automated_benchmarking.py

% `ruff check`
```
Error: tests/automated_benchmarking.py:237:21: F821 Undefined name `baseline_label`
Error: tests/automated_benchmarking.py:250:21: F821 Undefined name `baseline_label`
Error: tests/automated_benchmarking.py:318:55: F821 Undefined name `frequenc`
Error: Process completed with exit code 1.
```
% [`ruff rule F821`](https://docs.astral.sh/ruff/rules/undefined-name)
2025-10-23 18:22:44 +02:00
Yann Collet
442fa2f2d5
Merge pull request #4516 from Cyan4973/mingw_calloc_order
minor: fix mingw warnings: calloc argument order
2025-10-23 07:57:40 -08:00
Yann Collet
5539fcfb6a minor: fix mingw warnings: calloc argument order 2025-10-23 07:01:01 -07:00
Yann Collet
6e58e9a2c4
Merge pull request #4509 from arpadpanyik-arm/revert_branch_opt
AArch64: Revert previous branch optimization
2025-10-18 10:10:55 -07:00
Arpad Panyik
0dffae42e3 AArch64: Remove 32-bit code from ZSTD_decodeSequence
Remove the 32-bit code paths from the AArch64 only sections of
ZSTD_decodeSequence.
2025-10-08 18:59:24 +00:00
Arpad Panyik
33618c89e5 AArch64: Revert previous branch optimization
Revert a branch optimization that was based on an incorrect
assumption in the AArch64 part of ZSTD_decodeSequence. In extreme
cases the existing implementation could lead to data corruption.

Insert an UNLIKELY hint to guide the compilers toward generating more
efficient machine code.
2025-10-08 18:58:45 +00:00
Yann Collet
23dae4bf49
Merge pull request #4504 from rzikm/asm-conditional
Make ASM language conditional at CMake configure time
2025-10-06 23:39:28 -07:00
Radek Zikmund
f94a01de74 Enable ASM language during CMake configure time only when needed 2025-10-02 14:40:11 +02:00
Yann Collet
b8d6101fba
Merge pull request #4502 from zijianli1234/dev
- Modify the GCC version used for CI testing of the RISCV architecture
2025-09-30 12:35:40 -07:00
ZijianLi
87cc127705 - Modify the GCC version used for CI testing of the RISCV architecture
- Fix a bug in the ZSTD_row_getRVVMask function
- Improve some performance for ZSTD_copy16()
2025-09-26 22:34:57 +08:00
Yann Collet
7758cc3e7a [cmake] add minimal build test
for CMakeLists.txt at root
2025-09-24 22:46:29 -07:00
Yann Collet
c9d3af9ed0 [cmake] root wrapper
allow the existence of a `CMakeLists.txt` file at root,
for easier integration with other projects expecting this file at root.

Existing integration point, within `build/cmake/`, still works as expected.
2025-09-24 22:46:29 -07:00
Yann Collet
f42dee27b6
Merge pull request #4500 from facebook/legacy01_init
fix minor initialization warnings
2025-09-24 22:46:05 -07:00
Yann Collet
17888b3fbe fix minor initialization warnings 2025-09-24 22:08:03 -07:00
Yann Collet
a8f732e50f
Merge pull request #4498 from facebook/contentSize_doc
update documentation of ZSTD_getFrameContentSize()
2025-09-23 23:59:34 -07:00
Yann Collet
c15fa3cd40 update documentation of ZSTD_getFrameContentSize()
hopefully answering #4495
2025-09-23 23:17:11 -07:00
Yann Collet
89d685e42d
Merge pull request #4497 from facebook/legacy_fix
fix minor warning in legacy decoders
2025-09-23 12:55:50 -08:00
Yann Collet
4c1f86c777 fix minor warning in legacy decoders
for mingw + clang CI test
2025-09-23 13:01:38 -07:00
Cristian Le
eb062bc339 Split lib target types in their own export groups
This allows for the non-primary library to be missing in the Config.cmake file, e.g. if the devel files have a separate static-devel package

Signed-off-by: Cristian Le <git@lecris.dev>
2025-09-23 10:29:44 +02:00
Yann Collet
ee9b5f4371
Merge pull request #4490 from facebook/doc_profiling_vs
minor: add profiling notes for Visual Studio
2025-09-20 22:30:40 -08:00
Yann Collet
0c6d32df9a added profiling notes for Visual Studio 2025-09-20 22:13:49 -07:00
Yann Collet
f9b0c4fd0d
Merge pull request #4489 from facebook/doc_install
Added documentation details for Makefile installation and pkg-config.
2025-09-20 21:04:35 -08:00
Yann Collet
be072c708e Added documentation details for Makefile installation and pkg-config. 2025-09-20 16:33:41 +00:00
Yann Collet
085cc9319a
Merge pull request #4486 from rlefko/fix-pthread-init-memleak
Fix memory leak in pthread init functions on failure
2025-09-19 21:42:21 -08:00
Yann Collet
e6e5a95c15
Merge pull request #4487 from neiljohari/adhoc/dictionary-file-counting
make DiB_fileStats skip invalid files (fileSize <= 0) to prevent negative totals and bogus allocation
2025-09-19 21:42:06 -08:00
Yann Collet
d190b38863
Merge pull request #4481 from w1m024/support-rvv-getmask
add RVV optimization for ZSTD_row_getMatchMask
2025-09-16 13:55:11 -08:00
Neil Johari
236e44f00f
Remove debug logging 2025-09-16 00:03:08 -07:00
Neil Johari
85f4a7e84e
Fix bug 2025-09-16 00:02:04 -07:00
Neil Johari
96fdb9bd16
Add debug logging and simple repro 2025-09-15 23:58:45 -07:00
Ryan Lefkowitz
c59812e558 🔧 Fix memory leak in pthread init functions on failure
When pthread_mutex_init() or pthread_cond_init() fails in the debug
implementation (DEBUGLEVEL >= 1), the previously allocated memory was
not freed, causing a memory leak.

This fix ensures that allocated memory is properly freed when pthread
initialization functions fail, preventing resource leaks in error
conditions.

The issue affects:
- ZSTD_pthread_mutex_init() at lib/common/threading.c:146
- ZSTD_pthread_cond_init() at lib/common/threading.c:167

This is particularly important for long-running applications or
scenarios with resource constraints where pthread initialization
might fail due to system limits.
2025-09-15 18:20:01 -04:00
w1m024
fb7a86f20f Refactor ZSTD_row_getMatchMask for RVV optimization
Performance (vs. SWAR)
- 16-byte data: 5.87x speedup
- 32-byte data: 9.63x speedup
- 64-byte data: 17.98x speedup

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>
2025-09-11 20:45:54 +00:00
w1m024
c9d2cbd5ba add RVV optimization for ZSTD_row_getMatchMask
Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>
2025-09-09 06:20:55 +00:00
Yann Collet
98d2b90e82
Merge pull request #4480 from facebook/dependabot/github_actions/github/codeql-action-3.30.1
Bump github/codeql-action from 3.29.4 to 3.30.1
2025-09-08 07:52:31 -07:00
Yann Collet
683c91fca8
Merge pull request #4479 from facebook/dependabot/github_actions/msys2/setup-msys2-2.29.0
Bump msys2/setup-msys2 from 2.28.0 to 2.29.0
2025-09-08 07:51:17 -07:00
dependabot[bot]
ef4bab9079
Bump github/codeql-action from 3.29.4 to 3.30.1
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.4 to 3.30.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](4e828ff8d4...f1f6e5f6af)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.30.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 05:06:48 +00:00
dependabot[bot]
d3536643a9
Bump msys2/setup-msys2 from 2.28.0 to 2.29.0
Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.28.0 to 2.29.0.
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](40677d36a5...fb197b72ce)

---
updated-dependencies:
- dependency-name: msys2/setup-msys2
  dependency-version: 2.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 05:06:40 +00:00
Yann Collet
3580aa28e6
Merge pull request #4472 from bgilbert/override_dependency
meson: Call `meson.override_dependency()` if Meson is new enough
2025-09-05 15:32:16 -07:00
Yann Collet
6936bc84e7
Merge pull request #4475 from Cyan4973/default_nbThreads
Default nb threads
2025-09-02 17:19:17 -07:00
Yann Collet
249e4a07d5 fixed minor unused variable warning
in certain compilation modes
2025-09-02 16:36:44 -07:00
Yann Collet
725a152c7b benchmark uses 1 thread by default 2025-09-02 16:29:14 -07:00
Yann Collet
c41fc1aa01 only display nbThread Msg in nbThreads > 1 2025-09-02 16:05:35 -07:00
Yann Collet
6551db3459 specify nb of threads used during benchmarking
used to require `-v` (verbose) modifier
2025-09-02 15:53:45 -07:00
Yann Collet
1c5d45fc11 fixed -T# documentation in zstd -H
provide the local value for default nbThreads
which is dynamic and depends on local nb of cores.
2025-09-02 15:46:51 -07:00
Yann Collet
fc551317fb
Merge pull request #4474 from jlokier/threads-doc-fix
Update manual about the default value of `-T#`/`--threads=#`
2025-09-02 15:40:32 -07:00
Jamie Lokier
64c4288e92 Update manual about the default value of -T#/--threads=#
The section about `ZSTD_NBTHREADS` already explains the default number of
threads, since it changed from 1 (commit 17beeb5).  But the option description
for `-T#`/`--threads=#` incorrectly said the default was still 1.

I noticed this when I found compression slower with `-T1` than without it.
2025-09-02 16:44:39 +01:00
Benjamin Gilbert
ba59aeb674 meson: Call meson.override_dependency() if Meson is new enough
This tells Meson that we intend libzstd_dep to be used by a parent project
if the parent looks for a dependency named "libzstd".  Without this, the
mapping from "libzstd" to our variable libzstd_dep must be encoded in the
Meson wrap file or in the parent's meson.build.
2025-08-28 18:50:34 -05:00
Yann Collet
22b4483163
Merge pull request #4469 from facebook/dependabot/github_actions/actions/setup-java-5.0.0
Bump actions/setup-java from 4.7.1 to 5.0.0
2025-08-25 09:07:01 -07:00
dependabot[bot]
0ee187c540
Bump actions/setup-java from 4.7.1 to 5.0.0
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.1 to 5.0.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](c5195efecf...dded088883)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-25 09:00:57 +00:00
Yann Collet
b5c294ea01
Merge pull request #4440 from arpadpanyik-arm/convert_seq_sve2
AArch64: Add SVE2 path for convertSequences_noRepcodes
2025-08-21 17:20:33 -07:00
Arpad Panyik
2849f3a5d1 AArch64: Add SVE2 path for convertSequences_noRepcodes
Add an 8-way vector length agnostic (VLA) SVE2 code path for
convertSequences_noRepcodes. It works with any SVE vector length.

Relative performance to GCC-13 using: `./fullbench -b18 -l5 enwik5`

               Neon      SVE2
Neoverse-V2   before     after    uplift
GCC-13:      100.000%  103.209%   1.032x
GCC-14:      100.309%  134.872%   1.344x
GCC-15:      100.355%  134.827%   1.343x
Clang-18:    123.614%  128.565%   1.040x
Clang-19:    123.587%  132.984%   1.076x
Clang-20:    123.629%  133.023%   1.075x

               Neon      SVE2
Cortex-A720   before     after    uplift
GCC-13:      100.000%  116.032%   1.160x
GCC-14:       99.700%  116.648%   1.169x
GCC-15:      100.354%  117.047%   1.166x
Clang-18:    100.447%  116.762%   1.162x
Clang-19:    100.454%  116.627%   1.160x
Clang-20:    100.452%  116.649%   1.161x
2025-08-21 17:37:41 +00:00
Yann Collet
290e692ef8
Merge pull request #4463 from brad0/gnu_source_qsort
Check for build environment instead of just _GNU_SOURCE
2025-08-21 09:30:29 -07:00
Yann Collet
b3f134bfd4
Merge pull request #4465 from thiru-mcw/arm64_support
WOA_support:: Add CI setup for packaging Windows on ARM artifacts
2025-08-20 11:23:34 -07:00
Thirumalai Nagalingam
076283fa88 CI: Enable MSVC ARM64 job using Github WOA runner
- Reintroduce the MSVC ARM64 build configuration with "Visual Studio 17 2022"
- Update runner to `windows-11-arm` (GitHub-hosted Windows on ARM)
2025-08-20 17:19:48 +05:30
Thirumalai Nagalingam
002c227596 CI: Add CI setup for packaging Win-ARM64 artifacts 2025-08-20 17:12:21 +05:30
Thirumalai Nagalingam
42243c3d46 CI: Update build_package.bat for CMake builds 2025-08-20 17:12:05 +05:30
Yann Collet
0551eaa851
Merge pull request #4464 from facebook/cli_traces_div0
fixed a potential division by 0 in the cli trace unit
2025-08-19 17:43:11 -07:00
Yann Collet
ae64545c6b fixed a potential division by 0 in the cli trace unit 2025-08-19 17:13:15 -07:00
Brad Smith
0d1f8de9ad Check for build environment instead of just _GNU_SOURCE
Fixes the build on OpenBSD and NetBSD. It is too easy for _GNU_SOURCE
to be defined even on non-Linux systems. Found via py-zstandard with
the embedded copy of zstandard and Python defines _GNU_SOURCE.

Also simplify the Linux checking, there is no need to check the rest
of the symbol names.
2025-08-19 20:06:24 -04:00
Yann Collet
40c285e0ba
Merge pull request #4419 from AZero13/patch-1
Check for job before releasing resources
2025-08-19 17:02:48 -07:00
Yann Collet
cfeb29e397
Merge pull request #4462 from facebook/dependabot/github_actions/actions/checkout-5
Bump actions/checkout from 4 to 5
2025-08-18 09:10:13 -07:00
dependabot[bot]
0e69452a30
Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-18 08:13:07 +00:00
Yann Collet
3991e8ac84
Merge pull request #4459 from Margen67/premake
Remove need for trailing forward slash in dir
2025-08-17 12:14:42 -07:00
Margen67
1e1db47323
Remove need for trailing forward slash in dir 2025-08-17 00:44:39 -07:00
Yann Collet
e128976193
Merge pull request #4448 from Cyan4973/install_oses
regroup list of OSes for install inside common variable
2025-07-28 11:01:58 -08:00
Yann Collet
8bca04ba9f regroup list of OSes for install inside common variable
within lib/install_oses.mk.

fixes #4445
2025-07-28 11:33:22 -07:00
Yann Collet
5b89189741
Merge pull request #4450 from facebook/dependabot/github_actions/github/codeql-action-3.29.4
Bump github/codeql-action from 3.28.9 to 3.29.4
2025-07-28 07:33:09 -08:00
dependabot[bot]
96f316a246
Bump github/codeql-action from 3.28.9 to 3.29.4
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.9 to 3.29.4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](9e8d0789d4...4e828ff8d4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-28 06:30:43 +00:00
Yann Collet
9bf5d340ae
Merge pull request #4447 from facebook/android-cmake
added android cmake build
2025-07-24 10:07:16 -08:00
Yann Collet
34f3a0ab11
Merge pull request #4413 from arpadpanyik-arm/huf_decode2x
AArch64: Enhance struct access in Huffman decode 2X
2025-07-23 15:03:37 -08:00
Yann Collet
6f1cb87ade
Merge pull request #4443 from facebook/opt_simplify_4442
simplify sequence resolution in zstd_opt
2025-07-23 15:01:36 -08:00
Yann Collet
3b23f0c673 added android cmake build
is expecte to fail, due to #4444
2025-07-23 15:07:20 -07:00
Yann Collet
0055ce7a02 simplify sequence resolution in zstd_opt
initially hinted by @pitaj in #4442
2025-07-18 21:21:47 -07:00
Yann Collet
f9e26bb42b
Merge pull request #4394 from AZero13/zstd
Remove redundant setting of allJobsCompleted to 1
2025-07-18 18:55:47 -08:00
Yann Collet
8c651868ff
Merge pull request #4418 from arpadpanyik-arm/decode_seq_opt
AArch64: Improve ZSTD_decodeSequence performance
2025-07-18 18:54:49 -08:00
Yann Collet
a1e11db08a
Merge pull request #4435 from zijianli1234/dev
add riscv  ci
2025-07-18 18:54:24 -08:00
Yann Collet
afa96bbf25
Merge pull request #4429 from arpadpanyik-arm/convertSequences_Neon
Improve speed of ZSTD_compressSequencesAndLiterals using Neon
2025-07-13 23:52:48 -08:00
Yann Collet
c768d7b94b
Merge pull request #4436 from facebook/dependabot/github_actions/cygwin/cygwin-install-action-6
Bump cygwin/cygwin-install-action from 5 to 6
2025-07-13 23:52:32 -08:00
dependabot[bot]
3ce4d1cba3
Bump cygwin/cygwin-install-action from 5 to 6
Bumps [cygwin/cygwin-install-action](https://github.com/cygwin/cygwin-install-action) from 5 to 6.
- [Release notes](https://github.com/cygwin/cygwin-install-action/releases)
- [Commits](f61179d722...f200932376)

---
updated-dependencies:
- dependency-name: cygwin/cygwin-install-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-14 06:27:46 +00:00
Yann Collet
9a41990883
Merge pull request #4433 from facebook/vs2025
removed VS2019 runners
2025-07-12 19:44:28 -08:00
ZijianLi
534860c90b add -DMEM_FORCE_MEMORY_ACCESS=0 in CI RVV test 2025-07-13 10:51:08 +08:00
Yann Collet
7325384a68 removed VS2019 runners
replaced by one vs2025 runner,
which is badly named since it still running MSVC 2022,
but it's a good test that  shows that the matrix is able to handle multiple MSVC versions.
2025-07-11 10:29:07 -07:00
Arpad Panyik
703f855734 AArch64: Enable optimized QEMU CI builds
Add missing `-O3` flag to the compilation of AArch64 SVE2 builds
executed by QEMU. This can decrease the CI job runtime considerably.
2025-07-10 18:20:57 +00:00
Arpad Panyik
07cd78d366 AArch64: Add Neon path for convertSequences_noRepcodes
Add a 4-way Neon implementation for the convertSequences_noRepcodes
function. Remove 'static' keywords from all of its implementations to
be able to add unit tests.

Relative performance to Clang-18 using: `./fullbench -b18 -l5 enwik5`

Neoverse-V2   before     after
Clang-18:    100.000%  311.703%
Clang-19:    100.191%  311.714%
Clang-20:    100.181%  311.723%
GCC-13:      107.520%  252.309%
GCC-14:      107.652%  253.158%
GCC-15:      107.674%  253.168%

Cortex-A720   before     after
Clang-18:    100.000%  204.512%
Clang-19:    102.825%  204.600%
Clang-20:    102.807%  204.558%
GCC-13:      110.668%  203.594%
GCC-14:      110.684%  203.978%
GCC-15:      102.864%  204.299%

Co-authored by, Thomas Daubney <Thomas.Daubney@arm.com>
2025-07-10 18:20:57 +00:00
Arpad Panyik
8e4400463a Improve ZSTD_get1BlockSummary
Add a faster scalar implementation of ZSTD_get1BlockSummary which
removes the data dependency of the accumulators in the hot loop to
leverage the superscalar potential of recent out-of-order CPUs.
The new algorithm leverages SWAR (SIMD Within A Register) methodology
to exploit the capabilities of 64-bit architectures. It achieves this
by packing two 32-bit data elements into a single 64-bit register,
enabling parallel operations on these subcomponents while ensuring
that the 32-bit boundaries prevent overflow, thereby optimizing
computational efficiency.

Corresponding unit tests are included.

Relative performance to GCC-13 using: `./fullbench -b19 -l5 enwik5`

Neoverse-V2   before     after
GCC-13:      100.000%  290.527%
GCC-14:      100.000%  291.714%
GCC-15:       99.914%  291.495%
Clang-18:    148.072%  264.524%
Clang-19:    148.075%  264.512%
Clang-20:    148.062%  264.490%

Cortex-A720   before     after
GCC-13:      100.000%  235.261%
GCC-14:      101.064%  234.903%
GCC-15:      112.977%  218.547%
Clang-18:    127.135%  180.359%
Clang-19:    127.149%  180.297%
Clang-20:    127.154%  180.260%

Co-authored by, Thomas Daubney <Thomas.Daubney@arm.com>
2025-07-10 18:20:49 +00:00
ZijianLi
d04e7944dd add compiler version check. 2025-07-07 23:07:39 +08:00
ZijianLi
2c3f23b018 fix dereferencing type-punned pointer error 2025-06-29 15:36:25 +08:00
ZijianLi
40f64f3493 add riscv rvv ci 2025-06-29 15:33:50 +08:00
Yann Collet
1dbc2e0908
Merge pull request #4414 from arpadpanyik-arm/copy8
AArch64: Use better block COPY8
2025-06-25 07:47:01 -04:00
Rose
4efbd56749 Check for job before releasing
ZSTDMT_freeCCtx calls ZSTDMT_releaseAllJobResources, but ZSTDMT_releaseAllJobResources may be called when ZSTDMT_freeCCtx is called when initialization fails, resulting in a NULL pointer dereference.
2025-06-24 14:05:08 -04:00
Rose
50f169411b Remove redundant setting of allJobsCompleted to 1
This will do it automatically.
2025-06-24 14:04:21 -04:00
Arpad Panyik
a28e8182b1 AArch64: Improve ZSTD_decodeSequence performance
LLVM's alias-analysis sometimes fails to see that a static-array member
of a struct cannot alias other members. This patch:

- Reduces array accesses via struct indirection to aid load/store alias
  analysis under Clang.
- Converts dynamic array indexing into conditional-move arithmetic,
  eliminating branches and extra loads/stores on out-of-order CPUs.
- Reloads the bitstream only when match-length bits are consumed
  (assuming each reload only needs to happen once per match-length
  read), improving branch-prediction rates.
- Removes the UNLIKELY() hint, which recent compilers already handle
  well without cost.

Decompression uplifts on a Neoverse V2 system, using Zstd-1.5.8
compiled with "-O3 -march=armv8.2-a+sve2":

                 Clang-19  Clang-20   Clang-*    GCC-14    GCC-15
 1#silesia.tar:  +11.556%  +16.203%   +0.240%   +2.216%   +7.891%
 2#silesia.tar:  +15.493%  +21.140%   -0.041%   +2.850%   +9.926%
 3#silesia.tar:  +16.887%  +22.570%   -0.183%   +3.056%  +10.660%
 4#silesia.tar:  +17.785%  +23.315%   -0.262%   +3.343%  +11.187%
 5#silesia.tar:  +18.125%  +24.175%   -0.466%   +3.350%  +11.228%
 6#silesia.tar:  +17.607%  +23.339%   -0.591%   +3.175%  +10.851%
 7#silesia.tar:  +17.463%  +22.837%   -0.486%   +3.292%  +10.868%

* Requires Clang-21 support from LLVM commit hash
  `a53003fe23cb6c871e72d70ff2d3a075a7490da2`
   (Clang-21 hasn’t been released as of this writing)

Co-authored by:
 David Sherwood, David.Sherwood@arm.com
 Ola Liljedahl, Ola.Liljedahl@arm.com
2025-06-24 12:22:23 +00:00
Arpad Panyik
bd38fc2c5f AArch64: Enhance struct access in Huffman decode 2X
In the multi-stream multi-symbol Huffman decoder GCC generates
suboptimal code - emitting more loads for HUF_DEltX2 struct member
accesses. Forcing it to use 32-bit loads and bit arithmetic to extract
the necessary parts (UBFX) improves the overall decode speed.

Also avoid integer type conversions in the symbol decodes, which
leads to better instruction selection in table lookup accesses.

On AArch64 the decoder no longer runs into register-pressure limits,
so we can simplify the hot path and improve throughput

Decompression uplifts on a Neoverse V2 system, using Zstd-1.5.8
compiled with "-O3 -march=armv8.2-a+sve2":

                 Clang-20   Clang-*    GCC-13    GCC-14    GCC-15
 1#silesia.tar:   +0.820%   +1.365%   +2.480%   +1.348%   +0.987%
 2#silesia.tar:   +0.426%   +0.784%   +1.218%   +0.665%   +0.554%
 3#silesia.tar:   +0.112%   +0.389%   +0.508%   +0.188%   +0.261%

* Requires Clang-21 support from LLVM commit hash
  `a53003fe23cb6c871e72d70ff2d3a075a7490da2`
  (Clang-21 hasn’t been released as of this writing)
2025-06-23 14:16:25 +00:00
Yann Collet
3c3b8274c5
Merge pull request #4417 from facebook/dependabot/github_actions/msys2/setup-msys2-2.28.0
Bump msys2/setup-msys2 from 2.27.0 to 2.28.0
2025-06-23 06:32:14 -07:00
dependabot[bot]
7b1b6a0d2d
Bump msys2/setup-msys2 from 2.27.0 to 2.28.0
Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.27.0 to 2.28.0.
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](61f9e5e925...40677d36a5)

---
updated-dependencies:
- dependency-name: msys2/setup-msys2
  dependency-version: 2.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-23 06:24:00 +00:00
Yann Collet
bdceb81271
Merge pull request #4415 from bgilbert/buildtype
meson: drop unused variable
2025-06-21 20:31:26 -07:00
Yann Collet
2e8ec28b30
Merge pull request #4416 from facebook/test_largeDictionary
added test-largeDictionary to dev-long CI script
2025-06-21 12:37:08 -07:00
Yann Collet
2295826266 update tests duration indications 2025-06-21 12:01:07 -07:00
Yann Collet
d77a7b6895 added test-largeDictionary to dev-long CI script 2025-06-21 11:34:10 -07:00
Yann Collet
528132e9a0
Merge pull request #4402 from mugitya03/tests
Release resources in error paths via cleanup
2025-06-21 11:33:44 -07:00
jinyaoguo
878be1c8f0 fix 2025-06-21 13:43:47 -04:00
jinyaoguo
16e13ebdeb delete 2025-06-21 13:03:13 -04:00
jinyaoguo
a74f7fcabd merge 2025-06-21 12:57:12 -04:00
Benjamin Gilbert
a4b9ebcbeb meson: drop unused variable 2025-06-20 23:34:13 -07:00
Arpad Panyik
1e9d2006ae AArch64: Use better block copy8
The vector copy is only necessary for 16-byte blocks on AArch64.

Decompression uplifts on a Neoverse V2 system, using Zstd-1.5.8
compiled with "-O3 -march=armv8.2-a+sve2":

                 Clang-19  Clang-20    GCC-14    GCC-15
 1#silesia.tar:   +0.316%   +0.865%   +0.025%   +0.096%
 2#silesia.tar:   +0.689%   +1.374%   +0.027%   +0.065%
 3#silesia.tar:   +0.811%   +1.654%   +0.034%   +0.033%
 4#silesia.tar:   +0.912%   +1.755%   +0.027%   +0.042%
 5#silesia.tar:   +0.995%   +1.826%   +0.062%   +0.094%
 6#silesia.tar:   +0.976%   +1.777%   +0.065%   +0.104%
 7#silesia.tar:   +0.910%   +1.738%   +0.077%   +0.110%
2025-06-20 17:05:41 +00:00
Yann Collet
7eefc22169
Merge pull request #4367 from ClickHouse/cfi
Add unwind information in huf_decompress_amd64.S
2025-06-19 23:41:38 -07:00
Yann Collet
354cede369
Merge pull request #4412 from Cyan4973/rm_bd
remove duplicate
2025-06-19 14:32:32 -07:00
Yann Collet
e315155cc2 removed duplicate
this file is already present as `largeDictionary.c`
2025-06-18 15:07:32 -07:00
Yann Collet
429dc891b2
Merge pull request #4411 from arpadpanyik-arm/hist_sve2
AArch64: Add SVE2 implementation of histogram computation
2025-06-18 13:48:54 -07:00
Yann Collet
2082749775
Merge pull request #4409 from bgilbert/meson-license
meson: use SPDX expression for license
2025-06-16 10:54:43 -07:00
Yann Collet
4255c5ea89
Merge pull request #4408 from mugitya03/MLK-3
Ensure BMK_timedFnState is always freed in benchMem
2025-06-16 09:01:58 -07:00
Benjamin Gilbert
57bd0eb6a7 meson: use SPDX expression for license
This is the format recommended by Meson documentation.
2025-06-14 19:48:40 -07:00
Arpad Panyik
d28a737750 Add unit tests for HIST_count_wksp
The following tests are included:
- Empty input scenario test.
- Workspace size and alignment tests.
- Symbol out-of-range tests.
- Cover multiple input sizes, vary permitted maximum symbol
  values, and include diverse symbol distributions.

These tests verifies count table correctness, maxSymbolValuePtr
updates, and error-handling paths. It enables automated regression
of core histogram logic as well.
2025-06-13 22:55:53 +00:00
jinyaoguo
cad0b72ad8 Ensure BMK_timedFnState is always freed in benchMem
When an error occurs in BMK_isSuccessful_runOutcome, the code
previously skipped the call to BMK_freeTimedFnState(tfs),
leaking the allocated tfs object.
Fiexed by calling BMK_freeTimedFnState(tfs) before goto _cleanOut.
2025-06-12 19:52:58 -04:00
Arpad Panyik
7e4937bc75 AArch64: Add SVE2 implementation of histogram computation
The existing scalar implementation uses a 4-way pipelined histogram
calculation which is very efficient on out-of-order CPUs. However,
this can be further accelerated using the SVE2 HISTSEG instructions -
which compute a histogram for 16 byte chunks in a vector register.

On a system with 128-bit vectors (VL128) we need 16 HISTSEG executions
to compute the histogram for the whole symbol space (0..255) of 16
bytes input. However we can only accumulate 15 of such 16 byte strips
before possible overflow. So we need to extend and save the 8-bit
histogram accumulators to 16-bit after every 240 byte chunks of input.
To store all in registers we would need 32 128-bit registers. Longer
SVE2 vectors could help here, if such machines become available.

The maximum input block size in Zstd is 128 KiB, so 16-bit accumulators
would not be enough. However an LZ pass will prepend the histogram
calculation, so it is impossible (my assumption) to overflow the 16-bit
accumulators.

The symbol distribution is also not uniform, the lower values are more
common, so we used a 3 pass algorithm to prevent stack spilling. In the
first pass we only compute histograms for 64 symbols (4-way SIMD) while
also computing the maximum symbol value. If we have symbol values
larger than 64 we start the second pass to compute the next 96 elements
of the histogram. The final pass calculates the remaining part of the
histogram (256 symbols in total) if needed. This split of histogram
generation gave the best overall results for performance.

This implementation is the best performing of a number of different
cache blocking schemes tested.

Compression uplifts on a Neoverse V2 system, using Zstd-1.5.8
(e26dde3d) as a baseline, compiled with "-O3 -march=armv8.2-a+sve2":

                 Clang-20    GCC-14
 1#silesia.tar:   +6.173%   +5.987%
 2#silesia.tar:   +5.200%   +5.011%
 3#silesia.tar:   +4.332%   +5.031%
 4#silesia.tar:   +2.789%   +3.064%
 5#silesia.tar:   +2.028%   +1.838%
 6#silesia.tar:   +1.562%   +1.340%
 7#silesia.tar:   +1.160%   +0.959%
2025-06-11 12:14:22 +00:00
Yann Collet
5e6bdf5e3d
Merge pull request #4406 from Cyan4973/separate-cmake-tests
cmake CI tests refactor
2025-06-09 15:19:47 -07:00
Yann Collet
9a6fe9a428 remove global variable
overkill and leaky to transport a test result just in one place.
2025-06-09 21:55:06 +00:00
Yann Collet
88bea95d11
Merge pull request #4403 from dloidolt/fix_FUZZ_malloc_rand
fuzz: Fix FUZZ_malloc_rand() to return non-NULL for zero-size allocations
2025-06-09 10:57:59 -07:00
Yann Collet
39c091bc9e
Merge pull request #4397 from xiaoge1001/free
Fix several locations with potential memory leak
2025-06-09 10:06:36 -07:00
shixuantong
de8d9e8914 Fix several locations with potential memory leak 2025-06-09 21:23:23 +08:00
Yann Collet
472acf5d83 fix #4405 2025-06-09 07:24:03 +00:00
Yann Collet
7e0324e124 fixed cmake + windows + visual + clang-cl
by removing processing of resource files in this case
2025-06-09 07:09:51 +00:00
Yann Collet
b6dc2924f8 remove fail-fast so that the outcome of other tests can be observed 2025-06-09 06:59:18 +00:00
Yann Collet
49fe2ec793 refactor: modularize CMakeLists.txt for better maintainability
- Split monolithic 235-line CMakeLists.txt into focused modules
- Main file reduced to 78 lines with clear section organization
- Created 5 specialized modules:
  * ZstdVersion.cmake - CMake policies and version management
  * ZstdOptions.cmake - Build options and platform configuration
  * ZstdDependencies.cmake - External dependency management
  * ZstdBuild.cmake - Build targets and validation
  * ZstdPackage.cmake - Package configuration generation

Benefits:
- Improved readability and maintainability
- Better separation of concerns
- Easier debugging and modification
- Preserved 100% backward compatibility
- All existing build options and targets unchanged

The refactored build system passes all tests and maintains
identical functionality while being much easier to understand
and maintain.
2025-06-09 03:47:33 +00:00
Yann Collet
75abb8bc1c add cmake build test with ZSTD_BUILD_TESTS disabled
should reproduce #4405 and fail
2025-06-09 00:05:19 +00:00
Yann Collet
c826c572cf added macos arm64 tests
and comment out windows arm64 tests due to unacceptably long queue time
2025-06-08 22:40:15 +00:00
Yann Collet
a168ae7232 added windows arm64 runner to cmake tests 2025-06-08 22:19:57 +00:00
Yann Collet
b922774602 refactor CMake tests workflow for readability 2025-06-08 21:44:21 +00:00
Yann Collet
a2dba85fd1 ci: separate cmake tests into dedicated workflow file
- Create new .github/workflows/cmake-tests.yml with all cmake-related jobs
- Move cmake-build-and-test-check, cmake-source-directory-with-spaces, and cmake-visual-2022 jobs
- Remove cmake tests from dev-short-tests.yml to improve organization
- Maintain same trigger conditions and test configurations
- Add dedicated concurrency group for cmake tests

This separation allows cmake tests to run independently and makes
the CI configuration more modular and easier to maintain.
2025-06-08 20:25:25 +00:00
Yann Collet
ec8ad2e552
Merge pull request #4384 from xiaoge1001/dev
update `--rm` cmd help info
2025-06-08 12:39:26 -07:00
Yann Collet
5b6fbf5f96
Merge pull request #4392 from mugitya03/MLK
Fix potential memory leak in function `benchMem`
2025-06-08 12:38:31 -07:00
Yann Collet
e23d0a9616
Merge pull request #4399 from zijianli1234/dev
Improve speed of convertSequences() and get1BlockSummary() using RVV
2025-06-08 12:38:02 -07:00
Michael Kolupaev
a480191f9e Fix Darwin build of huf_decompress_amd64.S 2025-06-08 05:07:09 +00:00
Michael Kolupaev
80cac404c7 Add unwind information in huf_decompress_amd64.S 2025-06-08 05:07:09 +00:00
Dominik Loidolt
4be08ba122 fuzz: Fix FUZZ_malloc_rand() to return non-NULL for zero-size allocations
The FUZZ_malloc_rand() function was incorrectly always returning NULL for
zero-size allocations. The random offset generated by
FUZZ_dataProducer_int32Range() was not being added to the pointer variable,
causing the function to always return (void *)0.
2025-06-05 17:28:30 +02:00
jinyaoguo
a81ffe11d4 Release resources in error paths via cleanup
Replace direct returns in error-handling branches with a unified
cleanup block that frees allocated resources before returning,
improving code quality and robustness.
2025-06-04 18:08:11 -04:00
Yann Collet
bd894054c0
Merge pull request #4401 from mugitya03/MLK-1
Release resources before returning
2025-06-04 12:49:38 -07:00
jinyaoguo
dd4cee9190 Release resources before returning
In main, resources were freed on the success path but not in the error path.
This change ensures all allocated resources are released before returning.
2025-06-03 15:28:11 -04:00
李子建
d95123f2e6 Improve speed of ZSTD_compressSequencesAndLiterals() using RVV 2025-06-02 17:21:02 +08:00
shixuantong
4bd5654e72 update --rm cmd help info
Starting from cee6bec9fa, --rm is ignored when the output is `stdout`.
2025-05-30 06:49:52 +08:00
jinyaoguo
4618b255ea Fix memory leak in function benchMem
`speedPerRound` is allocated at the start of benchMem to collect per-round speeds,
but is never freed, causing a leak on each invocation.
2025-05-25 15:21:23 -04:00
Dave Vasilevsky
f9938c217d lz4: Remove ancient test helpers
Building lz4 as root was causing `make clean` to fail with permission
errors.

We used to have to install lz4 from source back in Ubuntu 14.04, but
nowadays the installed lz4 is fine. Get rid of ancient helpers and
cruft!
2025-05-07 22:01:49 -07:00
Dave Vasilevsky
448a09ff78 seekable_format: Fix conversion warnings in parallel_compression 2025-05-07 22:01:49 -07:00
Dave Vasilevsky
13cb7a10ae seekable_format: Add test for parallel_compression memory usage
Use ulimit to fail the test if we use O(filesize) memory, rather than
O(threads).
2025-05-07 22:01:49 -07:00
Dave Vasilevsky
01c973de8d seekable_format: Fix race in parallel_processing
There was no memory barrier between writing and reading `done`, which
would allow reordering to cause races. With so little data to handle
after each job completes, we might as well just join.
2025-05-07 22:01:49 -07:00
Dave Vasilevsky
6fc8455a72 seekable_format: Cleanup POOL in parallel_compression 2025-05-07 22:01:49 -07:00
Dave Vasilevsky
2d4cff69c4 seekable_format: Make parallel_compression use memory properly
Previously, parallel_compression would only handle each job's results
after ALL jobs were successfully queued. This caused all src/dst
buffers to remain in memory until then!

It also polled to check whether a job completed, which is racy without
any memory barrier.

Now, we flush results as a side effect of completing a job. Completed
frames are placed in an ordered linked-list, and any eligible frames
are flushed. This may be zero or multiple frames, depending on the
order in which jobs finish.

This design also makes it simple to support streaming input, so that
is now available. Just pass `-` as the filename, and stdin/stdout will
be used for I/O.
2025-05-07 22:01:49 -07:00
Dave Vasilevsky
f5b6531902 seekable_format: Link against multi-threaded libzstd.a
Some of these examples are intended to be parallel, and don't make
sense to link against single-threaded libzstd.

The filename of mt and nomt libzstd are identical, so it's still
possible to link against the single-threaded one, just harder.
2025-05-07 22:01:49 -07:00
Dave Vasilevsky
6b0039abcf seekable_format: Build with $(MAKE)
This passes make flags, such as `-jN` for building in parallel, to
the underlying make.
2025-05-07 22:01:49 -07:00
Thomas Devoogdt
769723aee2 [cmake] only require a CXX compiler when tests are build
Signed-off-by: Thomas Devoogdt <thomas@devoogdt.com>
2025-05-06 12:20:26 -07:00
Nobuhiro Iwamatsu
2d224dc745 Add License variable to pkg-config file
The pkg-config file has License variable that allows you to set the license for
the software. This sets 'BSD-3-Clause OR GPL-2.0-only' to License.

Ref: https://github.com/pkgconf/pkgconf/blob/master/man/pc.5#L116
Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
2025-05-06 12:16:28 -07:00
Yann Collet
e26dde3dcf
Merge pull request #4378 from Cyan4973/fix_zstreamtest_minor
fix minor warning in zstreamtest
2025-04-29 14:01:14 -07:00
Yann Collet
453e252015
Merge pull request #4371 from ecordonnier-sc/eco/fix-macos-duplicate-lc-rpath
Fix duplicate LC_RPATH error on MacOS
2025-04-29 14:00:41 -07:00
Yann Collet
7f907d5c23 fix minor warning in zstreamtest 2025-04-29 09:56:00 -07:00
Etienne Cordonnier
8929d3b09f Fix duplicate LC_RPATH error on MacOS
After the update to MacOS 15.4, the dynamic loader dyld treats duplicated LC_RPATH as an error.
The `FLAGS` variable already contains `LDFLAGS`, thus using both `FLAGS` and `LDFLAGS`
duplicates all `LDFLAGS`, including `-Wl,rpath` parameters.

The duplicate LC_RPATH causes this kind of errors:

```
dyld[29361]: Library not loaded: @loader_path/../lib/libzstd.1.dylib
      Referenced from: <7131C877-3CF0-33AC-AA05-257BA4FDD770> /Users/foobar/...
      Reason: tried: '/Users/foobar/..../lib/libzstd.1.dylib' (duplicate LC_RPATH '/usr/mypath.../lib')
```

Closes https://github.com/facebook/zstd/issues/4369

Signed-off-by: Etienne Cordonnier <ecordonnier@snap.com>
2025-04-18 15:59:06 +02:00
Yann Collet
d654fca786
Merge pull request #4362 from facebook/dependabot/github_actions/actions/setup-java-4.7.1
Bump actions/setup-java from 4.7.0 to 4.7.1
2025-04-14 03:19:07 -07:00
dependabot[bot]
28ffb100ab
Bump actions/setup-java from 4.7.0 to 4.7.1
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.0 to 4.7.1.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](3a4f6e1af5...c5195efecf)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 4.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 05:21:33 +00:00
Yann Collet
f5d4da09f5
Merge pull request #4353 from afq984/sparse
Check regular file for sparse support after opening
2025-04-07 03:48:41 -07:00
Li-Yu Yu
2a12bbaf90 Update cli-tests/file-stat tests 2025-03-28 22:46:26 +00:00
Li-Yu Yu
3bd5aa3404 Check regular file for sparse support after opening
A regular file may be created by the open call.
Checking after opening allows sparseFileSupport even
if dstFileName does not already exist.
2025-03-28 21:23:10 +00:00
Yann Collet
c5926fbab8
Merge pull request #4349 from Cyan4973/devfd
Support process substitution for `--filelist=`
2025-03-28 10:35:45 -07:00
Yann Collet
2f9627863f update error message 2025-03-28 10:02:37 -07:00
Yann Collet
0bdeb1d204 fix test 2025-03-28 09:18:17 -07:00
Yann Collet
8626da73b6 add error message clarification for inputs as process substitution 2025-03-28 09:18:17 -07:00
Yann Collet
a293cdcb85 added CI test 2025-03-28 09:18:17 -07:00
Yann Collet
0bde39a9b3 visual studio fix 2025-03-28 09:18:17 -07:00
Yann Collet
94cfa0b5a0 minor: restore some code comment 2025-03-28 09:18:17 -07:00
Yann Collet
76c2fdc7b7 better naming
and more narrow scope of local variables
2025-03-28 09:18:17 -07:00
Yann Collet
7630870b47 second implementation, better structured for improved maintenance 2025-03-28 09:18:17 -07:00
Yann Collet
165e52ce62 first implementation supporting Process Substitution 2025-03-28 09:18:17 -07:00
Yann Collet
7f0519dcfd
Merge pull request #4346 from Cyan4973/wintime
fix a risk of overflow on a time counter on Windows
2025-03-27 21:07:57 -07:00
Yann Collet
23e8812f5b
Merge pull request #4350 from Cyan4973/patchapply
add --patch-apply command
2025-03-27 09:57:20 -07:00
Yann Collet
eb168a0afc add --patch-apply command
as an equivalent for `-d --patch-from`.
Requested by @sergeevabc in #2173.
2025-03-25 14:50:39 -07:00
Yann Collet
12ea5f6e30
Merge pull request #4314 from facebook/dependabot/github_actions/ossf/scorecard-action-2.4.1
Bump ossf/scorecard-action from 2.4.0 to 2.4.1
2025-03-24 18:33:51 -07:00
Yann Collet
ec40252066
Merge pull request #4345 from Cyan4973/block128
[doc] minor clarification for maximum block size
2025-03-24 18:33:01 -07:00
Yann Collet
64dc08f47f
Merge pull request #4344 from Cyan4973/assert1
add an assert
2025-03-24 18:32:37 -07:00
Yann Collet
334af72280 update zstd --fast benchmark result
use --fast=4, instead of --fast=3,
to make it more representative of a lzo equivalent scenario.
2025-03-23 12:06:58 -07:00
Yann Collet
c59f7ac51e update benchmark result
brotli uses -1 level, like all other compressors
2025-03-23 12:02:51 -07:00
Yann Collet
33f4d40d1e fix a risk of overflow on a time counter on Windows
closes #4126
2025-03-23 11:42:41 -07:00
Yann Collet
bea1e942f7 [doc] minor clarification for maximum block size
closes #4339
2025-03-22 23:52:45 -07:00
Yann Collet
2fec3989c1 add an assert
to help static analyzers understand there is no overflow risk there.
2025-03-22 18:23:31 -07:00
Yann Collet
6775af5b2e
Merge pull request #4341 from clan/pragma
lib/zstd.h: don't put pragma after static
2025-03-20 19:49:08 -07:00
Z. Liu
cd8ca9d92e lib/zstd.h: move pragma before static
otherwise will cause dev-python/zstandard build failed when compiling with
clang as reported at https://bugs.gentoo.org/950259

the root cause is pycparser, which is unfixed since reported 2.5 years
ago, :(

Signed-off-by: Z. Liu <zhixu.liu@gmail.com>
2025-03-20 03:40:42 +00:00
Yann Collet
eca205fc78
Merge pull request #4336 from Cyan4973/qsort_v2
fix #4312 - musl compilation compatibility
2025-03-12 10:31:54 -07:00
Yann Collet
4d53e27144 removed OpenBSD specificity 2025-03-12 09:55:14 -07:00
Yann Collet
ddcb41a282 updated documentation 2025-03-11 14:10:35 -07:00
Yann Collet
a9b8fef2e8 add support for C11 Annex K qsort_s()
standard defined re-entrant variant of qsort().
Unfortunately, Annex K is optional.
2025-03-11 14:10:35 -07:00
Yann Collet
dcf675886b re-design qsort() selection in cover
centralizes auto detection tests,
then distribute the outcome in all the places where it's active.
2025-03-11 14:10:35 -07:00
Yann Collet
51b6e79f65 fix #4312
and upgraded the test so that it would fail, both at compile time and at run time, without the fix
2025-03-11 14:10:35 -07:00
Yann Collet
9a57bdc0bd attempt to reduce length of long cli tests by invoking -T0 2025-03-11 14:10:35 -07:00
Nick Terrell
68dfd14a8c [linux] Opt out of row based match finder for the kernel
The row based match finder is slower without SIMD. We used to detect the
presence of SIMD to set the lower bound to 17, but that breaks
determinism. Instead, specifically opt into it for the kernel, because
it is one of the rare cases that doesn't have SIMD support.
2025-03-11 16:18:59 -04:00
Yann Collet
b27ba56a6d
Merge pull request #4335 from Cyan4973/dec_mt_warning
warn when requesting decompression with multiple threads
2025-03-11 11:51:15 -07:00
Yann Collet
19541b4d1a fix minor unused variable warning 2025-03-11 00:17:45 -07:00
Yann Collet
c583c2c39e warn when requesting decompression with multiple threads
restore #2918 fix
2025-03-10 22:50:00 -07:00
Yann Collet
f9a6031963
Merge pull request #4334 from Cyan4973/fix4332
fix #4332: setting ZSTD_NBTHREADS=0 via environment variable
2025-03-10 21:12:24 -08:00
Yann Collet
3c4096c83e fixed ShellCheck warning 2025-03-10 19:11:44 -07:00
Yann Collet
2ff87aefac fix FreeBSD
use an alias instead of a function

also: added more traces and updated version nb to v1.5.8
2025-03-10 19:04:41 -07:00
Yann Collet
c18374bb16 add test
checks that ZSTD_NBTHREADS triggers the expected verbose message

Also: checked that the new test script fails on current `dev` branch, and is fixed by this branch
2025-03-10 13:40:47 -07:00
Yann Collet
56e2ebf5c3 removed useless assert() 2025-03-10 09:54:06 -07:00
Yann Collet
d5986f235f fix #4332: setting ZSTD_NBTHREADS=0 via environment variables 2025-03-10 00:12:34 -07:00
Nick Terrell
b16d193512 [test] Add tests for determinism
Run compression & validate the compressed file matches a known checksum.

To update the output run:

```
make -C tests update-cli-tests
```
2025-03-07 10:31:19 -05:00
Nick Terrell
0de4991942 Add a method for checking if ZSTD was compiled with flags that impact determinism 2025-03-07 10:31:19 -05:00
Yann Collet
99cf130cfc
Merge pull request #4329 from Cyan4973/cmd_split
New commands --split and --jobsize
2025-03-05 07:46:04 -08:00
Nick Terrell
190a620974 [zstd] Remove global variables in dictBuilder
D50949782 fixed a race condition updating `g_displayLevel` by disabling display.
Instead of disabling display, delete the global variable and always "capture" a local `displayLevel` variable.
This also fixes `DISPLAYUPDATE()` by requiring the user to pass in the last update time as the first parameter.
2025-03-05 10:35:01 -05:00
Nick Terrell
d5b84f5a27 [zstd] Backport D49756856 2025-03-05 10:35:01 -05:00
Yann Collet
5e7d721235
Merge pull request #4327 from Cyan4973/win_artifacts
Generate Zstandard binaries for Windows with lz4 support
2025-03-04 16:08:01 -08:00
Yann Collet
5ae1cb9fa1 added a cli test for new command --jobsize 2025-03-04 15:24:43 -08:00
Yann Collet
f5a0e047cb fix typo 2025-03-04 15:12:35 -08:00
Yann Collet
0b40c513fd update fileio to employ jobSize 2025-03-04 14:55:25 -08:00
Yann Collet
0298df50f9 update cli-tests 2025-03-04 14:43:06 -08:00
Yann Collet
9b8b414833 updated playTests.sh to employ the new commands 2025-03-04 13:22:01 -08:00
Yann Collet
19ffcf81b8 changed -B# command into --jobsize
to reduce confusion with the term "block".

-B# remains supported for existing scripts,
but it's no longer documented, so it's effectively a hidden shortcut.
2025-03-04 13:17:10 -08:00
Yann Collet
fcfb3160dc convert benchmark unit to use the new naming scheme
chunks instead of blocks
2025-03-04 13:04:59 -08:00
Yann Collet
d5dbdd6ece changed command --blocksize into --split
to reduce confusion with the concept of "blocks" inside a Zstandard frame.

We are now talking about "independent chunks" being produced by a `split` operation.

updated documentation accordingly.

Note: old commands "-B#` and `--blocksize=#` remain supported,
to maintain compatibility with existing scripts.
2025-03-04 12:53:23 -08:00
Yann Collet
bceb8f2dbc attempt to no longer depend on system library presence for autodetection
use explicit opt-in and path setting
2025-03-03 17:20:43 -08:00
Yann Collet
9ec1a7c0ac update zstd build recipe to also support lz4 format 2025-03-03 15:36:38 -08:00
Yann Collet
7df457a51d
Merge pull request #4324 from facebook/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2025-03-03 10:39:50 -08:00
Yann Collet
cab2a29c36
Update windows-artifacts.yml
edit version comment
2025-03-02 23:11:35 -08:00
Yann Collet
3c6c472f01
Update scorecards.yml
edit version comment
2025-03-02 23:11:08 -08:00
Yann Collet
46b2e05a33
Update publish-release-artifacts.yml
fix version comment
2025-03-02 23:10:09 -08:00
dependabot[bot]
83db5376d7
Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 05:44:17 +00:00
Sergey Senozhatsky
0727fc5ff9 lib: zstd: export API needed for dictionary support
Patch series "zram: introduce custom comp backends API", v7.

This series introduces support for run-time compression algorithms tuning,
so users, for instance, can adjust compression/acceleration levels and
provide pre-trained compression/decompression dictionaries which certain
algorithms support.

At this point we stop supporting (old/deprecated) comp API.  We may add
new acomp API support in the future, but before that zram needs to undergo
some major rework (we are not ready for async compression).

Some benchmarks for reference (look at column #2)

*** init zstd
/sys/block/zram0/mm_stat
1750659072 504622188 514355200        0 514355200        1        0    34204    34204

*** init zstd dict=/home/ss/zstd-dict-amd64
/sys/block/zram0/mm_stat
1750650880 465908890 475398144        0 475398144        1        0    34185    34185

*** init zstd level=8 dict=/home/ss/zstd-dict-amd64
/sys/block/zram0/mm_stat
1750654976 430803319 439873536        0 439873536        1        0    34185    34185

*** init lz4
/sys/block/zram0/mm_stat
1750646784 664266564 677060608        0 677060608        1        0    34288    34288

*** init lz4 dict=/home/ss/lz4-dict-amd64
/sys/block/zram0/mm_stat
1750650880 619990300 632102912        0 632102912        1        0    34278    34278

*** init lz4hc
/sys/block/zram0/mm_stat
1750630400 609023822 621232128        0 621232128        1        0    34288    34288

*** init lz4hc dict=/home/ss/lz4-dict-amd64
/sys/block/zram0/mm_stat
1750659072 505133172 515231744        0 515231744        1        0    34278    34278

Recompress
init zram zstd (prio=0), zstd level=5 (prio 1), zstd with dict (prio 2)

*** zstd
/sys/block/zram0/mm_stat
1750982656 504630584 514269184        0 514269184        1        0    34204    34204

*** idle recompress priority=1 (zstd level=5)
/sys/block/zram0/mm_stat
1750982656 488645601 525438976        0 514269184        1        0    34204    34204

*** idle recompress priority=2 (zstd dict)
/sys/block/zram0/mm_stat
1750982656 460869640 517914624        0 514269184        1        0    34185    34204

This patch (of 24):

We need to export a number of API functions that enable advanced zstd
usage - C/D dictionaries, dictionaries sharing between contexts, etc.

Link: https://lkml.kernel.org/r/20240902105656.1383858-1-senozhatsky@chromium.org
Link: https://lkml.kernel.org/r/20240902105656.1383858-2-senozhatsky@chromium.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Nick Terrell <terrelln@fb.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2025-02-28 17:09:46 -05:00
Yann Collet
a9337e6739
Merge pull request #4321 from Cyan4973/win_artifacts
Automate Windows Artifact generation and publication
2025-02-28 12:35:06 -08:00
Yann Collet
e99be473a6 automatically upload windows artifact on Release Tag creation 2025-02-28 12:04:06 -08:00
Yann Collet
bbbb2379ed test win artifact generation on pushing to release
this will get a chance to check that win artifact generation works correctly
before creating the release tag.
2025-02-28 09:42:50 -08:00
Yann Collet
a6d232dcad avoid double zipping 2025-02-28 09:33:22 -08:00
Yann Collet
88100bc62f proper usage of standard variables 2025-02-27 16:59:40 -08:00
Yann Collet
4e1723a7e4 fixed the script so that it fails when a copy fails
and also: fix the list of files, as `zdict.h` was incorrectly set.
2025-02-27 16:18:44 -08:00
Yann Collet
7340657c6f update build_package.bat by using a subrouting 2025-02-27 16:18:44 -08:00
Yann Collet
77e58994d2 updated zlib version to more recent v1.3.1 2025-02-27 16:18:44 -08:00
Yann Collet
e94e09dd7b ensure that a copy error results in the task failing clearly
error code != 0, red status

checked by intentionally inserting an error in another run
2025-02-27 16:18:44 -08:00
Yann Collet
017ada44b5
Merge pull request #4322 from Cyan4973/meson_win
fix the meson windows build
2025-02-27 16:17:34 -08:00
Yann Collet
bbf2801ddd try to fix the meson windows build
apparently could be just a missing include
2025-02-27 15:45:59 -08:00
Yann Collet
a1a5154b69
Merge pull request #4312 from Cyan4973/musl_ci
introduce ZSTD_USE_C90_QSORT
2025-02-27 14:27:21 -08:00
Yann Collet
22b2fd2517
Merge pull request #4317 from hirohira9119/fix-function-signature
Fix function signature mismatch for ZSTD_convertBlockSequences
2025-02-27 13:03:03 -08:00
Yann Collet
d6fbaaac99
Merge pull request #4320 from sebres/patch-1
build_package.bat: fix path to zstd_errors.h, avoid silently ignore of the errors if build failed
2025-02-26 15:15:03 -08:00
Yann Collet
0ac659fb00
Merge pull request #4319 from Cyan4973/Wconversion
step towards -Wconversion
2025-02-26 15:14:52 -08:00
Yann Collet
dca9791862 fixed minor C++ compat warnings 2025-02-26 14:30:29 -08:00
Sergey G. Brester
4d81b0000d
GHA/windows-artifacts.yml: don't ignore the error if build-package batch failed 2025-02-26 20:13:44 +01:00
Sergey G. Brester
f0d3173203
build_package.bat: don't swallow the error(s) by copy, exit with error if failed somewhere 2025-02-26 20:02:48 +01:00
Sergey G. Brester
97bc43cc68
build_package.bat: fix path to zstd_errors.h (it is in lib not in lib/common)
closes gh-4318
2025-02-26 19:27:44 +01:00
Yann Collet
db2d205ada fixed -Wconversion for lib/decompress/zstd_decompress_block.c 2025-02-26 10:01:05 -08:00
Yann Collet
2413f17322 fixed -Wconversion for cover.c 2025-02-26 08:33:01 -08:00
Yann Collet
8ffa27d93b fixed -Wconversion for divsufsort.c 2025-02-26 08:12:11 -08:00
Yann Collet
e635221f1b fixed -Wconversion for zdict 2025-02-26 08:07:51 -08:00
Yann Collet
30281d889f fix conversion warning 2025-02-26 07:41:34 -08:00
hirohira
2840631dc1 Fix function signature mismatch for ZSTD_convertBlockSequences 2025-02-26 08:23:48 +09:00
Yann Collet
76779f52c2
Merge pull request #4310 from Cyan4973/cmake_target_compile
[cmake] use target_compile_definitions
2025-02-25 10:04:10 -08:00
Yann Collet
3ff0d794b8
Merge pull request #4309 from Cyan4973/check_manual
Check API manual and man pages before release
2025-02-24 15:17:11 -08:00
Yann Collet
5743da491b
Merge pull request #4315 from facebook/dependabot/github_actions/msys2/setup-msys2-2.27.0
Bump msys2/setup-msys2 from 2.26.0 to 2.27.0
2025-02-24 01:53:48 -08:00
dependabot[bot]
e1e2f3873d
Bump msys2/setup-msys2 from 2.26.0 to 2.27.0
Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.26.0 to 2.27.0.
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](d44ca8e88d...61f9e5e925)

---
updated-dependencies:
- dependency-name: msys2/setup-msys2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 05:44:08 +00:00
dependabot[bot]
b40dabeda2
Bump ossf/scorecard-action from 2.4.0 to 2.4.1
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.0 to 2.4.1.
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](62b2cac7ed...f49aabe0b5)

---
updated-dependencies:
- dependency-name: ossf/scorecard-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 05:44:05 +00:00
Yann Collet
fd5498a179 document ZSTD_USE_C90_QSORT 2025-02-21 12:48:26 -08:00
Yann Collet
ebfa660b82 introduce ZSTD_USE_C90_QSORT 2025-02-21 11:36:30 -08:00
Yann Collet
8ff47f3df0 added musl compilation test in CI 2025-02-21 09:57:55 -08:00
Yann Collet
0c3345d6ec [cmake] use target_compile_definitions
which is considered best practice.
2025-02-20 16:00:54 -08:00
Yann Collet
c2ab0f9c4e check man page update 2025-02-20 13:14:11 -08:00
Yann Collet
4690d66c7e add CI check for zstd_manual before release
ensures it's properly updated
2025-02-20 13:00:16 -08:00
Yann Collet
1bef87857b
Merge pull request #4302 from facebook/man157
updated man pages and manual
2025-02-19 16:56:55 -08:00
Yann Collet
6af3842118 updated man pages and manual
fixes #4301
2025-02-19 16:25:00 -08:00
Yann Collet
d157156bb8
Merge pull request #4300 from facebook/bench_157
updated benchmark numbers for v1.5.7
2025-02-18 22:18:57 -08:00
Yann Collet
37077c859b updated benchmark numbers
using latest version of @inikep's lzbench
2025-02-18 21:22:02 -08:00
Yann Collet
eb6608869f faster clang-msan-testzstd
this is by far our longest CI test.
Attempt to make it run a bit faster.
2025-02-18 16:19:18 -08:00
152 changed files with 6276 additions and 1882 deletions

View file

@ -2,7 +2,7 @@ task:
name: FreeBSD (make check)
freebsd_instance:
matrix:
image_family: freebsd-14-2
image_family: freebsd-15-0-amd64-zfs
install_script: pkg install -y gmake coreutils
script: |
MOREFLAGS="-Werror" gmake -j all

View file

@ -3,4 +3,4 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
interval: "monthly"

View file

@ -13,16 +13,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Set up JDK 17
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0
with:
java-version: '17'
distribution: 'temurin'
- name: Setup Android SDK
uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407 # v3.2.2
uses: android-actions/setup-android@651bceb6f9ca583f16b8d75b62c36ded2ae6fc9c # v4.0.0
- name: Install Android NDK
run: |
@ -37,3 +37,14 @@ jobs:
RANLIB=llvm-ranlib \
STRIP=llvm-strip
- name: Build with CMake and NDK
run: |
mkdir -p build-android
cd build-android
cmake --version
cmake ../build/cmake \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-21 \
-DCMAKE_BUILD_TYPE=Release
cmake --build . --parallel

168
.github/workflows/cmake-tests.yml vendored Normal file
View file

@ -0,0 +1,168 @@
name: cmake-tests
# CMake-specific build and test workflows
# This workflow validates zstd builds across different CMake configurations,
# platforms, and edge cases to ensure broad compatibility.
concurrency:
group: cmake-${{ github.ref }}
cancel-in-progress: true
on:
pull_request:
branches: [ dev, release, actionsTest ]
permissions: read-all
env:
# Centralized test timeouts for consistency
QUICK_TEST_TIME: "30s"
STANDARD_TEST_TIME: "1mn"
# Common CMake flags
COMMON_CMAKE_FLAGS: "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON"
jobs:
# Basic cmake build using the root CMakeLists.txt
# Provides a lightweight sanity check that the top-level project config builds
# with the default Unix Makefiles generator driven purely through cmake commands
cmake-root-basic:
name: "CMake Root Build"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Configure (Root)
run: |
cmake -S . -B cmake-build -DCMAKE_BUILD_TYPE=Release ${{ env.COMMON_CMAKE_FLAGS }}
- name: Build (Root)
run: |
cmake --build cmake-build --config Release
# Ubuntu-based cmake build using make wrapper
# This test uses the make-driven cmake build to ensure compatibility
# with the existing build system integration
cmake-ubuntu-basic:
name: "CMake build using make wrapper"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Install dependencies
run: |
sudo apt install liblzma-dev # Required for compression algorithms
- name: CMake build and test via make
run: |
# Use make wrapper for cmake build with quick test timeouts
FUZZERTEST=-T${{ env.STANDARD_TEST_TIME }} ZSTREAM_TESTTIME=-T${{ env.STANDARD_TEST_TIME }} make cmakebuild V=1
# Cross-platform cmake build with edge case: source paths containing spaces
# This test ensures cmake handles filesystem paths with spaces correctly
# across different operating systems and build generators
cmake-cross-platform-spaces:
name: "CMake Cross-Platform (Spaces in Path)"
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
generator: "Unix Makefiles"
name: "Linux"
- os: windows-latest
generator: "NMake Makefiles"
name: "Windows NMake"
- os: macos-latest
generator: "Unix Makefiles"
name: "macOS"
env:
SRC_DIR: "source directory with spaces"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
with:
path: "${{ env.SRC_DIR }}"
- uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
if: ${{ matrix.generator == 'NMake Makefiles' }}
- name: "CMake build and install (${{ matrix.name }})"
run: |
# Test Release build with installation to verify packaging
cmake -S "${{ env.SRC_DIR }}/build/cmake" -B build -DBUILD_TESTING=ON -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=Release --install-prefix "${{ runner.temp }}/install"
cmake --build build --config Release
cmake --install build --config Release
# Windows-specific cmake testing with Visual Studio 2022
# Tests multiple generators and toolchains to ensure broad Windows compatibility
# including MSVC (x64, Win32, ARM64), MinGW, and Clang-CL with various architectures and optimizations
cmake-windows-comprehensive:
name: "CMake Windows VS2022 (${{ matrix.name }})"
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- generator: "Visual Studio 17 2022"
flags: "-A x64"
name: "MSVC x64"
runner: "windows-2022"
cmake_extra_flags: "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON"
- generator: "Visual Studio 17 2022"
flags: "-A Win32"
name: "MSVC Win32"
runner: "windows-2022"
cmake_extra_flags: "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON"
- generator: "Visual Studio 17 2022"
flags: "-A x64"
name: "MSVC x64 (No ZSTD_BUILD_TESTS)"
runner: "windows-2022"
# Intentionally omit ZSTD_BUILD_TESTS to reproduce the CXX language configuration bug
cmake_extra_flags: "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON"
- generator: "Visual Studio 17 2022"
flags: "-A ARM64"
name: "MSVC ARM64"
runner: "windows-11-arm" # githuh runner for WOA instance
- generator: "MinGW Makefiles"
flags: ""
name: "MinGW"
runner: "windows-2022"
cmake_extra_flags: "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON"
- generator: "Visual Studio 17 2022"
flags: "-T ClangCL"
name: "Clang-CL"
runner: "windows-2022"
cmake_extra_flags: "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON"
- generator: "Visual Studio 17 2022"
flags: "-T ClangCL -A x64 -DCMAKE_C_FLAGS=/arch:AVX2"
name: "Clang-CL AVX2"
runner: "windows-2022"
cmake_extra_flags: "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # tag=v3.0.0
- name: "Configure CMake (${{ matrix.name }})"
run: |
cd build\cmake
mkdir build
cd build
cmake.exe -G "${{matrix.generator}}" ${{matrix.flags}} -DCMAKE_BUILD_TYPE=Debug ${{ matrix.cmake_extra_flags }} -DZSTD_ZSTREAM_FLAGS=-T${{ env.QUICK_TEST_TIME }} -DZSTD_FUZZER_FLAGS=-T${{ env.QUICK_TEST_TIME }} -DZSTD_FULLBENCH_FLAGS=-i0 ..
- name: "Build (${{ matrix.name }})"
run: |
cd build\cmake\build
cmake.exe --build .
- name: "Test (${{ matrix.name }})"
run: |
cd build\cmake\build
ctest.exe -V -C Debug
# macOS ARM64 (Apple Silicon) specific cmake testing
# Validates zstd builds and runs correctly on Apple Silicon architecture
# Uses native ARM64 hardware for optimal performance and compatibility testing
cmake-macos-arm64:
name: "CMake macOS ARM64 (Apple Silicon)"
runs-on: macos-14 # ARM64 runner
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: "CMake build and test (ARM64)"
run: |
# Configure and build with ARM64-specific optimizations
cd build/cmake
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ${{ env.COMMON_CMAKE_FLAGS }} -DZSTD_ZSTREAM_FLAGS=-T${{ env.QUICK_TEST_TIME }} -DZSTD_FUZZER_FLAGS=-T${{ env.QUICK_TEST_TIME }} -DZSTD_FULLBENCH_FLAGS=-i1 ..
make -j$(sysctl -n hw.ncpu)
ctest -V

View file

@ -17,7 +17,7 @@ jobs:
image: fbopensource/zstd-circleci-primary:0.0.1
options: --entrypoint /bin/bash
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6.0.2
- name: Install Dependencies
run: |
sudo apt-get update
@ -40,7 +40,7 @@ jobs:
image: fbopensource/zstd-circleci-primary:0.0.1
options: --entrypoint /bin/bash
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6.0.2
- name: Install Dependencies
run: |
sudo apt-get update
@ -73,9 +73,9 @@ jobs:
env:
CIRCLE_ARTIFACTS: "/tmp/circleci-artifacts"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6.0.2
- name: restore_cache
uses: actions/cache@v4
uses: actions/cache@v6
with:
key: regression-cache-{{ checksum "tests/regression/data.c" }}-v0
path: tests/regression/cache
@ -99,6 +99,6 @@ jobs:
echo " are still good, copy it into the repo and commit it."
echo "> diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv"
diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7.0.1
with:
path: "/tmp/circleci-artifacts"

View file

@ -1,5 +1,5 @@
name: dev-long-tests
# Tests longer than 10mn
# Tests generally longer than 10mn
concurrency:
group: long-${{ github.ref }}
@ -12,40 +12,44 @@ on:
permissions: read-all
jobs:
# lasts ~7mn
make-all:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: make all
run: make all
# lasts ~24mn
# lasts ~19mn
make-test:
runs-on: ubuntu-latest
env:
DEVNULLRIGHTS: 1
READFROMBLOCKDEVICE: 1
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: make test
run: make test
run: |
make test
make -j zstd
./tests/test_process_substitution.bash ./zstd
# lasts ~26mn
# lasts ~16mn
make-test-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: make test on macos
run: make test
# lasts ~24mn
# lasts ~10mn
make-test-32bit:
runs-on: ubuntu-latest
env:
DEVNULLRIGHTS: 1
READFROMBLOCKDEVICE: 1
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: make test # note: `make -j test success` seems to require a clean state
run: |
sudo apt-get -qqq update
@ -53,51 +57,61 @@ jobs:
make clean
CFLAGS="-m32 -O2" make -j test V=1
# lasts ~7mn
test-largeDictionary:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: largeDictionary
run: |
CFLAGS="-Werror -O3" make -j -C tests test-largeDictionary
# lasts ~9mn
no-intrinsics-fuzztest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: no intrinsics fuzztest
run: MOREFLAGS="-DZSTD_NO_INTRINSICS" make -C tests fuzztest
# lasts ~8mn
tsan-zstreamtest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: thread sanitizer zstreamtest
run: CC=clang ZSTREAM_TESTTIME=-T3mn make tsan-test-zstream
uasan-zstreamtest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: ub + address sanitizer on zstreamtest
run: CC=clang make uasan-test-zstream
# lasts ~15mn
# lasts ~11mn
tsan-fuzztest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: thread sanitizer fuzztest
run: CC=clang make tsan-fuzztest
big-tests-zstreamtest32:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: zstream tests in 32bit mode, with big tests
run: |
sudo apt-get -qqq update
make libc6install
CC=clang make -C tests test-zstream32 FUZZER_FLAGS="--big-tests"
# lasts ~23mn
# lasts ~13mn
gcc-8-asan-ubsan-testzstd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: gcc-8 + ASan + UBSan + Test Zstd
# See https://askubuntu.com/a/1428822
run: |
@ -109,14 +123,14 @@ jobs:
clang-asan-ubsan-testzstd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: clang + ASan + UBSan + Test Zstd
run: CC=clang make -j uasan-test-zstd </dev/null V=1
gcc-asan-ubsan-testzstd-32bit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: ASan + UBSan + Test Zstd, 32bit mode
run: |
sudo apt-get -qqq update
@ -130,7 +144,7 @@ jobs:
gcc-8-asan-ubsan-fuzz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: gcc-8 + ASan + UBSan + Fuzz Test
# See https://askubuntu.com/a/1428822
run: |
@ -142,14 +156,14 @@ jobs:
clang-asan-ubsan-fuzz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: clang + ASan + UBSan + Fuzz Test
run: CC=clang FUZZER_FLAGS="--long-tests" make clean uasan-fuzztest
gcc-asan-ubsan-fuzz32:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: ASan + UBSan + Fuzz Test 32bit
run: |
sudo apt-get -qqq update
@ -159,7 +173,7 @@ jobs:
clang-asan-fuzz32:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: clang + ASan + Fuzz Test 32bit
run: |
sudo apt-get -qqq update
@ -174,7 +188,7 @@ jobs:
# clang-asan-ubsan-fuzz32:
# runs-on: ubuntu-20.04
# steps:
# - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
# - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
# - name: clang + ASan + UBSan + Fuzz Test 32bit
# run: |
# sudo apt-get -qqq update
@ -184,28 +198,28 @@ jobs:
asan-ubsan-regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: ASan + UBSan + Regression Test
run: make -j uasanregressiontest
clang-asan-ubsan-regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: clang + ASan + UBSan + Regression Test
run: CC=clang make -j uasanregressiontest
msan-regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: MSan + Regression Test
run: make -j msanregressiontest
clang-msan-fuzz-unoptimized:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: clang + MSan + Fuzz Test
run: |
sudo apt-get -qqq update
@ -215,28 +229,25 @@ jobs:
clang-msan-fuzz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: clang + MSan + Fuzz Test
run: |
sudo apt-get -qqq update
sudo apt-get install clang
CC=clang FUZZER_FLAGS="--long-tests" make clean msan-fuzztest
# lasts ~24mn
clang-msan-testzstd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: clang + MSan + Test Zstd
run: |
sudo apt-get update
sudo apt-get install clang
CC=clang make msan-test-zstd HAVE_ZLIB=0 HAVE_LZ4=0 HAVE_LZMA=0 V=1
CC=clang make -j msan-test-zstd HAVE_ZLIB=0 HAVE_LZ4=0 HAVE_LZMA=0 V=1
armfuzz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Qemu ARM emulation + Fuzz Test
run: |
sudo apt-get -qqq update
@ -246,7 +257,7 @@ jobs:
valgrind-fuzz-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: valgrind + fuzz test stack mode # ~ 7mn
shell: 'script -q -e -c "bash {0}"'
run: |
@ -262,8 +273,8 @@ jobs:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # tag=v2.26.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # tag=v2.32.0
with:
msystem: MINGW64
install: make
@ -306,7 +317,7 @@ jobs:
dry-run: false
sanitizer: ${{ matrix.sanitizer }}
- name: Upload Crash
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # tag=v4.3.1
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # tag=v7.0.1
if: failure() && steps.build.outcome == 'success'
with:
name: ${{ matrix.sanitizer }}-artifacts

View file

@ -16,39 +16,40 @@ jobs:
linux-kernel:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: linux kernel, library + build + test
run: make -C contrib/linux-kernel test CFLAGS="-Werror -Wunused-const-variable -Wunused-but-set-variable"
benchmarking:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: make benchmarking
run: make benchmarking
check-32bit: # designed to catch https://github.com/facebook/zstd/issues/2428
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: make check on 32-bit
run: |
sudo apt update
APT_PACKAGES="gcc-multilib" make apt-install
CFLAGS="-m32 -O1 -fstack-protector" make check V=1
CFLAGS="-m32 -O1 -fstack-protector" make V=1 -C tests test-cli-tests
build-c89:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- name: ensure zstd can be build with c89/c90 compilers (+ long long support + variadic macros)
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: ensure zstd can be built with c89/c90 compilers (+ long long support + variadic macros)
run: |
make c89build V=1
build-zstd-dll:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: build zstd bin against a dynamic lib (debuglevel for more dependencies)
run: |
make -C lib lib-mt-release
@ -57,7 +58,7 @@ jobs:
gcc-7-libzstd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: gcc-7 + libzstdmt compilation
# See https://askubuntu.com/a/1428822
run: |
@ -71,44 +72,10 @@ jobs:
# candidate test (for discussion) : underlink test
# LDFLAGS=-Wl,--no-undefined : will make the linker fail if dll is underlinked
cmake-build-and-test-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- name: cmake build and test
run: |
sudo apt install liblzma-dev
FUZZERTEST=-T1mn ZSTREAM_TESTTIME=-T1mn make cmakebuild V=1
cmake-source-directory-with-spaces:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
generator: "Unix Makefiles"
- os: windows-latest
generator: "NMake Makefiles"
- os: macos-latest
generator: "Unix Makefiles"
env:
SRC_DIR: "source directory with spaces"
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
with:
path: "${{ env.SRC_DIR }}"
- uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
if: ${{ matrix.generator == 'NMake Makefiles' }}
- name: cmake build on a source directory with spaces
run: |
cmake -S "${{ env.SRC_DIR }}/build/cmake" -B build -DBUILD_TESTING=ON -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=Release --install-prefix "${{ runner.temp }}/install"
cmake --build build --config Release
cmake --install build --config Release
cpp-gnu90-c99-compatibility:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: C++, gnu90 and c99 compatibility
run: |
make cxxtest
@ -122,7 +89,7 @@ jobs:
mingw-cross-compilation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: mingw cross-compilation
run: |
# sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix; (doesn't work)
@ -133,7 +100,7 @@ jobs:
armbuild:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: ARM Build Test
run: |
sudo apt-get -qqq update
@ -143,7 +110,7 @@ jobs:
bourne-shell:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Bourne shell compatibility (shellcheck)
run: |
wget https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.x86_64.tar.xz
@ -153,7 +120,7 @@ jobs:
zlib-wrapper:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: install valgrind
run: |
sudo apt-get -qqq update
@ -166,10 +133,9 @@ jobs:
lz4-threadpool-libs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: LZ4, thread pool, and libs build testslib wrapper test
run: |
make lz4install
make -C tests test-lz4
make check < /dev/null | tee # mess with lz4 console detection
make clean
@ -180,7 +146,7 @@ jobs:
gcc-make-all-avx2:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Make all, with AVX2
run: |
sudo apt-get -qqq update
@ -190,7 +156,7 @@ jobs:
gcc-make-all-32bit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Make all, 32bit mode
run: |
sudo apt-get -qqq update
@ -200,7 +166,7 @@ jobs:
gcc-make-all-32bit-avx2:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Make all, 32bit + AVX2 mode
run: |
sudo apt-get -qqq update
@ -211,7 +177,7 @@ jobs:
gcc-8-make:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: gcc-8 build
# See https://askubuntu.com/a/1428822
run: |
@ -234,7 +200,7 @@ jobs:
flags: "HAVE_ZLIB=0 HAVE_LZ4=0 HAVE_LZMA=1"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Build with ${{matrix.name}}
run: |
sudo apt install liblzma-dev
@ -244,7 +210,7 @@ jobs:
implicit-fall-through:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: -Wimplicit-fallthrough build
run: |
make clean
@ -255,7 +221,7 @@ jobs:
meson-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Install packages
run: |
sudo apt-get update
@ -279,7 +245,7 @@ jobs:
meson-mingw-cross-compilation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Install packages
run: |
sudo apt-get -qqq update
@ -323,7 +289,7 @@ jobs:
meson-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Install packages
run: pip install --pre meson
- name: Configure with Meson
@ -339,34 +305,6 @@ jobs:
run: |
meson install -C builddir --destdir staging/
cmake-visual-2022:
strategy:
matrix:
include:
- generator: "Visual Studio 17 2022"
flags: "-A x64"
- generator: "Visual Studio 17 2022"
flags: "-A Win32"
- generator: "MinGW Makefiles"
- generator: "Visual Studio 17 2022"
flags: "-T ClangCL"
- generator: "Visual Studio 17 2022"
flags: "-T ClangCL -A x64 -DCMAKE_C_FLAGS=/arch:AVX2"
runs-on: windows-2022
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # tag=v2.0.0
- name: Build & Test
working-directory: ${{env.GITHUB_WORKSPACE}}
run: |
cd build\cmake
mkdir build
cd build
cmake.exe -G "${{matrix.generator}}" ${{matrix.flags}} -DCMAKE_BUILD_TYPE=Debug -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_ZSTREAM_FLAGS=-T30s -DZSTD_FUZZER_FLAGS=-T30s -DZSTD_FULLBENCH_FLAGS=-i0 ..
cmake.exe --build .
ctest.exe -V -C Debug
msbuild-visual-studio:
strategy:
fail-fast: false # 'false' means Don't stop matrix workflows even if some matrix failed.
@ -376,15 +314,14 @@ jobs:
{ name: "VS 2022 Win32 Debug", platform: Win32, configuration: Debug, toolset: v143, runner: "windows-2022", arch: "" },
{ name: "VS 2022 x64 Release", platform: x64, configuration: Release, toolset: v143, runner: "windows-2022", arch: ""},
{ name: "VS 2022 Win32 Release", platform: Win32, configuration: Release, toolset: v143, runner: "windows-2022", arch: ""},
{ name: "VS 2019 x64 Release", platform: Win32, configuration: Release, toolset: v142, runner: "windows-2019", arch: ""},
{ name: "VS 2019 Win32 Release", platform: x64, configuration: Release, toolset: v142, runner: "windows-2019", arch: ""},
{ name: "VS 2025 x64 Debug", platform: x64, configuration: Debug, toolset: v143, runner: "windows-2025", arch: ""},
{ name: "VS 2022 x64 Release AVX2", platform: x64, configuration: Release, toolset: v143, runner: "windows-2022", arch: "AdvancedVectorExtensions2" },
]
runs-on: ${{matrix.runner}}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # tag=v2.0.0
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # tag=v3.0.0
- name: Build ${{matrix.name}}
working-directory: ${{env.GITHUB_WORKSPACE}}
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
@ -407,7 +344,7 @@ jobs:
libzstd-size:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: libzstd size test
run: |
make clean && make -j -C lib libzstd && ./tests/check_size.py lib/libzstd.so 1100000
@ -418,7 +355,7 @@ jobs:
minimal-decompressor-macros:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: minimal decompressor macros
run: |
make clean && make -j all ZSTD_LIB_MINIFY=1 MOREFLAGS="-Werror"
@ -435,7 +372,7 @@ jobs:
dynamic-bmi2:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: dynamic bmi2 tests
run: |
make clean && make -j check MOREFLAGS="-O0 -Werror -mbmi2"
@ -447,7 +384,7 @@ jobs:
test-variants:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: make all variants & validate
run: |
make -j -C programs allVariants MOREFLAGS=-O0
@ -466,7 +403,7 @@ jobs:
{ name: PPC64LE, xcc_pkg: gcc-powerpc64le-linux-gnu, xcc: powerpc64le-linux-gnu-gcc, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64le-static },
{ name: S390X, xcc_pkg: gcc-s390x-linux-gnu, xcc: s390x-linux-gnu-gcc, xemu_pkg: qemu-system-s390x, xemu: qemu-s390x-static },
{ name: MIPS, xcc_pkg: gcc-mips-linux-gnu, xcc: mips-linux-gnu-gcc, xemu_pkg: qemu-system-mips, xemu: qemu-mips-static },
{ name: RISC-V, xcc_pkg: gcc-riscv64-linux-gnu, xcc: riscv64-linux-gnu-gcc, xemu_pkg: qemu-system-riscv64,xemu: qemu-riscv64-static },
{ name: RISC-V, xcc_pkg: gcc-14-riscv64-linux-gnu, xcc: riscv64-linux-gnu-gcc-14, xemu_pkg: qemu-system-riscv64,xemu: qemu-riscv64-static },
{ name: M68K, xcc_pkg: gcc-m68k-linux-gnu, xcc: m68k-linux-gnu-gcc, xemu_pkg: qemu-system-m68k, xemu: qemu-m68k-static },
{ name: SPARC, xcc_pkg: gcc-sparc64-linux-gnu, xcc: sparc64-linux-gnu-gcc, xemu_pkg: qemu-system-sparc, xemu: qemu-sparc64-static },
]
@ -474,7 +411,7 @@ jobs:
XCC: ${{ matrix.xcc }}
XEMU: ${{ matrix.xemu }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: apt update & install
run: |
sudo apt-get update
@ -496,6 +433,9 @@ jobs:
run: |
make clean
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j check
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j -C tests test-cli-tests
CFLAGS="-O3 -march=armv8.2-a+sve2" LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j check
CFLAGS="-O3 -march=armv8.2-a+sve2" LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j -C tests test-cli-tests
# This test is only compatible with standard libraries that support BTI (Branch Target Identification).
# Unfortunately, the standard library provided on Ubuntu 24.04 does not have this feature enabled.
# make clean
@ -520,6 +460,9 @@ jobs:
if: ${{ matrix.name == 'RISC-V' }}
run: |
LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check
CFLAGS="-march=rv64gcv -O3" LDFLAGS="-static -DMEM_FORCE_MEMORY_ACCESS=0" CC=$XCC QEMU_SYS="$XEMU -cpu rv64,v=true,vlen=128" make clean check
CFLAGS="-march=rv64gcv -O3" LDFLAGS="-static -DMEM_FORCE_MEMORY_ACCESS=0" CC=$XCC QEMU_SYS="$XEMU -cpu rv64,v=true,vlen=256" make clean check
CFLAGS="-march=rv64gcv -O3" LDFLAGS="-static -DMEM_FORCE_MEMORY_ACCESS=0" CC=$XCC QEMU_SYS="$XEMU -cpu rv64,v=true,vlen=512" make clean check
- name: M68K
if: ${{ matrix.name == 'M68K' }}
run: |
@ -543,8 +486,8 @@ jobs:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # tag=v2.26.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # tag=v2.32.0
with:
msystem: ${{ matrix.msystem }}
install: make diffutils
@ -579,9 +522,9 @@ jobs:
platform: [x64, Win32]
configuration: [Release]
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # tag=v2.0.0
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # tag=v3.0.0
- name: Build and run tests
working-directory: ${{env.GITHUB_WORKSPACE}}
env:
@ -600,8 +543,8 @@ jobs:
runs-on: windows-latest
steps:
- run: git config --global core.autocrlf input
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: cygwin/cygwin-install-action@f61179d72284ceddc397ed07ddb444d82bf9e559 # tag=v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- uses: cygwin/cygwin-install-action@3f0a3f9f988f7e96b8c18098ae05eaec175f5b52 # tag=v6
with:
platform: x86_64
packages: >-
@ -632,7 +575,7 @@ jobs:
container:
image: debian:testing
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Install dependencies
run: |
apt -y update
@ -647,7 +590,7 @@ jobs:
versions-compatibility:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Versions Compatibility Test
run: |
make -C tests versionsTest
@ -655,7 +598,7 @@ jobs:
clangbuild:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: make clangbuild
run: |
make clangbuild
@ -663,7 +606,7 @@ jobs:
gcc-pgo:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Build PGO Zstd with GCC
env:
CC: gcc
@ -674,7 +617,7 @@ jobs:
clang-pgo:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Build PGO Zstd with Clang
env:
CC: clang
@ -684,10 +627,21 @@ jobs:
make -C programs zstd-pgo
./programs/zstd -b
musl-build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Install musl-tools
run: |
sudo apt install -y musl-tools
- name: Compile with musl-gcc and test-zstd
run: |
CC=musl-gcc CFLAGS="-Werror -O3" CPPFLAGS=-DZDICT_QSORT=ZDICT_QSORT_C90 make -j -C tests test-zstd V=1
intel-cet-compatibility:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Build Zstd
run: |
make -j zstd V=1
@ -718,8 +672,9 @@ jobs:
echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
sudo apt-get update
sudo apt-get install -y intel-basekit intel-hpckit
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: make check
run: |
source /opt/intel/oneapi/setvars.sh
make CC=icx check
make CC=icx -C tests test-cli-tests

View file

@ -12,7 +12,7 @@ jobs:
regression-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6.0.2
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev
- name: Regression Test

View file

@ -17,7 +17,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
- name: Archive
env:

64
.github/workflows/release_check.yml vendored Normal file
View file

@ -0,0 +1,64 @@
name: release_checks
on:
push:
branches:
- release
pull_request:
branches:
- release
permissions: read-all
jobs:
verify-manual:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v6.0.2
- name: Save current manual
run: mv doc/zstd_manual.html doc/zstd_manual_saved.html
- name: Generate new manual
run: make manual
- name: Compare manuals
run: |
if ! cmp -s doc/zstd_manual.html doc/zstd_manual_saved.html; then
echo "The API manual was not updated before release !"
exit 1
fi
verify-man-pages:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v6.0.2
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y ruby ruby-dev
sudo gem install ronn
- name: Display ronn version
run: ronn --version
- name: Save current man pages
run: |
mv programs/zstd.1 programs/zstd.1.saved
mv programs/zstdgrep.1 programs/zstdgrep.1.saved
mv programs/zstdless.1 programs/zstdless.1.saved
- name: Generate new manual pages
run: make -C programs man
- name: Compare man pages
run: |
for file in zstd.1 zstdgrep.1 zstdless.1; do
if ! cmp -s programs/$file programs/$file.saved; then
echo "The man page $file should have been updated."
exit 1
fi
done

View file

@ -27,12 +27,12 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # tag=v2.4.0
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # tag=v2.4.1
with:
results_file: results.sarif
results_format: sarif
@ -51,7 +51,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # tag=v4.3.1
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # tag=v7.0.1
with:
name: SARIF file
path: results.sarif
@ -59,6 +59,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # tag=v3.28.9
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # tag=v4.36.2
with:
sarif_file: results.sarif

View file

@ -2,7 +2,7 @@ name: windows-artifacts
on:
push:
branches: [ test_artifacts, win_artifacts ]
branches: [ test_artifacts, win_artifacts, release ]
release:
types:
- published
@ -11,48 +11,109 @@ permissions: read-all
jobs:
windows-artifacts:
# see https://ariya.io/2020/07/on-github-actions-with-msys2
runs-on: windows-latest
# see https://github.com/msys2/setup-msys2
permissions:
contents: write # to fetch code and upload artifacts
# For msys2, see https://ariya.io/2020/07/on-github-actions-with-msys2
runs-on: ${{ matrix.shell == 'cmake' && 'windows-11-arm' || 'windows-latest' }}
strategy:
# For msys2, see https://github.com/msys2/setup-msys2
matrix:
include:
- { msystem: mingw64, env: x86_64, ziparch: win64 }
- { msystem: mingw32, env: i686, ziparch: win32 }
- { msystem: mingw64, env: x86_64, ziparch: win64, shell: msys2 }
- { msystem: mingw32, env: i686, ziparch: win32, shell: msys2 }
- { msystem: null, env: arm64, ziparch: win-arm64, shell: cmake }
defaults:
run:
shell: msys2 {0}
shell: ${{ matrix.shell == 'cmake' && 'pwsh' || 'msys2 {0}' }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3
- uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # tag=v2.26.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2
# MSYS2 setup
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # tag=v2.32.0
if: matrix.shell == 'msys2'
with:
msystem: ${{ matrix.msystem }}
install: make zlib git p7zip mingw-w64-${{matrix.env}}-gcc
install: make p7zip git mingw-w64-${{matrix.env}}-gcc
update: true
- name: display versions
- name: display versions (MSYS2)
if: matrix.shell == 'msys2'
run: |
make -v
cc -v
- name: Building zlib to static link
- name: display versions (CMake)
if: matrix.shell == 'cmake'
run: |
git clone --depth 1 --branch v1.2.11 https://github.com/madler/zlib
cmake --version
# Build dependencies (MSYS2 only)
- name: Building zlib to static link
if: matrix.shell == 'msys2'
run: |
git clone --depth 1 --branch v1.3.1 https://github.com/madler/zlib
make -C zlib -f win32/Makefile.gcc libz.a
- name: Building lz4 to static link
if: matrix.shell == 'msys2'
run: |
git clone --depth 1 --branch v1.10.0 https://github.com/lz4/lz4
# ensure both libraries use the same version of libxxhash
cp lib/common/xxhash.* lz4/lib
CPPFLAGS=-DXXH_NAMESPACE=LZ4_ make -C lz4/lib liblz4.a V=1
# Build zstd
- name: Building zstd programs
if: matrix.shell == 'msys2'
run: |
CPPFLAGS=-I../zlib LDFLAGS=../zlib/libz.a make -j allzstd MOREFLAGS=-static V=1
CPPFLAGS="-I../zlib -I../lz4/lib" LDFLAGS=-static make -j allzstd V=1 HAVE_ZLIB=1 HAVE_LZ4=1 HAVE_LZMA=0 LDLIBS="../zlib/libz.a ../lz4/lib/liblz4.a"
- name: Create artifacts
- name: Build zstd (CMake ARM64)
if: matrix.shell == 'cmake'
run: |
./lib/dll/example/build_package.bat
cd build\cmake
mkdir build
cd build
cmake.exe -G "Visual Studio 17 2022" -A ARM64 -DCMAKE_BUILD_TYPE=Release -DZSTD_BUILD_PROGRAMS=ON -DZSTD_BUILD_SHARED=ON -DZSTD_BUILD_STATIC=ON ..
cmake.exe --build . --config Release --parallel
- name: Create artifacts (MSYS2)
if: matrix.shell == 'msys2'
run: |
./lib/dll/example/build_package.bat || exit 1
mv bin/ zstd-${{ github.ref_name }}-${{matrix.ziparch}}/
7z a -tzip -mx9 zstd-${{ github.ref_name }}-${{matrix.ziparch}}.zip zstd-${{ github.ref_name }}-${{matrix.ziparch}}/
cd ..
- name: Publish zstd-$VERSION-${{matrix.ziparch}}.zip
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # tag=v4.3.1
- name: Create artifacts (CMake)
if: matrix.shell == 'cmake'
run: |
.\lib\dll\example\build_package.bat
if ($LASTEXITCODE -ne 0) { exit 1 }
mv bin/ zstd-${{ github.ref_name }}-${{matrix.ziparch}}/
- name: Publish zstd-$VERSION-${{matrix.ziparch}}.zip for manual inspection
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # tag=v7.0.1
with:
path: ${{ github.workspace }}/zstd-${{ github.ref_name }}-${{matrix.ziparch}}.zip
name: zstd-${{ github.ref_name }}-${{matrix.ziparch}}.zip
compression-level: 9 # maximum compression
if-no-files-found: error # defaults to `warn`
path: ${{ github.workspace }}/zstd-${{ github.ref_name }}-${{matrix.ziparch}}/
name: zstd-${{ github.ref_name }}-${{matrix.ziparch}}
- name: Package artifact for upload (MSYS2)
if: matrix.shell == 'msys2'
run: |
7z a -tzip -mx9 "$(cygpath -u '${{ github.workspace }}/zstd-${{ github.ref_name }}-${{ matrix.ziparch }}.zip')" "$(cygpath -u '${{ github.workspace }}/zstd-${{ github.ref_name }}-${{ matrix.ziparch }}')"
- name: Package artifact for upload (CMake)
if: matrix.shell == 'cmake'
run: |
Compress-Archive -Path "zstd-${{ github.ref_name }}-${{ matrix.ziparch }}" -DestinationPath "zstd-${{ github.ref_name }}-${{ matrix.ziparch }}.zip" -CompressionLevel Optimal
- name: Upload release asset
if: github.event_name == 'release'
shell: pwsh
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ github.ref_name }}" "$env:GITHUB_WORKSPACE/zstd-${{ github.ref_name }}-${{ matrix.ziparch }}.zip" --clobber

21
.gitignore vendored
View file

@ -22,16 +22,6 @@ zstdmt
*.out
*.app
# Test artefacts
tmp*
*.zst
*.zstd
dictionary.
dictionary
NUL
cmakebuild/
install/
# Build artefacts
contrib/linux-kernel/linux/
projects/
@ -40,6 +30,17 @@ bin/
buck-out/
build-*
*.gcda
cmakebuild/
cmake-build/
# Test artefacts
tmp*
*.zst
*.zstd
dictionary.
dictionary
NUL
install/
# IDE
.clang_complete

View file

@ -1,3 +1,7 @@
v1.6.0 (Dec 2025)
api: legacy format support is now disabled by default
build: `ZSTD_LEGACY_SUPPORT` defaults to `0` in Makefile and CMake
V1.5.7 (Feb 2025)
fix: compression bug in 32-bit mode associated with long-lasting sessions
api: new method `ZSTD_compressSequencesAndLiterals()` (#4217, #4232)

11
CMakeLists.txt Normal file
View file

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.10)
# Thin wrapper so `cmake -S .` behaves like `cmake -S build/cmake`.
# Policy lives in build/cmake; keep parent project language-less.
project(zstd-superbuild LANGUAGES NONE)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-source builds are not supported. Specify -B <build-dir>.")
endif()
add_subdirectory(build/cmake)

View file

@ -373,7 +373,12 @@ counter `L1-dcache-load-misses`
#### Visual Studio
TODO
Build Zstd with symbols first (for example `cmake -B build -S build/cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo && ninja -C build zstd`) so the profiler resolves call stacks.
* Launch Visual Studios Performance Profiler (`Alt+F2`), enable CPU Usage (optionally Instrumentation), and point it at the `programs/zstd` benchmark you want to run.
* If you prefer to start the benchmark from a terminal, use “Attach to running process” to latch onto it mid-run; keep frame pointers (`-fno-omit-frame-pointer`) for clean stacks.
* When you stop the capture, review the call tree, hot path, and annotated source panes
* Microsofts [Performance Profiling docs](https://learn.microsoft.com/en-us/visualstudio/profiling/?view=vs-2022) cover deeper sampling, ETW, and collection options if required.
## Issues
We use GitHub issues to track public bugs. Please ensure your description is

View file

@ -144,10 +144,13 @@ clean:
$(Q)$(RM) -r lz4 cmakebuild mesonbuild install
@echo Cleaning completed
LIBZSTD_MK_DIR = $(ZSTDDIR)
include $(LIBZSTD_MK_DIR)/install_oses.mk # UNAME, INSTALL_OS_LIST
#------------------------------------------------------------------------------
# make install is validated only for Linux, macOS, Hurd and some BSD targets
#------------------------------------------------------------------------------
ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD DragonFly NetBSD MSYS_NT% CYGWIN_NT% Haiku AIX,$(shell sh -c 'MSYSTEM="MSYS" uname') ))
ifneq (,$(filter $(INSTALL_OS_LIST),$(UNAME)))
HOST_OS = POSIX
@ -351,7 +354,7 @@ apt-add-repo:
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update -y -qq
.PHONY: ppcinstall arminstall valgrindinstall libc6install gcc6install gcc7install gcc8install gpp6install clang38install lz4install
.PHONY: ppcinstall arminstall valgrindinstall libc6install gcc6install gcc7install gcc8install gpp6install clang38install
ppcinstall:
APT_PACKAGES="qemu-system-ppc qemu-user-static gcc-powerpc-linux-gnu" $(MAKE) apt-install
@ -379,10 +382,6 @@ gpp6install: apt-add-repo
clang38install:
APT_PACKAGES="clang-3.8" $(MAKE) apt-install
# Ubuntu 14.04 ships a too-old lz4
lz4install:
[ -e lz4 ] || git clone https://github.com/lz4/lz4 && sudo $(MAKE) -C lz4 install
endif

View file

@ -30,9 +30,9 @@ a list of known ports and bindings is provided on [Zstandard homepage](https://f
For reference, several fast compression algorithms were tested and compared
on a desktop featuring a Core i7-9700K CPU @ 4.9GHz
and running Ubuntu 20.04 (`Linux ubu20 5.15.0-101-generic`),
and running Ubuntu 24.04 (`Linux 6.8.0-53-generic`),
using [lzbench], an open-source in-memory benchmark by @inikep
compiled with [gcc] 9.4.0,
compiled with [gcc] 14.2.0,
on the [Silesia compression corpus].
[lzbench]: https://github.com/inikep/lzbench
@ -41,16 +41,16 @@ on the [Silesia compression corpus].
| Compressor name | Ratio | Compression| Decompress.|
| --------------- | ------| -----------| ---------- |
| **zstd 1.5.6 -1** | 2.887 | 510 MB/s | 1580 MB/s |
| [zlib] 1.2.11 -1 | 2.743 | 95 MB/s | 400 MB/s |
| brotli 1.0.9 -0 | 2.702 | 395 MB/s | 430 MB/s |
| **zstd 1.5.6 --fast=1** | 2.437 | 545 MB/s | 1890 MB/s |
| **zstd 1.5.6 --fast=3** | 2.239 | 650 MB/s | 2000 MB/s |
| quicklz 1.5.0 -1 | 2.238 | 525 MB/s | 750 MB/s |
| lzo1x 2.10 -1 | 2.106 | 650 MB/s | 825 MB/s |
| [lz4] 1.9.4 | 2.101 | 700 MB/s | 4000 MB/s |
| lzf 3.6 -1 | 2.077 | 420 MB/s | 830 MB/s |
| snappy 1.1.9 | 2.073 | 530 MB/s | 1660 MB/s |
| **zstd 1.5.7 -1** | 2.896 | 510 MB/s | 1550 MB/s |
| brotli 1.1.0 -1 | 2.883 | 290 MB/s | 425 MB/s |
| [zlib] 1.3.1 -1 | 2.743 | 105 MB/s | 390 MB/s |
| **zstd 1.5.7 --fast=1** | 2.439 | 545 MB/s | 1850 MB/s |
| quicklz 1.5.0 -1 | 2.238 | 520 MB/s | 750 MB/s |
| **zstd 1.5.7 --fast=4** | 2.146 | 665 MB/s | 2050 MB/s |
| lzo1x 2.10 -1 | 2.106 | 650 MB/s | 780 MB/s |
| [lz4] 1.10.0 | 2.101 | 675 MB/s | 3850 MB/s |
| snappy 1.2.1 | 2.089 | 520 MB/s | 1500 MB/s |
| lzf 3.6 -1 | 2.077 | 410 MB/s | 820 MB/s |
[zlib]: https://www.zlib.net/
[lz4]: https://lz4.github.io/lz4/
@ -120,33 +120,40 @@ Dictionary gains are mostly effective in the first few KB. Then, the compression
## Build instructions
`make` is the officially maintained build system of this project.
All other build systems are "compatible" and 3rd-party maintained,
they may feature small differences in advanced options.
When your system allows it, prefer using `make` to build `zstd` and `libzstd`.
`make` is the main build system of this project.
It is the reference, and other build systems are periodically updated to stay compatible.
However, small drifts and feature differences can be present, since perfect synchronization is difficult.
For this reason, when your build system allows it, prefer employing `make`.
### Makefile
If your system is compatible with standard `make` (or `gmake`),
invoking `make` in root directory will generate `zstd` cli in root directory.
It will also create `libzstd` into `lib/`.
Assuming your system supports standard `make` (or `gmake`),
just invoking `make` in root directory generates `zstd` cli at root,
and also generates `libzstd` into `lib/`.
Other available options include:
- `make install` : create and install zstd cli, library and man pages
- `make check` : create and run `zstd`, test its behavior on local platform
Other standard targets include:
- `make install` : install zstd cli, library and man pages
- `make check` : run `zstd`, test its essential behavior on local platform
The `Makefile` follows the [GNU Standard Makefile conventions](https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html),
allowing staged install, standard flags, directory variables and command variables.
allowing staged install, standard compilation flags, directory variables and command variables.
For advanced use cases, specialized compilation flags which control binary generation
are documented in [`lib/README.md`](lib/README.md#modular-build) for the `libzstd` library
For advanced use cases, specialized flags which control binary generation and installation paths are documented
in [`lib/README.md`](lib/README.md#modular-build) for the `libzstd` library
and in [`programs/README.md`](programs/README.md#compilation-variables) for the `zstd` CLI.
### cmake
A `cmake` project generator is provided within `build/cmake`.
It can generate Makefiles or other build scripts
to create `zstd` binary, and `libzstd` dynamic and static libraries.
A `cmake` project generator is available for generating Makefiles or other build scripts
to create the `zstd` binary as well as `libzstd` dynamic and static libraries.
The repository root now contains a minimal `CMakeLists.txt` that forwards to `build/cmake`,
so you can configure the project with a standard `cmake -S .` invocation,
while the historical `cmake -S build/cmake` entry point remains fully supported.
```bash
cmake -S . -B build-cmake
cmake --build build-cmake
```
By default, `CMAKE_BUILD_TYPE` is set to `Release`.
@ -156,7 +163,7 @@ By default, `CMAKE_BUILD_TYPE` is set to `Release`.
To perform a Fat/Universal2 build and install use the following commands:
```bash
cmake -B build-cmake-debug -S build/cmake -G Ninja -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h;arm64"
cmake -S . -B build-cmake-debug -G Ninja -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h;arm64"
cd build-cmake-debug
ninja
sudo ninja install
@ -198,10 +205,11 @@ If the version is out of date, please [create an issue or pull request](https://
### Visual Studio (Windows)
Going into `build` directory, you will find additional possibilities:
- Projects for Visual Studio 2005, 2008 and 2010.
- Projects for Visual Studio 2008 and 2010.
+ VS2010 project is compatible with VS2012, VS2013, VS2015 and VS2017.
- Automated build scripts for Visual compiler by [@KrzysFR](https://github.com/KrzysFR), in `build/VS_scripts`,
which will build `zstd` cli and `libzstd` library without any need to open Visual Studio solution.
- It is now recommended to generate Visual Studio solutions from `cmake`
### Buck
@ -210,7 +218,7 @@ The output binary will be in `buck-out/gen/programs/`.
### Bazel
You easily can integrate zstd into your Bazel project by using the module hosted on the [Bazel Central Repository](https://registry.bazel.build/modules/zstd).
You can integrate zstd into your Bazel project by using the module hosted on the [Bazel Central Repository](https://registry.bazel.build/modules/zstd).
## Testing
@ -221,9 +229,9 @@ For information on CI testing, please refer to `TESTING.md`.
## Status
Zstandard is currently deployed within Facebook and many other large cloud infrastructures.
It is run continuously to compress large amounts of data in multiple formats and use cases.
Zstandard is considered safe for production environments.
Zstandard is deployed within Meta and many other large cloud infrastructures,
to compress humongous amounts of data in various formats and use cases.
It is also continuously fuzzed for security issues by Google's [oss-fuzz](https://github.com/google/oss-fuzz/tree/master/projects/zstd) program.
## License
@ -232,6 +240,5 @@ Zstandard is dual-licensed under [BSD](LICENSE) OR [GPLv2](COPYING).
## Contributing
The `dev` branch is the one where all contributions are merged before reaching `release`.
If you plan to propose a patch, please commit into the `dev` branch, or its own feature branch.
Direct commit to `release` are not permitted.
For more information, please read [CONTRIBUTING](CONTRIBUTING.md).

View file

@ -45,7 +45,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE"
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@ -122,7 +122,7 @@
EnableIntrinsicFunctions="true"
OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE"
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
@ -197,7 +197,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE"
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@ -275,7 +275,7 @@
EnableIntrinsicFunctions="true"
OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\compress"
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE"
PreprocessorDefinitions="ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"

View file

@ -45,7 +45,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\dictBuilder"
PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE"
PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@ -121,7 +121,7 @@
EnableIntrinsicFunctions="true"
OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\dictBuilder"
PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE"
PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
@ -195,7 +195,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\dictBuilder"
PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE"
PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@ -272,7 +272,7 @@
EnableIntrinsicFunctions="true"
OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\dictBuilder"
PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE"
PreprocessorDefinitions="ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"

View file

@ -169,7 +169,7 @@
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
@ -188,7 +188,7 @@
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@ -208,7 +208,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<EnablePREfast>false</EnablePREfast>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@ -229,7 +229,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>false</TreatWarningAsError>
<EnablePREfast>false</EnablePREfast>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>

View file

@ -162,7 +162,7 @@
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
@ -181,7 +181,7 @@
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@ -201,7 +201,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<EnablePREfast>false</EnablePREfast>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@ -222,7 +222,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>false</TreatWarningAsError>
<EnablePREfast>false</EnablePREfast>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>

View file

@ -187,7 +187,7 @@
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError>
<EnablePREfast>false</EnablePREfast>
<EnableEnhancedInstructionSet>$(InstructionSet)</EnableEnhancedInstructionSet>
@ -204,7 +204,7 @@
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError>
<EnablePREfast>false</EnablePREfast>
<EnableEnhancedInstructionSet>$(InstructionSet)</EnableEnhancedInstructionSet>
@ -223,7 +223,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<EnablePREfast>false</EnablePREfast>
<TreatWarningAsError>false</TreatWarningAsError>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@ -245,7 +245,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=0;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>false</TreatWarningAsError>
<EnablePREfast>false</EnablePREfast>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>

View file

@ -9,220 +9,73 @@
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
# As of 2018-12-26 ZSTD has been validated to build with cmake version 3.13.2 new policies.
# Set and use the newest cmake policies that are validated to work
set(ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION "3")
set(ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION "13") #Policies never changed at PATCH level
if("${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}" EQUAL "${CMAKE_MAJOR_VERSION}" AND
"${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}" GREATER "${CMAKE_MINOR_VERSION}")
set(ZSTD_CMAKE_POLICY_VERSION "${CMAKE_VERSION}")
else()
set(ZSTD_CMAKE_POLICY_VERSION "${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}.${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}.0")
endif()
cmake_policy(VERSION ${ZSTD_CMAKE_POLICY_VERSION})
set(CMAKE_BUILD_WITH_INSTALL_RPATH on)
#-----------------------------------------------------------------------------
# Setup CMake environment
#-----------------------------------------------------------------------------
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
# Define project paths
set(ZSTD_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..")
set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib)
# Parse version
include(GetZstdLibraryVersion)
GetZstdLibraryVersion(${LIBRARY_DIR}/zstd.h zstd_VERSION_MAJOR zstd_VERSION_MINOR zstd_VERSION_PATCH)
set(ZSTD_SHORT_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}")
set(ZSTD_FULL_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}")
#-----------------------------------------------------------------------------
# Configure CMake policies and version
#-----------------------------------------------------------------------------
include(ZstdVersion)
#-----------------------------------------------------------------------------
# Project declaration
#-----------------------------------------------------------------------------
project(zstd
VERSION "${ZSTD_FULL_VERSION}"
LANGUAGES C # Main library is in C
ASM # And ASM
CXX # Testing contributed code also utilizes CXX
LANGUAGES C # Main library is in C and ASM, ASM is enabled conditionally
HOMEPAGE_URL "${zstd_HOMEPAGE_URL}"
DESCRIPTION "${zstd_DESCRIPTION}"
)
message(STATUS "ZSTD VERSION: ${zstd_VERSION}")
set(zstd_HOMEPAGE_URL "https://facebook.github.io/zstd")
set(zstd_DESCRIPTION "Zstandard is a real-time compression algorithm, providing high compression ratios.")
# Set a default build type if none was specified
#-----------------------------------------------------------------------------
# Build type configuration
#-----------------------------------------------------------------------------
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
#-----------------------------------------------------------------------------
# Include standard modules
#-----------------------------------------------------------------------------
include(GNUInstallDirs)
#-----------------------------------------------------------------------------
# Add extra compilation flags
#-----------------------------------------------------------------------------
include(AddZstdCompilationFlags)
ADD_ZSTD_COMPILATION_FLAGS()
# Always hide XXHash symbols
add_definitions(-DXXH_NAMESPACE=ZSTD_)
#-----------------------------------------------------------------------------
# Installation variables
# Display installation information
#-----------------------------------------------------------------------------
message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}")
#-----------------------------------------------------------------------------
# Options
# Configure build options
#-----------------------------------------------------------------------------
# Legacy support
option(ZSTD_LEGACY_SUPPORT "LEGACY SUPPORT" ON)
if (ZSTD_LEGACY_SUPPORT)
message(STATUS "ZSTD_LEGACY_SUPPORT defined!")
set(ZSTD_LEGACY_LEVEL 5 CACHE STRING "")
add_definitions(-DZSTD_LEGACY_SUPPORT=${ZSTD_LEGACY_LEVEL})
else ()
message(STATUS "ZSTD_LEGACY_SUPPORT not defined!")
add_definitions(-DZSTD_LEGACY_SUPPORT=0)
endif ()
if (APPLE)
option(ZSTD_FRAMEWORK "Build as Apple Frameworks" OFF)
endif ()
if (ANDROID)
set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT OFF)
# Old versions of bionic libc don't have fseeko/ftello
if ((NOT ${ANDROID_PLATFORM_LEVEL}) OR ${ANDROID_PLATFORM_LEVEL} VERSION_LESS 24)
message(STATUS "Setting compile definitions for old Android API")
add_compile_definitions(LIBC_NO_FSEEKO)
endif ()
else()
set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT ON)
endif()
# Multi-threading support
option(ZSTD_MULTITHREAD_SUPPORT "MULTITHREADING SUPPORT" ${ZSTD_MULTITHREAD_SUPPORT_DEFAULT})
if (ZSTD_MULTITHREAD_SUPPORT)
message(STATUS "ZSTD_MULTITHREAD_SUPPORT is enabled")
else ()
message(STATUS "ZSTD_MULTITHREAD_SUPPORT is disabled")
endif ()
option(ZSTD_BUILD_PROGRAMS "BUILD PROGRAMS" ON)
option(ZSTD_BUILD_CONTRIB "BUILD CONTRIB" OFF)
# Respect the conventional CMake option for enabling tests if it was specified on the first configure
if (BUILD_TESTING)
set(ZSTD_BUILD_TESTS_default ON)
else()
set(ZSTD_BUILD_TESTS_default OFF)
endif()
option(ZSTD_BUILD_TESTS "BUILD TESTS" ${ZSTD_BUILD_TESTS_default})
if (MSVC)
option(ZSTD_USE_STATIC_RUNTIME "LINK TO STATIC RUN-TIME LIBRARIES" OFF)
endif ()
include(ZstdOptions)
#-----------------------------------------------------------------------------
# External dependencies
# Configure compilation flags
#-----------------------------------------------------------------------------
# Define a function to handle special thread settings for HP-UX
# See https://github.com/facebook/zstd/pull/3862 for details.
function(setup_hpux_threads)
find_package(Threads)
if (NOT Threads_FOUND)
set(CMAKE_USE_PTHREADS_INIT 1 PARENT_SCOPE)
set(CMAKE_THREAD_LIBS_INIT -lpthread PARENT_SCOPE)
set(CMAKE_HAVE_THREADS_LIBRARY 1 PARENT_SCOPE)
set(Threads_FOUND TRUE PARENT_SCOPE)
endif()
endfunction()
if (ZSTD_MULTITHREAD_SUPPORT AND UNIX)
if (CMAKE_SYSTEM_NAME MATCHES "HP-UX")
setup_hpux_threads()
else()
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
endif()
if (CMAKE_USE_PTHREADS_INIT)
set(THREADS_LIBS "${CMAKE_THREAD_LIBS_INIT}")
else()
message(SEND_ERROR "ZSTD currently does not support thread libraries other than pthreads")
endif()
endif ()
include(AddZstdCompilationFlags)
ADD_ZSTD_COMPILATION_FLAGS(ON ZSTD_ENABLE_CXX ON)
#-----------------------------------------------------------------------------
# Add source directories
# Configure dependencies
#-----------------------------------------------------------------------------
add_subdirectory(lib)
option(ZSTD_PROGRAMS_LINK_SHARED "PROGRAMS LINK SHARED" OFF)
if (ZSTD_BUILD_PROGRAMS)
if (NOT ZSTD_BUILD_STATIC AND NOT ZSTD_PROGRAMS_LINK_SHARED)
message(SEND_ERROR "You need to build static library to build zstd CLI")
elseif(NOT ZSTD_BUILD_SHARED AND ZSTD_PROGRAMS_LINK_SHARED)
message(SEND_ERROR "You need to build shared library to build zstd CLI")
endif ()
add_subdirectory(programs)
endif ()
if (ZSTD_BUILD_TESTS)
enable_testing()
if (NOT ZSTD_BUILD_STATIC)
message(SEND_ERROR "You need to build static library to build tests")
endif ()
add_subdirectory(tests)
endif ()
if (ZSTD_BUILD_CONTRIB)
add_subdirectory(contrib)
endif ()
include(ZstdDependencies)
#-----------------------------------------------------------------------------
# Add clean-all target
# Configure build targets
#-----------------------------------------------------------------------------
add_custom_target(clean-all
COMMAND ${CMAKE_BUILD_TOOL} clean
COMMAND rm -rf ${CMAKE_BINARY_DIR}/
)
include(ZstdBuild)
#-----------------------------------------------------------------------------
# Generate Package Config files
#
# This section is based on the boiler plate code from:
# https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#creating-packages
# Configure package generation
#-----------------------------------------------------------------------------
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfigVersion.cmake"
VERSION ${zstd_VERSION}
COMPATIBILITY SameMajorVersion
)
# A Package Config file that works from the build directory
export(EXPORT zstdExports
FILE "${CMAKE_CURRENT_BINARY_DIR}/zstdTargets.cmake"
NAMESPACE zstd::
)
# A Package Config file that works from the installation directory
set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/zstd)
install(EXPORT zstdExports
FILE zstdTargets.cmake
NAMESPACE zstd::
DESTINATION ${ConfigPackageLocation}
)
configure_package_config_file(
zstdConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake"
INSTALL_DESTINATION ${ConfigPackageLocation}
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfigVersion.cmake"
DESTINATION ${ConfigPackageLocation}
)
include(ZstdPackage)

View file

@ -1,5 +1,7 @@
include(CheckCXXCompilerFlag)
include(CheckCCompilerFlag)
if(CMAKE_CXX_COMPILER)
include(CheckCXXCompilerFlag)
endif()
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
set(ZSTD_HAVE_CHECK_LINKER_FLAG true)
@ -21,7 +23,7 @@ function(EnableCompilerFlag _flag _C _CXX _LD)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_flag}" PARENT_SCOPE)
endif ()
endif ()
if (_CXX)
if (_CXX AND CMAKE_CXX_COMPILER)
CHECK_CXX_COMPILER_FLAG(${_flag} CXX_FLAG_${varname})
if (CXX_FLAG_${varname})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_flag}" PARENT_SCOPE)
@ -49,7 +51,7 @@ function(EnableCompilerFlag _flag _C _CXX _LD)
endif ()
endfunction()
macro(ADD_ZSTD_COMPILATION_FLAGS)
macro(ADD_ZSTD_COMPILATION_FLAGS _C _CXX _LD)
# We set ZSTD_HAS_NOEXECSTACK if we are certain we've set all the required
# compiler flags to mark the stack as non-executable.
set(ZSTD_HAS_NOEXECSTACK false)
@ -63,26 +65,26 @@ macro(ADD_ZSTD_COMPILATION_FLAGS)
# EnableCompilerFlag("-std=c99" true false) # Set C compilation to c99 standard
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND MSVC)
# clang-cl normally maps -Wall to -Weverything.
EnableCompilerFlag("/clang:-Wall" true true false)
EnableCompilerFlag("/clang:-Wall" _C _CXX false)
else ()
EnableCompilerFlag("-Wall" true true false)
EnableCompilerFlag("-Wall" _C _CXX false)
endif ()
EnableCompilerFlag("-Wextra" true true false)
EnableCompilerFlag("-Wundef" true true false)
EnableCompilerFlag("-Wshadow" true true false)
EnableCompilerFlag("-Wcast-align" true true false)
EnableCompilerFlag("-Wcast-qual" true true false)
EnableCompilerFlag("-Wstrict-prototypes" true false false)
EnableCompilerFlag("-Wextra" _C _CXX false)
EnableCompilerFlag("-Wundef" _C _CXX false)
EnableCompilerFlag("-Wshadow" _C _CXX false)
EnableCompilerFlag("-Wcast-align" _C _CXX false)
EnableCompilerFlag("-Wcast-qual" _C _CXX false)
EnableCompilerFlag("-Wstrict-prototypes" _C false false)
# Enable asserts in Debug mode
if (CMAKE_BUILD_TYPE MATCHES "Debug")
EnableCompilerFlag("-DDEBUGLEVEL=1" true true false)
EnableCompilerFlag("-DDEBUGLEVEL=1" _C _CXX false)
endif ()
# Add noexecstack flags
# LDFLAGS
EnableCompilerFlag("-Wl,-z,noexecstack" false false true)
EnableCompilerFlag("-Wl,-z,noexecstack" false false _LD)
# CFLAGS & CXXFLAGS
EnableCompilerFlag("-Qunused-arguments" true true false)
EnableCompilerFlag("-Wa,--noexecstack" true true false)
EnableCompilerFlag("-Qunused-arguments" _C _CXX false)
EnableCompilerFlag("-Wa,--noexecstack" _C _CXX false)
# NOTE: Using 3 nested ifs because the variables are sometimes
# empty if the condition is false, and sometimes equal to false.
# This implicitly converts them to truthy values. There may be
@ -99,15 +101,15 @@ macro(ADD_ZSTD_COMPILATION_FLAGS)
set(ACTIVATE_MULTITHREADED_COMPILATION "ON" CACHE BOOL "activate multi-threaded compilation (/MP flag)")
if (CMAKE_GENERATOR MATCHES "Visual Studio" AND ACTIVATE_MULTITHREADED_COMPILATION)
EnableCompilerFlag("/MP" true true false)
EnableCompilerFlag("/MP" _C _CXX false)
endif ()
# UNICODE SUPPORT
EnableCompilerFlag("/D_UNICODE" true true false)
EnableCompilerFlag("/DUNICODE" true true false)
EnableCompilerFlag("/D_UNICODE" _C _CXX false)
EnableCompilerFlag("/DUNICODE" _C _CXX false)
# Enable asserts in Debug mode
if (CMAKE_BUILD_TYPE MATCHES "Debug")
EnableCompilerFlag("/DDEBUGLEVEL=1" true true false)
EnableCompilerFlag("/DDEBUGLEVEL=1" _C _CXX false)
endif ()
endif ()

View file

@ -0,0 +1,42 @@
# ################################################################
# ZSTD Build Targets Configuration
# ################################################################
# Always build the library first (this defines ZSTD_BUILD_STATIC/SHARED options)
add_subdirectory(lib)
# Validate build configuration after lib options are defined
if(ZSTD_BUILD_PROGRAMS)
if(NOT ZSTD_BUILD_STATIC AND NOT ZSTD_PROGRAMS_LINK_SHARED)
message(SEND_ERROR "Static library required to build zstd CLI programs")
elseif(NOT ZSTD_BUILD_SHARED AND ZSTD_PROGRAMS_LINK_SHARED)
message(SEND_ERROR "Shared library required to build zstd CLI programs")
endif()
endif()
if(ZSTD_BUILD_TESTS AND NOT ZSTD_BUILD_STATIC)
message(SEND_ERROR "Static library required to build test suite")
endif()
# Add programs if requested
if(ZSTD_BUILD_PROGRAMS)
add_subdirectory(programs)
endif()
# Add tests if requested
if(ZSTD_BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
# Add contrib utilities if requested
if(ZSTD_BUILD_CONTRIB)
add_subdirectory(contrib)
endif()
# Clean-all target for thorough cleanup
add_custom_target(clean-all
COMMAND ${CMAKE_BUILD_TOOL} clean
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/
COMMENT "Performing complete clean including build directory"
)

View file

@ -0,0 +1,30 @@
# ################################################################
# ZSTD Dependencies Configuration
# ################################################################
# Function to handle HP-UX thread configuration
function(setup_hpux_threads)
find_package(Threads)
if(NOT Threads_FOUND)
set(CMAKE_USE_PTHREADS_INIT 1 PARENT_SCOPE)
set(CMAKE_THREAD_LIBS_INIT -lpthread PARENT_SCOPE)
set(CMAKE_HAVE_THREADS_LIBRARY 1 PARENT_SCOPE)
set(Threads_FOUND TRUE PARENT_SCOPE)
endif()
endfunction()
# Configure threading support
if(ZSTD_MULTITHREAD_SUPPORT AND UNIX)
if(CMAKE_SYSTEM_NAME MATCHES "HP-UX")
setup_hpux_threads()
else()
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
endif()
if(CMAKE_USE_PTHREADS_INIT)
set(THREADS_LIBS "${CMAKE_THREAD_LIBS_INIT}")
else()
message(SEND_ERROR "ZSTD currently does not support thread libraries other than pthreads")
endif()
endif()

View file

@ -0,0 +1,68 @@
# ################################################################
# ZSTD Build Options Configuration
# ################################################################
# Legacy support configuration (disabled by default)
option(ZSTD_LEGACY_SUPPORT "Enable legacy format support" OFF)
if(ZSTD_LEGACY_SUPPORT)
message(STATUS "ZSTD_LEGACY_SUPPORT enabled")
set(ZSTD_LEGACY_LEVEL 5 CACHE STRING "Legacy support level")
add_definitions(-DZSTD_LEGACY_SUPPORT=${ZSTD_LEGACY_LEVEL})
else()
message(STATUS "ZSTD_LEGACY_SUPPORT disabled")
add_definitions(-DZSTD_LEGACY_SUPPORT=0)
endif()
# Platform-specific options
if(APPLE)
option(ZSTD_FRAMEWORK "Build as Apple Framework" OFF)
endif()
# Android-specific configuration
if(ANDROID)
set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT OFF)
# Handle old Android API levels
if((NOT ANDROID_PLATFORM_LEVEL) OR (ANDROID_PLATFORM_LEVEL VERSION_LESS 24))
message(STATUS "Configuring for old Android API - disabling fseeko/ftello")
add_compile_definitions(LIBC_NO_FSEEKO)
endif()
else()
set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT ON)
endif()
# Multi-threading support
option(ZSTD_MULTITHREAD_SUPPORT "Enable multi-threading support" ${ZSTD_MULTITHREAD_SUPPORT_DEFAULT})
if(ZSTD_MULTITHREAD_SUPPORT)
message(STATUS "Multi-threading support enabled")
else()
message(STATUS "Multi-threading support disabled")
endif()
# Build component options
option(ZSTD_BUILD_PROGRAMS "Build command-line programs" ON)
option(ZSTD_BUILD_CONTRIB "Build contrib utilities" OFF)
option(ZSTD_PROGRAMS_LINK_SHARED "Link programs against shared library" OFF)
# Test configuration
if(BUILD_TESTING)
set(ZSTD_BUILD_TESTS_default ON)
else()
set(ZSTD_BUILD_TESTS_default OFF)
endif()
option(ZSTD_BUILD_TESTS "Build test suite" ${ZSTD_BUILD_TESTS_default})
# MSVC-specific options
if(MSVC)
option(ZSTD_USE_STATIC_RUNTIME "Link to static runtime libraries" OFF)
endif()
# C++ support (needed for tests)
set(ZSTD_ENABLE_CXX ${ZSTD_BUILD_TESTS})
if(ZSTD_ENABLE_CXX)
enable_language(CXX)
endif()
# Set global definitions
add_definitions(-DXXH_NAMESPACE=ZSTD_)

View file

@ -0,0 +1,45 @@
# ################################################################
# ZSTD Package Configuration
# ################################################################
include(CMakePackageConfigHelpers)
# Generate version file
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfigVersion.cmake"
VERSION ${zstd_VERSION}
COMPATIBILITY SameMajorVersion
)
# Configure package for installation
set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/zstd)
foreach(target_suffix IN ITEMS "_shared" "_static" "")
if(TARGET "libzstd${target_suffix}")
# Export targets for build directory
export(EXPORT "zstdExports${target_suffix}"
FILE "${CMAKE_CURRENT_BINARY_DIR}/zstdTargets${target_suffix}.cmake"
NAMESPACE zstd::
)
# Install exported targets
install(EXPORT "zstdExports${target_suffix}"
FILE "zstdTargets${target_suffix}.cmake"
NAMESPACE zstd::
DESTINATION ${ConfigPackageLocation}
)
endif()
endforeach()
# Configure and install package config file
configure_package_config_file(
zstdConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake"
INSTALL_DESTINATION ${ConfigPackageLocation}
)
# Install config files
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/zstdConfigVersion.cmake"
DESTINATION ${ConfigPackageLocation}
)

View file

@ -0,0 +1,31 @@
# ################################################################
# ZSTD Version Configuration
# ################################################################
# Setup CMake policy version
set(ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION "3")
set(ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION "13")
# Determine appropriate policy version
if("${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}" EQUAL "${CMAKE_MAJOR_VERSION}" AND
"${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}" GREATER "${CMAKE_MINOR_VERSION}")
set(ZSTD_CMAKE_POLICY_VERSION "${CMAKE_VERSION}")
else()
set(ZSTD_CMAKE_POLICY_VERSION "${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}.${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}.0")
endif()
cmake_policy(VERSION ${ZSTD_CMAKE_POLICY_VERSION})
# Parse version from header file
include(GetZstdLibraryVersion)
GetZstdLibraryVersion(${LIBRARY_DIR}/zstd.h zstd_VERSION_MAJOR zstd_VERSION_MINOR zstd_VERSION_PATCH)
# Set version variables
set(ZSTD_SHORT_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}")
set(ZSTD_FULL_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}")
# Project metadata
set(zstd_HOMEPAGE_URL "https://facebook.github.io/zstd")
set(zstd_DESCRIPTION "Zstandard is a real-time compression algorithm, providing high compression ratios.")
message(STATUS "ZSTD VERSION: ${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}")

View file

@ -7,6 +7,15 @@ variables.
## How to build
You can configure the project from the repository root thanks to the forwarding
`CMakeLists.txt`:
```sh
cmake -S . -B build-cmake
cmake --build build-cmake
```
The historical workflow that starts configuration from `build/cmake` continues
to work as described below.
As cmake doesn't support command like `cmake clean`, it's recommended to perform an "out of source build".
To do this, you can create a new directory and build in it:
```sh

View file

@ -7,7 +7,7 @@
# in the COPYING file in the root directory of this source tree).
# ################################################################
project(libzstd C ASM)
project(libzstd C) # ASM language is conditionally enabled where supported
set(CMAKE_INCLUDE_CURRENT_DIR TRUE)
option(ZSTD_BUILD_STATIC "BUILD STATIC LIBRARIES" ON)
@ -40,6 +40,7 @@ if (MSVC)
add_compile_options(-DZSTD_DISABLE_ASM)
else ()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|AMD64.*|x86_64.*|X86_64.*" AND ${ZSTD_HAS_NOEXECSTACK})
enable_language(ASM)
set(DecompressSources ${DecompressSources} ${LIBRARY_DIR}/decompress/huf_decompress_amd64.S)
else()
add_compile_options(-DZSTD_DISABLE_ASM)
@ -97,9 +98,11 @@ if (ZSTD_LEGACY_SUPPORT)
${LIBRARY_LEGACY_DIR}/zstd_v07.h)
endif ()
if (MSVC)
if (MSVC AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
set(MSVC_RESOURCE_DIR ${ZSTD_SOURCE_DIR}/build/VS2010/libzstd-dll)
set(PlatformDependResources ${MSVC_RESOURCE_DIR}/libzstd-dll.rc)
else()
set(PlatformDependResources)
endif ()
# Explicitly set the language to C for all files, including ASM files.
@ -112,7 +115,7 @@ endif()
macro (add_definition target var)
if (NOT ("${${var}}" STREQUAL ""))
set_property(TARGET ${target} APPEND PROPERTY COMPILE_DEFINITIONS "${var}=__attribute__((visibility(\"${${var}}\")))")
target_compile_definitions(${target} PUBLIC "${var}=__attribute__((visibility(\"${${var}}\")))")
endif ()
endmacro ()
@ -120,13 +123,11 @@ endmacro ()
set(PUBLIC_INCLUDE_DIRS ${LIBRARY_DIR})
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} /I \"${LIBRARY_DIR}\"")
# Split project to static and shared libraries build
set(library_targets)
if (ZSTD_BUILD_SHARED)
add_library(libzstd_shared SHARED ${Sources} ${Headers} ${PlatformDependResources})
target_include_directories(libzstd_shared INTERFACE $<BUILD_INTERFACE:${PUBLIC_INCLUDE_DIRS}>)
list(APPEND library_targets libzstd_shared)
if (ZSTD_MULTITHREAD_SUPPORT)
set_property(TARGET libzstd_shared APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_MULTITHREAD")
target_compile_definitions(libzstd_shared PUBLIC ZSTD_MULTITHREAD)
if (UNIX)
target_link_libraries(libzstd_shared ${THREADS_LIBS})
endif ()
@ -138,9 +139,8 @@ endif ()
if (ZSTD_BUILD_STATIC)
add_library(libzstd_static STATIC ${Sources} ${Headers})
target_include_directories(libzstd_static INTERFACE $<BUILD_INTERFACE:${PUBLIC_INCLUDE_DIRS}>)
list(APPEND library_targets libzstd_static)
if (ZSTD_MULTITHREAD_SUPPORT)
set_property(TARGET libzstd_static APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_MULTITHREAD")
target_compile_definitions(libzstd_static PUBLIC ZSTD_MULTITHREAD)
if (UNIX)
target_link_libraries(libzstd_static ${THREADS_LIBS})
endif ()
@ -157,7 +157,6 @@ if (ZSTD_BUILD_SHARED AND NOT ZSTD_BUILD_STATIC)
endif ()
add_library(libzstd INTERFACE)
target_link_libraries(libzstd INTERFACE libzstd_shared)
list(APPEND library_targets libzstd)
endif ()
if (ZSTD_BUILD_STATIC AND NOT ZSTD_BUILD_SHARED)
if (BUILD_SHARED_LIBS)
@ -165,7 +164,6 @@ if (ZSTD_BUILD_STATIC AND NOT ZSTD_BUILD_SHARED)
endif ()
add_library(libzstd INTERFACE)
target_link_libraries(libzstd INTERFACE libzstd_static)
list(APPEND library_targets libzstd)
endif ()
if (ZSTD_BUILD_SHARED AND ZSTD_BUILD_STATIC)
# If both ZSTD_BUILD_SHARED and ZSTD_BUILD_STATIC are set, which is the
@ -174,11 +172,9 @@ if (ZSTD_BUILD_SHARED AND ZSTD_BUILD_STATIC)
if (BUILD_SHARED_LIBS)
add_library(libzstd INTERFACE)
target_link_libraries(libzstd INTERFACE libzstd_shared)
list(APPEND library_targets libzstd)
else ()
add_library(libzstd INTERFACE)
target_link_libraries(libzstd INTERFACE libzstd_static)
list(APPEND library_targets libzstd)
endif ()
endif ()
@ -272,8 +268,10 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libzstd.pc" DESTINATION "${CMAKE_INST
# install target
install(FILES ${PublicHeaders} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(TARGETS ${library_targets}
EXPORT zstdExports
foreach(target_suffix IN ITEMS "_shared" "_static" "")
if(TARGET "libzstd${target_suffix}")
install(TARGETS "libzstd${target_suffix}"
EXPORT "zstdExports${target_suffix}"
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
@ -282,6 +280,8 @@ install(TARGETS ${library_targets}
FRAMEWORK DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT runtime OPTIONAL
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
endif()
endforeach()
# uninstall target
if (NOT TARGET uninstall)

View file

@ -5,6 +5,9 @@ if(@ZSTD_MULTITHREAD_SUPPORT@ AND "@UNIX@")
find_dependency(Threads)
endif()
foreach(lib_suffix IN ITEMS "_shared" "_static")
include("${CMAKE_CURRENT_LIST_DIR}/zstdTargets${lib_suffix}.cmake" OPTIONAL)
endforeach()
include("${CMAKE_CURRENT_LIST_DIR}/zstdTargets.cmake")
check_required_components("zstd")

View file

@ -127,6 +127,10 @@ libzstd = library('zstd',
libzstd_dep = declare_dependency(link_with: libzstd,
include_directories: join_paths(zstd_rootdir,'lib')) # Do not expose private headers
if meson.version().version_compare('>=0.54.0')
meson.override_dependency('libzstd', libzstd_dep)
endif
# we link to both:
# - the shared library (for public symbols)
# - the static library (for private symbols)

View file

@ -10,7 +10,7 @@
project('zstd',
['c', 'cpp'],
license: ['BSD', 'GPLv2'],
license: 'BSD-3-Clause OR GPL-2.0-only',
default_options : [
# There shouldn't be any need to force a C standard convention for zstd
# but in case one would want that anyway, this can be done here.
@ -65,7 +65,6 @@ zstd_docdir = join_paths(zstd_datadir, 'doc', meson.project_name())
# Built-in options
use_debug = get_option('debug')
buildtype = get_option('buildtype')
default_library_type = get_option('default_library')
# Custom options

View file

@ -10,8 +10,8 @@
# Read guidelines from https://wiki.gnome.org/Initiatives/GnomeGoals/MesonPorting
option('legacy_level', type: 'integer', min: 0, max: 7, value: 5,
description: 'Support any legacy format: 7 to 1 for v0.7+ to v0.1+')
option('legacy_level', type: 'integer', min: 0, max: 7, value: 0,
description: 'Support legacy format: 0=disabled, 1-7=support v0.1+ to v0.7+')
option('debug_level', type: 'integer', min: 0, max: 9, value: 1,
description: 'Enable run-time debug. See lib/common/debug.h')
option('backtrace', type: 'feature', value: 'disabled',

View file

@ -19,7 +19,7 @@ def valgrindTest(valgrind, datagen, fuzzer, zstd, fullbench):
subprocess.check_call([*VALGRIND_ARGS, datagen, '-g50M'], stdout=subprocess.DEVNULL)
if subprocess.call([*VALGRIND_ARGS, zstd],
if subprocess.call([*VALGRIND_ARGS, zstd, '--fake-stdin-is-console'],
stdout=subprocess.DEVNULL) == 0:
raise subprocess.SubprocessError('zstd without argument should have failed')

View file

@ -27,6 +27,7 @@ do { \
} while (0) \
int main(int argc, char *argv[]) {
int retn = 0;
if (argc != 2) {
printf("Usage: externalSequenceProducer <file>\n");
return 1;
@ -96,12 +97,12 @@ int main(int argc, char *argv[]) {
break;
}
}
return 1;
retn = 1;
}
ZSTD_freeCCtx(zc);
free(src);
free(dst);
free(val);
return 0;
return retn;
}

View file

@ -45,7 +45,9 @@
#define RUN_TIME_DEFAULT_MS 1000
#define BENCH_TIME_DEFAULT_MS (BENCH_TIME_DEFAULT_S * RUN_TIME_DEFAULT_MS)
#define DISPLAY_LEVEL_DEFAULT 3
#ifndef ZSTD_DISPLAY_LEVEL_DEFAULT
# define ZSTD_DISPLAY_LEVEL_DEFAULT 3
#endif
#define BENCH_SIZE_MAX (1200 MB)
@ -61,7 +63,7 @@
#define DISPLAY(...) fprintf(stdout, __VA_ARGS__)
#define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
static int g_displayLevel = DISPLAY_LEVEL_DEFAULT; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */
static int g_displayLevel = ZSTD_DISPLAY_LEVEL_DEFAULT; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */
/*--- buffer_t ---*/
@ -739,6 +741,8 @@ static int benchMem(slice_collection_t dstBlocks, slice_collection_t srcBlocks,
/* BMK_benchTimedFn may not run exactly nbRounds iterations */
double speedAggregated =
aggregateData(speedPerRound, roundNb + 1, metricAggregatePref);
free(speedPerRound);
if (metricAggregatePref == fastest)
DISPLAY("Fastest Speed : %.1f MB/s \n", speedAggregated);
else

View file

@ -77,6 +77,30 @@ int zstd_min_clevel(void);
*/
int zstd_max_clevel(void);
/**
* zstd_default_clevel() - default compression level
*
* Return: Default compression level.
*/
int zstd_default_clevel(void);
/**
* struct zstd_custom_mem - custom memory allocation
*/
typedef ZSTD_customMem zstd_custom_mem;
/**
* struct zstd_dict_load_method - Dictionary load method.
* See zstd_lib.h.
*/
typedef ZSTD_dictLoadMethod_e zstd_dict_load_method;
/**
* struct zstd_dict_content_type - Dictionary context type.
* See zstd_lib.h.
*/
typedef ZSTD_dictContentType_e zstd_dict_content_type;
/* ====== Parameter Selection ====== */
/**
@ -136,6 +160,18 @@ typedef ZSTD_parameters zstd_parameters;
zstd_parameters zstd_get_params(int level,
unsigned long long estimated_src_size);
/**
* zstd_get_cparams() - returns zstd_compression_parameters for selected level
* @level: The compression level
* @estimated_src_size: The estimated source size to compress or 0
* if unknown.
* @dict_size: Dictionary size.
*
* Return: The selected zstd_compression_parameters.
*/
zstd_compression_parameters zstd_get_cparams(int level,
unsigned long long estimated_src_size, size_t dict_size);
typedef ZSTD_CCtx zstd_cctx;
typedef ZSTD_cParameter zstd_cparameter;
@ -205,6 +241,71 @@ zstd_cctx *zstd_init_cctx(void *workspace, size_t workspace_size);
size_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,
const void *src, size_t src_size, const zstd_parameters *parameters);
/**
* zstd_create_cctx_advanced() - Create compression context
* @custom_mem: Custom allocator.
*
* Return: NULL on error, pointer to compression context otherwise.
*/
zstd_cctx *zstd_create_cctx_advanced(zstd_custom_mem custom_mem);
/**
* zstd_free_cctx() - Free compression context
* @cdict: Pointer to compression context.
*
* Return: Always 0.
*/
size_t zstd_free_cctx(zstd_cctx* cctx);
/**
* struct zstd_cdict - Compression dictionary.
* See zstd_lib.h.
*/
typedef ZSTD_CDict zstd_cdict;
/**
* zstd_create_cdict_byreference() - Create compression dictionary
* @dict: Pointer to dictionary buffer.
* @dict_size: Size of the dictionary buffer.
* @dict_load_method: Dictionary load method.
* @dict_content_type: Dictionary content type.
* @custom_mem: Memory allocator.
*
* Note, this uses @dict by reference (ZSTD_dlm_byRef), so it should be
* free before zstd_cdict is destroyed.
*
* Return: NULL on error, pointer to compression dictionary
* otherwise.
*/
zstd_cdict *zstd_create_cdict_byreference(const void *dict, size_t dict_size,
zstd_compression_parameters cparams,
zstd_custom_mem custom_mem);
/**
* zstd_free_cdict() - Free compression dictionary
* @cdict: Pointer to compression dictionary.
*
* Return: Always 0.
*/
size_t zstd_free_cdict(zstd_cdict* cdict);
/**
* zstd_compress_using_cdict() - compress src into dst using a dictionary
* @cctx: The context. Must have been initialized with zstd_init_cctx().
* @dst: The buffer to compress src into.
* @dst_capacity: The size of the destination buffer. May be any size, but
* ZSTD_compressBound(srcSize) is guaranteed to be large enough.
* @src: The data to compress.
* @src_size: The size of the data to compress.
* @cdict: The dictionary to be used.
*
* Return: The compressed size or an error, which can be checked using
* zstd_is_error().
*/
size_t zstd_compress_using_cdict(zstd_cctx *cctx, void *dst,
size_t dst_capacity, const void *src, size_t src_size,
const zstd_cdict *cdict);
/* ====== Single-pass Decompression ====== */
typedef ZSTD_DCtx zstd_dctx;
@ -245,6 +346,71 @@ zstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size);
size_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,
const void *src, size_t src_size);
/**
* struct zstd_ddict - Decompression dictionary.
* See zstd_lib.h.
*/
typedef ZSTD_DDict zstd_ddict;
/**
* zstd_create_ddict_byreference() - Create decompression dictionary
* @dict: Pointer to dictionary buffer.
* @dict_size: Size of the dictionary buffer.
* @dict_load_method: Dictionary load method.
* @dict_content_type: Dictionary content type.
* @custom_mem: Memory allocator.
*
* Note, this uses @dict by reference (ZSTD_dlm_byRef), so it should be
* free before zstd_ddict is destroyed.
*
* Return: NULL on error, pointer to decompression dictionary
* otherwise.
*/
zstd_ddict *zstd_create_ddict_byreference(const void *dict, size_t dict_size,
zstd_custom_mem custom_mem);
/**
* zstd_free_ddict() - Free decompression dictionary
* @dict: Pointer to the dictionary.
*
* Return: Always 0.
*/
size_t zstd_free_ddict(zstd_ddict *ddict);
/**
* zstd_create_dctx_advanced() - Create decompression context
* @custom_mem: Custom allocator.
*
* Return: NULL on error, pointer to decompression context otherwise.
*/
zstd_dctx *zstd_create_dctx_advanced(zstd_custom_mem custom_mem);
/**
* zstd_free_dctx() -- Free decompression context
* @dctx: Pointer to decompression context.
* Return: Always 0.
*/
size_t zstd_free_dctx(zstd_dctx *dctx);
/**
* zstd_decompress_using_ddict() - decompress src into dst using a dictionary
* @dctx: The decompression context.
* @dst: The buffer to decompress src into.
* @dst_capacity: The size of the destination buffer. Must be at least as large
* as the decompressed size. If the caller cannot upper bound the
* decompressed size, then it's better to use the streaming API.
* @src: The zstd compressed data to decompress. Multiple concatenated
* frames and skippable frames are allowed.
* @src_size: The exact size of the data to decompress.
* @ddict: The dictionary to be used.
*
* Return: The decompressed size or an error, which can be checked using
* zstd_is_error().
*/
size_t zstd_decompress_using_ddict(zstd_dctx *dctx,
void *dst, size_t dst_capacity, const void *src, size_t src_size,
const zstd_ddict *ddict);
/* ====== Streaming Buffers ====== */
/**

View file

@ -67,6 +67,12 @@ int zstd_max_clevel(void)
}
EXPORT_SYMBOL(zstd_max_clevel);
int zstd_default_clevel(void)
{
return ZSTD_defaultCLevel();
}
EXPORT_SYMBOL(zstd_default_clevel);
size_t zstd_compress_bound(size_t src_size)
{
return ZSTD_compressBound(src_size);
@ -80,6 +86,13 @@ zstd_parameters zstd_get_params(int level,
}
EXPORT_SYMBOL(zstd_get_params);
zstd_compression_parameters zstd_get_cparams(int level,
unsigned long long estimated_src_size, size_t dict_size)
{
return ZSTD_getCParams(level, estimated_src_size, dict_size);
}
EXPORT_SYMBOL(zstd_get_cparams);
size_t zstd_cctx_set_param(zstd_cctx *cctx, ZSTD_cParameter param, int value)
{
return ZSTD_CCtx_setParameter(cctx, param, value);
@ -146,6 +159,33 @@ zstd_cctx *zstd_init_cctx(void *workspace, size_t workspace_size)
}
EXPORT_SYMBOL(zstd_init_cctx);
zstd_cctx *zstd_create_cctx_advanced(zstd_custom_mem custom_mem)
{
return ZSTD_createCCtx_advanced(custom_mem);
}
EXPORT_SYMBOL(zstd_create_cctx_advanced);
size_t zstd_free_cctx(zstd_cctx *cctx)
{
return ZSTD_freeCCtx(cctx);
}
EXPORT_SYMBOL(zstd_free_cctx);
zstd_cdict *zstd_create_cdict_byreference(const void *dict, size_t dict_size,
zstd_compression_parameters cparams,
zstd_custom_mem custom_mem)
{
return ZSTD_createCDict_advanced(dict, dict_size, ZSTD_dlm_byRef,
ZSTD_dct_auto, cparams, custom_mem);
}
EXPORT_SYMBOL(zstd_create_cdict_byreference);
size_t zstd_free_cdict(zstd_cdict *cdict)
{
return ZSTD_freeCDict(cdict);
}
EXPORT_SYMBOL(zstd_free_cdict);
size_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,
const void *src, size_t src_size, const zstd_parameters *parameters)
{
@ -154,6 +194,15 @@ size_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,
}
EXPORT_SYMBOL(zstd_compress_cctx);
size_t zstd_compress_using_cdict(zstd_cctx *cctx, void *dst,
size_t dst_capacity, const void *src, size_t src_size,
const ZSTD_CDict *cdict)
{
return ZSTD_compress_usingCDict(cctx, dst, dst_capacity,
src, src_size, cdict);
}
EXPORT_SYMBOL(zstd_compress_using_cdict);
size_t zstd_cstream_workspace_bound(const zstd_compression_parameters *cparams)
{
return ZSTD_estimateCStreamSize_usingCParams(*cparams);

View file

@ -44,6 +44,33 @@ size_t zstd_dctx_workspace_bound(void)
}
EXPORT_SYMBOL(zstd_dctx_workspace_bound);
zstd_dctx *zstd_create_dctx_advanced(zstd_custom_mem custom_mem)
{
return ZSTD_createDCtx_advanced(custom_mem);
}
EXPORT_SYMBOL(zstd_create_dctx_advanced);
size_t zstd_free_dctx(zstd_dctx *dctx)
{
return ZSTD_freeDCtx(dctx);
}
EXPORT_SYMBOL(zstd_free_dctx);
zstd_ddict *zstd_create_ddict_byreference(const void *dict, size_t dict_size,
zstd_custom_mem custom_mem)
{
return ZSTD_createDDict_advanced(dict, dict_size, ZSTD_dlm_byRef,
ZSTD_dct_auto, custom_mem);
}
EXPORT_SYMBOL(zstd_create_ddict_byreference);
size_t zstd_free_ddict(zstd_ddict *ddict)
{
return ZSTD_freeDDict(ddict);
}
EXPORT_SYMBOL(zstd_free_ddict);
zstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size)
{
if (workspace == NULL)
@ -59,6 +86,15 @@ size_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,
}
EXPORT_SYMBOL(zstd_decompress_dctx);
size_t zstd_decompress_using_ddict(zstd_dctx *dctx,
void *dst, size_t dst_capacity, const void* src, size_t src_size,
const zstd_ddict* ddict)
{
return ZSTD_decompress_usingDDict(dctx, dst, dst_capacity, src,
src_size, ddict);
}
EXPORT_SYMBOL(zstd_decompress_using_ddict);
size_t zstd_dstream_workspace_bound(size_t max_window_size)
{
return ZSTD_estimateDStreamSize(max_window_size);

View file

@ -2,6 +2,7 @@
-- Basic usage: project_zstd(ZSTD_DIR)
function project_zstd(dir, compression, decompression, deprecated, dictbuilder, legacy)
if string.sub(dir, -1, 1) ~= '/' then dir = dir .. '/' end
if compression == nil then compression = true end
if decompression == nil then decompression = true end
if deprecated == nil then deprecated = false end

View file

@ -10,6 +10,7 @@
#include <cstdio>
#include <mutex>
#include <chrono>
namespace pzstd {

View file

@ -11,6 +11,8 @@
ZSTDLIB_PATH = ../../../lib
ZSTDLIB_NAME = libzstd.a
# Parallel tools only make sense against multi-threaded libzstd
ZSTDLIB_TARGET = $(ZSTDLIB_NAME)-mt
ZSTDLIB = $(ZSTDLIB_PATH)/$(ZSTDLIB_NAME)
CPPFLAGS += -DXXH_NAMESPACE=ZSTD_ -I../ -I../../../lib -I../../../lib/common
@ -28,7 +30,7 @@ all: seekable_compression seekable_decompression seekable_decompression_mem \
parallel_processing
$(ZSTDLIB):
make -C $(ZSTDLIB_PATH) $(ZSTDLIB_NAME)
$(MAKE) -C $(ZSTDLIB_PATH) $(ZSTDLIB_TARGET)
seekable_compression : seekable_compression.c $(SEEKABLE_OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@

View file

@ -23,6 +23,8 @@
#include "xxhash.h"
#define ZSTD_MULTITHREAD 1
#include "threading.h"
#include "pool.h" // use zstd thread pool for demo
#include "../zstd_seekable.h"
@ -72,114 +74,87 @@ static size_t fclose_orDie(FILE* file)
exit(6);
}
static void fseek_orDie(FILE* file, long int offset, int origin)
{
if (!fseek(file, offset, origin)) {
if (!fflush(file)) return;
}
/* error */
perror("fseek");
exit(7);
}
static long int ftell_orDie(FILE* file)
{
long int off = ftell(file);
if (off != -1) return off;
/* error */
perror("ftell");
exit(8);
}
struct state {
FILE* fout;
ZSTD_pthread_mutex_t mutex;
size_t nextID;
struct job* pending;
ZSTD_frameLog* frameLog;
const int compressionLevel;
};
struct job {
const void* src;
size_t id;
struct job* next;
struct state* state;
void* src;
size_t srcSize;
void* dst;
size_t dstSize;
unsigned checksum;
int compressionLevel;
int done;
};
static void addPending_inmutex(struct state* state, struct job* job)
{
struct job** p = &state->pending;
while (*p && (*p)->id < job->id)
p = &(*p)->next;
job->next = *p;
*p = job;
}
static void flushFrame(struct state* state, struct job* job)
{
fwrite_orDie(job->dst, job->dstSize, state->fout);
free(job->dst);
size_t ret = ZSTD_seekable_logFrame(state->frameLog, (unsigned)job->dstSize, (unsigned)job->srcSize, job->checksum);
if (ZSTD_isError(ret)) {
fprintf(stderr, "ZSTD_seekable_logFrame() error : %s \n", ZSTD_getErrorName(ret));
exit(12);
}
}
static void flushPending_inmutex(struct state* state)
{
while (state->pending && state->pending->id == state->nextID) {
struct job* p = state->pending;
state->pending = p->next;
flushFrame(state, p);
free(p);
state->nextID++;
}
}
static void finishFrame(struct job* job)
{
struct state *state = job->state;
ZSTD_pthread_mutex_lock(&state->mutex);
addPending_inmutex(state, job);
flushPending_inmutex(state);
ZSTD_pthread_mutex_unlock(&state->mutex);
}
static void compressFrame(void* opaque)
{
struct job* job = opaque;
job->checksum = XXH64(job->src, job->srcSize, 0);
job->checksum = (unsigned)XXH64(job->src, job->srcSize, 0);
size_t ret = ZSTD_compress(job->dst, job->dstSize, job->src, job->srcSize, job->compressionLevel);
size_t ret = ZSTD_compress(job->dst, job->dstSize, job->src, job->srcSize, job->state->compressionLevel);
if (ZSTD_isError(ret)) {
fprintf(stderr, "ZSTD_compress() error : %s \n", ZSTD_getErrorName(ret));
exit(20);
}
job->dstSize = ret;
job->done = 1;
}
static void compressFile_orDie(const char* fname, const char* outName, int cLevel, unsigned frameSize, int nbThreads)
{
POOL_ctx* pool = POOL_create(nbThreads, nbThreads);
if (pool == NULL) { fprintf(stderr, "POOL_create() error \n"); exit(9); }
// No longer need
free(job->src);
job->src = NULL;
FILE* const fin = fopen_orDie(fname, "rb");
FILE* const fout = fopen_orDie(outName, "wb");
if (ZSTD_compressBound(frameSize) > 0xFFFFFFFFU) { fprintf(stderr, "Frame size too large \n"); exit(10); }
unsigned dstSize = ZSTD_compressBound(frameSize);
fseek_orDie(fin, 0, SEEK_END);
long int length = ftell_orDie(fin);
fseek_orDie(fin, 0, SEEK_SET);
size_t numFrames = (length + frameSize - 1) / frameSize;
struct job* jobs = malloc_orDie(sizeof(struct job) * numFrames);
size_t i;
for(i = 0; i < numFrames; i++) {
void* in = malloc_orDie(frameSize);
void* out = malloc_orDie(dstSize);
size_t inSize = fread_orDie(in, frameSize, fin);
jobs[i].src = in;
jobs[i].srcSize = inSize;
jobs[i].dst = out;
jobs[i].dstSize = dstSize;
jobs[i].compressionLevel = cLevel;
jobs[i].done = 0;
POOL_add(pool, compressFrame, &jobs[i]);
}
ZSTD_frameLog* fl = ZSTD_seekable_createFrameLog(1);
if (fl == NULL) { fprintf(stderr, "ZSTD_seekable_createFrameLog() failed \n"); exit(11); }
for (i = 0; i < numFrames; i++) {
while (!jobs[i].done) SLEEP(5); /* wake up every 5 milliseconds to check */
fwrite_orDie(jobs[i].dst, jobs[i].dstSize, fout);
free((void*)jobs[i].src);
free(jobs[i].dst);
size_t ret = ZSTD_seekable_logFrame(fl, jobs[i].dstSize, jobs[i].srcSize, jobs[i].checksum);
if (ZSTD_isError(ret)) { fprintf(stderr, "ZSTD_seekable_logFrame() error : %s \n", ZSTD_getErrorName(ret)); }
}
{ unsigned char seekTableBuff[1024];
ZSTD_outBuffer out = {seekTableBuff, 1024, 0};
while (ZSTD_seekable_writeSeekTable(fl, &out) != 0) {
fwrite_orDie(seekTableBuff, out.pos, fout);
out.pos = 0;
}
fwrite_orDie(seekTableBuff, out.pos, fout);
}
ZSTD_seekable_freeFrameLog(fl);
free(jobs);
fclose_orDie(fout);
fclose_orDie(fin);
finishFrame(job);
}
static const char* createOutFilename_orDie(const char* filename)
@ -193,6 +168,72 @@ static const char* createOutFilename_orDie(const char* filename)
return (const char*)outSpace;
}
static void openInOut_orDie(const char* fname, FILE** fin, FILE** fout) {
if (strcmp(fname, "-") == 0) {
*fin = stdin;
*fout = stdout;
} else {
*fin = fopen_orDie(fname, "rb");
const char* outName = createOutFilename_orDie(fname);
*fout = fopen_orDie(outName, "wb");
}
}
static void compressFile_orDie(const char* fname, int cLevel, unsigned frameSize, size_t nbThreads)
{
struct state state = {
.nextID = 0,
.pending = NULL,
.compressionLevel = cLevel,
};
ZSTD_pthread_mutex_init(&state.mutex, NULL);
state.frameLog = ZSTD_seekable_createFrameLog(1);
if (state.frameLog == NULL) { fprintf(stderr, "ZSTD_seekable_createFrameLog() failed \n"); exit(11); }
POOL_ctx* pool = POOL_create(nbThreads, nbThreads);
if (pool == NULL) { fprintf(stderr, "POOL_create() error \n"); exit(9); }
FILE* fin;
openInOut_orDie(fname, &fin, &state.fout);
if (ZSTD_compressBound(frameSize) > 0xFFFFFFFFU) { fprintf(stderr, "Frame size too large \n"); exit(10); }
size_t dstSize = ZSTD_compressBound(frameSize);
for (size_t id = 0; 1; id++) {
struct job* job = malloc_orDie(sizeof(struct job));
job->id = id;
job->next = NULL;
job->state = &state;
job->src = malloc_orDie(frameSize);
job->dst = malloc_orDie(dstSize);
job->srcSize = fread_orDie(job->src, frameSize, fin);
job->dstSize = dstSize;
POOL_add(pool, compressFrame, job);
if (feof(fin))
break;
}
POOL_joinJobs(pool);
POOL_free(pool);
if (state.pending) {
fprintf(stderr, "Unexpected leftover output blocks!\n");
exit(13);
}
{ unsigned char seekTableBuff[1024];
ZSTD_outBuffer out = {seekTableBuff, 1024, 0};
while (ZSTD_seekable_writeSeekTable(state.frameLog, &out) != 0) {
fwrite_orDie(seekTableBuff, out.pos, state.fout);
out.pos = 0;
}
fwrite_orDie(seekTableBuff, out.pos, state.fout);
}
ZSTD_seekable_freeFrameLog(state.frameLog);
fclose_orDie(state.fout);
fclose_orDie(fin);
}
int main(int argc, const char** argv) {
const char* const exeName = argv[0];
if (argc!=4) {
@ -204,10 +245,9 @@ int main(int argc, const char** argv) {
{ const char* const inFileName = argv[1];
unsigned const frameSize = (unsigned)atoi(argv[2]);
int const nbThreads = atoi(argv[3]);
size_t const nbThreads = (size_t)atoi(argv[3]);
const char* const outFileName = createOutFilename_orDie(inFileName);
compressFile_orDie(inFileName, outFileName, 5, frameSize, nbThreads);
compressFile_orDie(inFileName, 5, frameSize, nbThreads);
}
return 0;

View file

@ -100,13 +100,11 @@ struct sum_job {
const char* fname;
unsigned long long sum;
unsigned frameNb;
int done;
};
static void sumFrame(void* opaque)
{
struct sum_job* job = (struct sum_job*)opaque;
job->done = 0;
FILE* const fin = fopen_orDie(job->fname, "rb");
@ -128,7 +126,6 @@ static void sumFrame(void* opaque)
sum += data[i];
}
job->sum = sum;
job->done = 1;
fclose(fin);
ZSTD_seekable_free(seekable);
@ -153,14 +150,14 @@ static void sumFile_orDie(const char* fname, int nbThreads)
unsigned fnb;
for (fnb = 0; fnb < numFrames; fnb++) {
jobs[fnb] = (struct sum_job){ fname, 0, fnb, 0 };
jobs[fnb] = (struct sum_job){ fname, 0, fnb };
POOL_add(pool, sumFrame, &jobs[fnb]);
}
POOL_joinJobs(pool);
unsigned long long total = 0;
for (fnb = 0; fnb < numFrames; fnb++) {
while (!jobs[fnb].done) SLEEP(5); /* wake up every 5 milliseconds to check */
total += jobs[fnb].sum;
}

View file

@ -1 +1,2 @@
seekable_tests
data.txt

View file

@ -24,7 +24,7 @@ SEEKABLE_OBJS = ../zstdseek_compress.c ../zstdseek_decompress.c $(ZSTDLIB)
.PHONY: default clean test
default: test
test: seekable_tests
test: seekable_tests parallel_compression_test
./seekable_tests
$(ZSTDLIB):
@ -32,7 +32,27 @@ $(ZSTDLIB):
seekable_tests : $(SEEKABLE_OBJS)
EXAMPLES_PATH = ../examples
PARALLEL_COMPRESSION = $(EXAMPLES_PATH)/parallel_compression
DATAGEN_PATH = ../../../tests
DATAGEN = $(DATAGEN_PATH)/datagen
$(PARALLEL_COMPRESSION):
$(MAKE) -C $(EXAMPLES_PATH) parallel_compression
$(DATAGEN):
$(MAKE) -C $(DATAGEN_PATH) datagen
data.txt: $(DATAGEN)
$(DATAGEN) -g100M > $@
parallel_compression_test: $(PARALLEL_COMPRESSION) data.txt
ulimit -Sv 102400; $(PARALLEL_COMPRESSION) data.txt 1048576 2
.PHONY: parallel_compression_test parallel_comp
clean:
@$(RM) core *.o tmp* result* *.zst \
seekable_tests
seekable_tests data.txt
@echo Cleaning completed

View file

@ -316,6 +316,10 @@ int main(int argc, const char** argv)
for (pos = 0; pos < inSize; pos += 2) {
size_t const decStatus = ZSTD_seekable_decompress(stream, outBuffer, 1, pos);
if (decStatus != 1 || outBuffer[0] != inBuffer[pos]) {
free(seekBuffer);
free(outBuffer);
ZSTD_seekable_freeCStream(zscs);
ZSTD_seekable_free(stream);
goto _test_error;
}
}
@ -323,6 +327,10 @@ int main(int argc, const char** argv)
/* We read more than the compressed size, meaning there were some rereads.
This is unneeded because we only seeked forward. */
printf("Too much data read: %zu read, with compressed size %zu\n", buffWrapper.totalRead, seekSize);
free(seekBuffer);
free(outBuffer);
ZSTD_seekable_freeCStream(zscs);
ZSTD_seekable_free(stream);
goto _test_error;
}
@ -342,6 +350,10 @@ int main(int argc, const char** argv)
for (idx = 0; idx < sizeof(tests) / sizeof(tests[0]); idx++) {
size_t const decStatus = ZSTD_seekable_decompress(stream, outBuffer, tests[idx].size, tests[idx].offset);
if (decStatus != tests[idx].size || memcmp(outBuffer, inBuffer + tests[idx].offset, tests[idx].size) != 0) {
free(seekBuffer);
free(outBuffer);
ZSTD_seekable_freeCStream(zscs);
ZSTD_seekable_free(stream);
goto _test_error;
}
}

View file

@ -16,7 +16,7 @@ Distribution of this document is unlimited.
### Version
0.4.3 (2024-10-07)
0.4.5 (2026-05-14)
Introduction
@ -387,20 +387,24 @@ When `Block_Type` is `RLE_Block`, since `Block_Content`s size is always 1,
__`Block_Content`__ and __`Block_Maximum_Size`__
The size of `Block_Content` is limited by `Block_Maximum_Size`,
which is the smallest of:
The size of `Block_Content` is limited by `Block_Maximum_Size`, which is
determined once for a given frame and is the smallest of:
- `Window_Size`
- 128 KB
- 128 KiB (131.072 bytes)
`Block_Maximum_Size` is constant for a given frame.
This maximum is applicable to both the decompressed size
and the compressed size of any block in the frame.
Both the `Block_Content` and the decompressed size of any block in the frame must
be no larger than `Block_Maximum_Size`.
The reasoning for this limit is that a decoder can read this information
at the beginning of a frame and use it to allocate buffers.
The guarantees on the size of blocks ensure that
the buffers will be large enough for any following block of the valid frame.
If a compressed block is larger than its uncompressed content, it is recommended
to send it uncompressed (i.e., a `Raw_Block`). However, as long as
`Block_Content` is no larger than `Block_Maximum_Size`, it is legal to send such
a compressed block, even if it's larger than its uncompressed content.
Compressed Blocks
-----------------
@ -1742,6 +1746,8 @@ or at least provide a meaningful error code explaining for which reason it canno
Version changes
---------------
- 0.4.5 : minor clarification regarding Block_Maximum_Size
- 0.4.4 : minor clarification for block size
- 0.4.3 : clarifications for Huffman prefix code assignment example
- 0.4.2 : refactor FSE table construction process, inspired by Donald Pian
- 0.4.1 : clarifications on a few error scenarios, by Eric Lasota

View file

@ -110,6 +110,7 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
- ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
- ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small)
note 1 : a 0 return value means the frame is valid but "empty".
When invoking this method on a skippable frame, it will return 0.
note 2 : decompressed size is an optional field, it may not be present (typically in streaming mode).
When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.
In which case, it's necessary to use streaming mode to decompress data.
@ -128,9 +129,8 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
</p></pre><BR>
<pre><b>ZSTD_DEPRECATED("Replaced by ZSTD_getFrameContentSize")
ZSTDLIB_API
unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
</b><p> NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize().
</b><p> This function is now obsolete, in favor of ZSTD_getFrameContentSize().
Both functions work the same way, but ZSTD_getDecompressedSize() blends
"empty", "unknown" and "error" results to the same return value (0),
while ZSTD_getFrameContentSize() gives them separate return values.
@ -143,6 +143,11 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
@return : the compressed size of the first frame starting at `src`,
suitable to pass as `srcSize` to `ZSTD_decompress` or similar,
or an error code if input is invalid
Note 1: this method is called _find*() because it's not enough to read the header,
it may have to scan through the frame's content, to reach its end.
Note 2: this method also works with Skippable Frames. In which case,
it returns the size of the complete skippable frame,
which is always equal to its content size + 8 bytes for headers.
</p></pre><BR>
<h3>Compression helper functions</h3><pre></pre><b><pre></pre></b><BR>
@ -166,8 +171,7 @@ size_t ZSTD_compressBound(size_t srcSize); </b>/*!< maximum compressed size in w
</p></pre><BR>
<h3>Error helper functions</h3><pre></pre><b><pre>#include "zstd_errors.h" </b>/* list of errors */<b>
</b>/* ZSTD_isError() :<b>
<h3>Error helper functions</h3><pre></pre><b><pre></b>/* ZSTD_isError() :<b>
* Most ZSTD_* functions returning a size_t value can be tested for error,
* using ZSTD_isError().
* @return 1 if error, 0 otherwise
@ -1239,7 +1243,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
</p></pre><BR>
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
</b><p> srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
</b><p> srcSize must be large enough, aka >= ZSTD_FRAMEHEADERSIZE_PREFIX.
@return : size of the Frame Header,
or an error code (if srcSize is too small)
</p></pre><BR>
@ -1252,20 +1256,20 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
unsigned blockSizeMax;
ZSTD_FrameType_e frameType; </b>/* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */<b>
unsigned headerSize;
unsigned dictID;
unsigned dictID; </b>/* for ZSTD_skippableFrame, contains the skippable magic variant [0-15] */<b>
unsigned checksumFlag;
unsigned _reserved1;
unsigned _reserved2;
} ZSTD_frameHeader;
} ZSTD_FrameHeader;
</b></pre><BR>
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize); </b>/**< doesn't consume input */<b>
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize);
</b>/*! ZSTD_getFrameHeader_advanced() :<b>
* same as ZSTD_getFrameHeader(),
* with added capability to select a format (like ZSTD_f_zstd1_magicless) */
ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
</b><p> decode Frame Header, or requires larger `srcSize`.
@return : 0, `zfhPtr` is correctly filled,
>0, `srcSize` is too small, value is wanted `srcSize` amount,
</b><p> decode Frame Header into `zfhPtr`, or requires larger `srcSize`.
@return : 0 => header is complete, `zfhPtr` is correctly filled,
>0 => `srcSize` is too small, @return value is the wanted `srcSize` amount, `zfhPtr` is not filled,
or an error code, which can be tested using ZSTD_isError()
</p></pre><BR>
@ -1421,7 +1425,7 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx,
ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const ZSTD_Sequence* inSeqs, size_t nbSequences,
const void* literals, size_t litSize, size_t litCapacity,
const void* literals, size_t litSize, size_t litBufCapacity,
size_t decompressedSize);
</b><p> This is a variant of ZSTD_compressSequences() which,
instead of receiving (src,srcSize) as input parameter, receives (literals,litSize),
@ -1435,20 +1439,22 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,
- Not compatible with frame checksum, which must be disabled
- If any block is incompressible, will fail and return an error
- @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error.
- the buffer @literals must have a size @litCapacity which is larger than @litSize by at least 8 bytes.
- @litBufCapacity is the size of the underlying buffer into which literals are written, starting at address @literals.
@litBufCapacity must be at least 8 bytes larger than @litSize.
- @decompressedSize must be correct, and correspond to the sum of all Sequences. Any discrepancy will generate an error.
@return : final compressed size, or a ZSTD error code.
</p></pre><BR>
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
const void* src, size_t srcSize, unsigned magicVariant);
const void* src, size_t srcSize,
unsigned magicVariant);
</b><p> Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.
Skippable frames begin with a 4-byte magic number. There are 16 possible choices of magic number,
ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15.
As such, the parameter magicVariant controls the exact skippable frame magic number variant used, so
the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant.
As such, the parameter magicVariant controls the exact skippable frame magic number variant used,
so the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant.
Returns an error if destination buffer is not large enough, if the source size is not representable
with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid).
@ -1457,13 +1463,14 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,
</p></pre><BR>
<pre><b>size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,
unsigned* magicVariant,
const void* src, size_t srcSize);
</b><p> Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
</b><p> Retrieves the content of a zstd skippable frame starting at @src, and writes it to @dst buffer.
The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
in the magicVariant.
The parameter @magicVariant will receive the magicVariant that was supplied when the frame was written,
i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START.
This can be NULL if the caller is not interested in the magicVariant.
Returns an error if destination buffer is not large enough, or if the frame is not skippable.
@ -1471,7 +1478,7 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,
</p></pre><BR>
<pre><b>unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);
<pre><b>ZSTDLIB_STATIC_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);
</b><p> Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
</p></pre><BR>

View file

@ -57,7 +57,7 @@ cxx_library(
srcs=glob(['legacy/*.c']),
deps=[':common'],
exported_preprocessor_flags=[
'-DZSTD_LEGACY_SUPPORT=4',
'-DZSTD_LEGACY_SUPPORT=0',
],
)

View file

@ -128,7 +128,7 @@ $(ZSTD_STATICLIB): $(ZSTD_STATICLIB_OBJ)
$(AR) $(ARFLAGS) $@ $^
libzstd.a: $(ZSTD_STATICLIB)
cp -f $< $@
$(CP) $< $@
endif
@ -166,13 +166,13 @@ $(ZSTD_DYNLIB): $(ZSTD_DYNLIB_OBJ)
$(if $(filter -DZSTD_MULTITHREAD,$(CPPFLAGS)),\
@echo compiling multi-threaded dynamic library $(LIBVER),\
@echo compiling single-threaded dynamic library $(LIBVER))
$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@
$(CC) $(FLAGS) $^ $(SONAME_FLAGS) -o $@
@echo creating versioned links
ln -sf $@ libzstd.$(SHARED_EXT_MAJOR)
ln -sf $@ libzstd.$(SHARED_EXT)
$(LN) -sf $@ libzstd.$(SHARED_EXT_MAJOR)
$(LN) -sf $@ libzstd.$(SHARED_EXT)
$(LIBZSTD): $(ZSTD_DYNLIB)
cp -f $< $@
$(CP) $< $@
endif # ifndef BUILD_DIR
endif # if windows
@ -255,7 +255,7 @@ libzstd-nomt: $(ZSTD_NOMT_FILES)
echo "Error: Found zstdmt in list."; \
exit 1; \
fi
$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@
$(CC) $(FLAGS) $^ $(SONAME_FLAGS) -o $@
.PHONY: clean
clean:
@ -268,7 +268,7 @@ clean:
#-----------------------------------------------------------------------------
# make install is validated only for below listed environments
#-----------------------------------------------------------------------------
ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX MSYS_NT% CYGWIN_NT%,$(UNAME)))
ifneq (,$(filter $(INSTALL_OS_LIST),$(UNAME)))
lib: libzstd.pc
@ -363,8 +363,8 @@ install-shared:
[ -e $(DESTDIR)$(LIBDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)/
@echo Installing shared library
$(INSTALL_PROGRAM) $(LIBZSTD) $(DESTDIR)$(LIBDIR)
ln -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)
ln -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)
$(LN) -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)
$(LN) -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)
.PHONY: install-includes
install-includes:

View file

@ -7,15 +7,30 @@ in order to make it easier to select or exclude features.
#### Building
`Makefile` script is provided, supporting [Makefile conventions](https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html#Makefile-Conventions),
A `Makefile` script is provided, supporting [Makefile conventions](https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html#Makefile-Conventions),
including commands variables, staged install, directory variables and standard targets.
- `make` : generates both static and dynamic libraries
- `make install` : install libraries and headers in target system directories
- `make install` : install libraries, headers and pkg-config in local system directories
`libzstd` default scope is pretty large, including compression, decompression, dictionary builder,
and support for decoding legacy formats >= v0.5.0.
`libzstd` default scope includes compression, decompression, and dictionary builder.
Note: starting v1.6.0, support for decoding legacy formats is disabled by default.
See _modular build_ below to learn how to enable it.
The scope can be reduced on demand (see paragraph _modular build_).
#### Multiarch Support
For multiarch systems (like Debian/Ubuntu), libraries should be installed to architecture-specific directories.
When creating packages for such systems, use the `LIBDIR` variable to specify the correct multiarch path:
```bash
# For x86_64 systems on Ubuntu/Debian:
make install PREFIX=/usr LIBDIR=/usr/lib/x86_64-linux-gnu
# For ARM64 systems on Ubuntu/Debian:
make install PREFIX=/usr LIBDIR=/usr/lib/aarch64-linux-gnu
```
This will not only install the files in the correct directories, but also generate the correct paths for `pkg-config`.
#### Multithreading support
@ -85,7 +100,7 @@ The file structure is designed to make this selection manually achievable for an
Specifying a number limits versions supported to that version onward.
For example, `ZSTD_LEGACY_SUPPORT=2` means : "support legacy formats >= v0.2.0".
Conversely, `ZSTD_LEGACY_SUPPORT=0` means "do __not__ support legacy formats".
By default, this build macro is set as `ZSTD_LEGACY_SUPPORT=5`.
By default, this build macro is set as `ZSTD_LEGACY_SUPPORT=0` (disabled).
Decoding supported legacy format is a transparent capability triggered within decompression functions.
It's also allowed to invoke legacy API directly, exposed in `lib/legacy/zstd_legacy.h`.
Each version does also provide its own set of advanced API.
@ -193,6 +208,11 @@ The file structure is designed to make this selection manually achievable for an
and assembly decoding loops. You may want to use this macro if these loops are
slower on your platform.
- The macro `ZDICT_QSORT` can enforce selection of a specific sorting variant,
which is useful when autodetection fails, for example with older versions of `musl`.
For this scenario, it can be set as `ZDICT_QSORT=ZDICT_QSORT_C90`.
Other selectable suffixes are `_GNU`, `_APPLE`, `_MSVC` and `_C11`.
#### Windows : using MinGW+MSYS to create DLL
DLL can be created using MinGW+MSYS with the `make libzstd` command.

View file

@ -33,9 +33,13 @@ MEM_STATIC void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem)
MEM_STATIC void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem)
{
if (customMem.customAlloc) {
/* calloc implemented as malloc+memset;
* not as efficient as calloc, but next best guess for custom malloc */
/* calloc implemented as malloc+memset */
void* const ptr = customMem.customAlloc(customMem.opaque, size);
if (ptr == NULL) {
return NULL;
}
ZSTD_memset(ptr, 0, size);
return ptr;
}

View file

@ -21,7 +21,7 @@ MEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val)
30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7,
26, 12, 18, 6, 11, 5, 10, 9};
return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27];
return DeBruijnBytePos[((U32) ((val & (0-val)) * 0x077CB531U)) >> 27];
}
}

View file

@ -102,8 +102,8 @@ typedef enum { BIT_DStream_unfinished = 0, /* fully refilled */
} BIT_DStream_status; /* result of BIT_reloadDStream() */
MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
MEM_STATIC BitContainerType BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
FORCE_INLINE_TEMPLATE BitContainerType BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
FORCE_INLINE_TEMPLATE BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);

View file

@ -218,6 +218,18 @@
# if defined(__ARM_NEON) || defined(_M_ARM64)
# define ZSTD_ARCH_ARM_NEON
# endif
# if defined(__ARM_FEATURE_SVE)
# define ZSTD_ARCH_ARM_SVE
# endif
# if defined(__ARM_FEATURE_SVE2)
# define ZSTD_ARCH_ARM_SVE2
# endif
# if defined(__riscv) && defined(__riscv_vector)
# if ((defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 14) || \
(defined(__clang__) && __clang_major__ >= 19))
#define ZSTD_ARCH_RISCV_RVV
# endif
#endif
#
# if defined(ZSTD_ARCH_X86_AVX2)
# include <immintrin.h>
@ -227,6 +239,12 @@
# elif defined(ZSTD_ARCH_ARM_NEON)
# include <arm_neon.h>
# endif
# if defined(ZSTD_ARCH_ARM_SVE) || defined(ZSTD_ARCH_ARM_SVE2)
# include <arm_sve.h>
# endif
# if defined(ZSTD_ARCH_RISCV_RVV)
# include <riscv_vector.h>
# endif
#endif
/* C-language Attributes are added in C23. */
@ -357,9 +375,9 @@ ptrdiff_t ZSTD_wrappedPtrDiff(unsigned char const* lhs, unsigned char const* rhs
*/
MEM_STATIC
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
unsigned char const* ZSTD_wrappedPtrAdd(unsigned char const* ptr, ptrdiff_t add)
const void* ZSTD_wrappedPtrAdd(const void* ptr, ptrdiff_t add)
{
return ptr + add;
return (const char*)ptr + add;
}
/**
@ -370,9 +388,9 @@ unsigned char const* ZSTD_wrappedPtrAdd(unsigned char const* ptr, ptrdiff_t add)
*/
MEM_STATIC
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
unsigned char const* ZSTD_wrappedPtrSub(unsigned char const* ptr, ptrdiff_t sub)
const void* ZSTD_wrappedPtrSub(const void* ptr, ptrdiff_t sub)
{
return ptr - sub;
return (const char*)ptr - sub;
}
/**
@ -382,9 +400,9 @@ unsigned char const* ZSTD_wrappedPtrSub(unsigned char const* ptr, ptrdiff_t sub)
* @returns `ptr + add` except it defines `NULL + 0 == NULL`.
*/
MEM_STATIC
unsigned char* ZSTD_maybeNullPtrAdd(unsigned char* ptr, ptrdiff_t add)
void* ZSTD_maybeNullPtrAdd(void* ptr, ptrdiff_t add)
{
return add > 0 ? ptr + add : ptr;
return add > 0 ? (char*)ptr + add : ptr;
}
/* Issue #3240 reports an ASAN failure on an llvm-mingw build. Out of an

View file

@ -142,19 +142,17 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
/* Allocate space for the thread handles */
ctx->threads = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
ctx->threadCapacity = 0;
ctx->threadLimit = numThreads;
ctx->customMem = customMem;
/* Check for errors */
if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
/* Initialize the threads */
{ size_t i;
for (i = 0; i < numThreads; ++i) {
if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
ctx->threadCapacity = i;
while (ctx->threadCapacity < numThreads) {
if (ZSTD_pthread_create(&ctx->threads[ctx->threadCapacity++], NULL, &POOL_thread, ctx)) {
--ctx->threadCapacity;
POOL_free(ctx);
return NULL;
} }
ctx->threadCapacity = numThreads;
ctx->threadLimit = numThreads;
}
}
return ctx;
}
@ -220,23 +218,22 @@ static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)
return 0;
}
/* numThreads > threadCapacity */
ctx->threadLimit = numThreads;
{ ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
if (!threadPool) return 1;
/* replace existing thread pool */
/* extend existing thread pool */
ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(ZSTD_pthread_t));
ZSTD_customFree(ctx->threads, ctx->customMem);
ctx->threads = threadPool;
/* Initialize additional threads */
{ size_t threadId;
for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) {
if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) {
ctx->threadCapacity = threadId;
while (ctx->threadCapacity < numThreads) {
if (ZSTD_pthread_create(&threadPool[ctx->threadCapacity++], NULL, &POOL_thread, ctx)) {
--ctx->threadCapacity;
return 1;
} }
} }
}
}
}
/* successfully expanded */
ctx->threadCapacity = numThreads;
ctx->threadLimit = numThreads;
return 0;
}

View file

@ -168,4 +168,23 @@
# define ZSTD_CET_ENDBRANCH
#endif
/**
* ZSTD_IS_DETERMINISTIC_BUILD must be set to 0 if any compilation macro is
* active that impacts the compressed output.
*
* NOTE: ZSTD_MULTITHREAD is allowed to be set or unset.
*/
#if defined(ZSTD_CLEVEL_DEFAULT) \
|| defined(ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR) \
|| defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \
|| defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \
|| defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \
|| defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \
|| defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \
|| defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)
# define ZSTD_IS_DETERMINISTIC_BUILD 0
#else
# define ZSTD_IS_DETERMINISTIC_BUILD 1
#endif
#endif /* ZSTD_PORTABILITY_MACROS_H */

View file

@ -143,7 +143,14 @@ int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t con
*mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t));
if (!*mutex)
return 1;
return pthread_mutex_init(*mutex, attr);
{
int const ret = pthread_mutex_init(*mutex, attr);
if (ret != 0) {
ZSTD_free(*mutex);
*mutex = NULL;
}
return ret;
}
}
int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)
@ -164,7 +171,14 @@ int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const*
*cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t));
if (!*cond)
return 1;
return pthread_cond_init(*cond, attr);
{
int const ret = pthread_cond_init(*cond, attr);
if (ret != 0) {
ZSTD_free(*cond);
*cond = NULL;
}
return ret;
}
}
int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)

View file

@ -46,3 +46,12 @@ ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); }
/*! ZSTD_getErrorString() :
* provides error code string from enum */
const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString(code); }
int ZSTD_isDeterministicBuild(void)
{
#if ZSTD_IS_DETERMINISTIC_BUILD
return 1;
#else
return 0;
#endif
}

View file

@ -168,7 +168,7 @@ static UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
* Shared functions to include for inlining
*********************************************/
static void ZSTD_copy8(void* dst, const void* src) {
#if defined(ZSTD_ARCH_ARM_NEON)
#if defined(ZSTD_ARCH_ARM_NEON) && !defined(__aarch64__)
vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src));
#else
ZSTD_memcpy(dst, src, 8);
@ -185,6 +185,8 @@ static void ZSTD_copy16(void* dst, const void* src) {
vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src));
#elif defined(ZSTD_ARCH_X86_SSE2)
_mm_storeu_si128((__m128i*)dst, _mm_loadu_si128((const __m128i*)src));
#elif defined(ZSTD_ARCH_RISCV_RVV)
__riscv_vse8_v_u8m1((uint8_t*)dst, __riscv_vle8_v_u8m1((const uint8_t*)src, 16), 16);
#elif defined(__clang__)
ZSTD_memmove(dst, src, 16);
#else
@ -213,7 +215,7 @@ typedef enum {
* The src buffer must be before the dst buffer.
*/
MEM_STATIC FORCE_INLINE_ATTR
void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e const ovtype)
void ZSTD_wildcopy(void* dst, const void* src, size_t length, ZSTD_overlap_e const ovtype)
{
ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src;
const BYTE* ip = (const BYTE*)src;

View file

@ -19,6 +19,12 @@
#include "../common/error_private.h" /* ERROR */
#include "hist.h"
#if defined(ZSTD_ARCH_ARM_SVE2)
#define HIST_FAST_THRESHOLD 500
#else
#define HIST_FAST_THRESHOLD 1500
#endif
/* --- Error management --- */
unsigned HIST_isError(size_t code) { return ERR_isError(code); }
@ -65,6 +71,244 @@ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
typedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e;
#if defined(ZSTD_ARCH_ARM_SVE2)
FORCE_INLINE_TEMPLATE size_t min_size(size_t a, size_t b) { return a < b ? a : b; }
static
svuint16_t HIST_count_6_sve2(const BYTE* const src, size_t size, U32* const dst,
const svuint8_t c0, const svuint8_t c1,
const svuint8_t c2, const svuint8_t c3,
const svuint8_t c4, const svuint8_t c5,
const svuint16_t histmax, size_t maxCount)
{
const svbool_t vl128 = svptrue_pat_b8(SV_VL16);
svuint16_t hh0 = svdup_n_u16(0);
svuint16_t hh1 = svdup_n_u16(0);
svuint16_t hh2 = svdup_n_u16(0);
svuint16_t hh3 = svdup_n_u16(0);
svuint16_t hh4 = svdup_n_u16(0);
svuint16_t hh5 = svdup_n_u16(0);
svuint16_t hh6 = svdup_n_u16(0);
svuint16_t hh7 = svdup_n_u16(0);
svuint16_t hh8 = svdup_n_u16(0);
svuint16_t hh9 = svdup_n_u16(0);
svuint16_t hha = svdup_n_u16(0);
svuint16_t hhb = svdup_n_u16(0);
size_t i = 0;
while (i < size) {
/* We can only accumulate 15 (15 * 16 <= 255) iterations of histogram
* in 8-bit accumulators! */
const size_t size240 = min_size(i + 240, size);
svbool_t pred = svwhilelt_b8_u64(i, size);
svuint8_t c = svld1rq_u8(pred, src + i);
svuint8_t h0 = svhistseg_u8(c0, c);
svuint8_t h1 = svhistseg_u8(c1, c);
svuint8_t h2 = svhistseg_u8(c2, c);
svuint8_t h3 = svhistseg_u8(c3, c);
svuint8_t h4 = svhistseg_u8(c4, c);
svuint8_t h5 = svhistseg_u8(c5, c);
for (i += 16; i < size240; i += 16) {
pred = svwhilelt_b8_u64(i, size);
c = svld1rq_u8(pred, src + i);
h0 = svadd_u8_x(vl128, h0, svhistseg_u8(c0, c));
h1 = svadd_u8_x(vl128, h1, svhistseg_u8(c1, c));
h2 = svadd_u8_x(vl128, h2, svhistseg_u8(c2, c));
h3 = svadd_u8_x(vl128, h3, svhistseg_u8(c3, c));
h4 = svadd_u8_x(vl128, h4, svhistseg_u8(c4, c));
h5 = svadd_u8_x(vl128, h5, svhistseg_u8(c5, c));
}
hh0 = svaddwb_u16(hh0, h0);
hh1 = svaddwt_u16(hh1, h0);
hh2 = svaddwb_u16(hh2, h1);
hh3 = svaddwt_u16(hh3, h1);
hh4 = svaddwb_u16(hh4, h2);
hh5 = svaddwt_u16(hh5, h2);
hh6 = svaddwb_u16(hh6, h3);
hh7 = svaddwt_u16(hh7, h3);
hh8 = svaddwb_u16(hh8, h4);
hh9 = svaddwt_u16(hh9, h4);
hha = svaddwb_u16(hha, h5);
hhb = svaddwt_u16(hhb, h5);
}
svst1_u32(svwhilelt_b32_u64( 0, maxCount), dst + 0, svshllb_n_u32(hh0, 0));
svst1_u32(svwhilelt_b32_u64( 4, maxCount), dst + 4, svshllt_n_u32(hh0, 0));
svst1_u32(svwhilelt_b32_u64( 8, maxCount), dst + 8, svshllb_n_u32(hh1, 0));
svst1_u32(svwhilelt_b32_u64(12, maxCount), dst + 12, svshllt_n_u32(hh1, 0));
svst1_u32(svwhilelt_b32_u64(16, maxCount), dst + 16, svshllb_n_u32(hh2, 0));
svst1_u32(svwhilelt_b32_u64(20, maxCount), dst + 20, svshllt_n_u32(hh2, 0));
svst1_u32(svwhilelt_b32_u64(24, maxCount), dst + 24, svshllb_n_u32(hh3, 0));
svst1_u32(svwhilelt_b32_u64(28, maxCount), dst + 28, svshllt_n_u32(hh3, 0));
svst1_u32(svwhilelt_b32_u64(32, maxCount), dst + 32, svshllb_n_u32(hh4, 0));
svst1_u32(svwhilelt_b32_u64(36, maxCount), dst + 36, svshllt_n_u32(hh4, 0));
svst1_u32(svwhilelt_b32_u64(40, maxCount), dst + 40, svshllb_n_u32(hh5, 0));
svst1_u32(svwhilelt_b32_u64(44, maxCount), dst + 44, svshllt_n_u32(hh5, 0));
svst1_u32(svwhilelt_b32_u64(48, maxCount), dst + 48, svshllb_n_u32(hh6, 0));
svst1_u32(svwhilelt_b32_u64(52, maxCount), dst + 52, svshllt_n_u32(hh6, 0));
svst1_u32(svwhilelt_b32_u64(56, maxCount), dst + 56, svshllb_n_u32(hh7, 0));
svst1_u32(svwhilelt_b32_u64(60, maxCount), dst + 60, svshllt_n_u32(hh7, 0));
svst1_u32(svwhilelt_b32_u64(64, maxCount), dst + 64, svshllb_n_u32(hh8, 0));
svst1_u32(svwhilelt_b32_u64(68, maxCount), dst + 68, svshllt_n_u32(hh8, 0));
svst1_u32(svwhilelt_b32_u64(72, maxCount), dst + 72, svshllb_n_u32(hh9, 0));
svst1_u32(svwhilelt_b32_u64(76, maxCount), dst + 76, svshllt_n_u32(hh9, 0));
svst1_u32(svwhilelt_b32_u64(80, maxCount), dst + 80, svshllb_n_u32(hha, 0));
svst1_u32(svwhilelt_b32_u64(84, maxCount), dst + 84, svshllt_n_u32(hha, 0));
svst1_u32(svwhilelt_b32_u64(88, maxCount), dst + 88, svshllb_n_u32(hhb, 0));
svst1_u32(svwhilelt_b32_u64(92, maxCount), dst + 92, svshllt_n_u32(hhb, 0));
hh0 = svmax_u16_x(vl128, hh0, hh1);
hh2 = svmax_u16_x(vl128, hh2, hh3);
hh4 = svmax_u16_x(vl128, hh4, hh5);
hh6 = svmax_u16_x(vl128, hh6, hh7);
hh8 = svmax_u16_x(vl128, hh8, hh9);
hha = svmax_u16_x(vl128, hha, hhb);
hh0 = svmax_u16_x(vl128, hh0, hh2);
hh4 = svmax_u16_x(vl128, hh4, hh6);
hh8 = svmax_u16_x(vl128, hh8, hha);
hh0 = svmax_u16_x(vl128, hh0, hh4);
hh8 = svmax_u16_x(vl128, hh8, histmax);
return svmax_u16_x(vl128, hh0, hh8);
}
static size_t HIST_count_sve2(unsigned* count, unsigned* maxSymbolValuePtr,
const void* source, size_t sourceSize,
HIST_checkInput_e check)
{
const BYTE* ip = (const BYTE*)source;
const size_t maxCount = *maxSymbolValuePtr + 1;
assert(*maxSymbolValuePtr <= 255);
if (!sourceSize) {
ZSTD_memset(count, 0, maxCount * sizeof(*count));
*maxSymbolValuePtr = 0;
return 0;
}
{ const svbool_t vl128 = svptrue_pat_b8(SV_VL16);
const svuint8_t c0 = svreinterpret_u8(svindex_u32(0x0C040800, 0x01010101));
const svuint8_t c1 = svadd_n_u8_x(vl128, c0, 16);
const svuint8_t c2 = svadd_n_u8_x(vl128, c0, 32);
const svuint8_t c3 = svadd_n_u8_x(vl128, c1, 32);
svuint8_t symbolMax = svdup_n_u8(0);
svuint16_t hh0 = svdup_n_u16(0);
svuint16_t hh1 = svdup_n_u16(0);
svuint16_t hh2 = svdup_n_u16(0);
svuint16_t hh3 = svdup_n_u16(0);
svuint16_t hh4 = svdup_n_u16(0);
svuint16_t hh5 = svdup_n_u16(0);
svuint16_t hh6 = svdup_n_u16(0);
svuint16_t hh7 = svdup_n_u16(0);
svuint16_t max;
size_t maxSymbolValue;
size_t i = 0;
while (i < sourceSize) {
/* We can only accumulate 15 (15 * 16 <= 255) iterations of
* histogram in 8-bit accumulators! */
const size_t size240 = min_size(i + 240, sourceSize);
svbool_t pred = svwhilelt_b8_u64(i, sourceSize);
svuint8_t c = svld1rq_u8(pred, ip + i);
svuint8_t h0 = svhistseg_u8(c0, c);
svuint8_t h1 = svhistseg_u8(c1, c);
svuint8_t h2 = svhistseg_u8(c2, c);
svuint8_t h3 = svhistseg_u8(c3, c);
symbolMax = svmax_u8_x(vl128, symbolMax, c);
for (i += 16; i < size240; i += 16) {
pred = svwhilelt_b8_u64(i, sourceSize);
c = svld1rq_u8(pred, ip + i);
h0 = svadd_u8_x(vl128, h0, svhistseg_u8(c0, c));
h1 = svadd_u8_x(vl128, h1, svhistseg_u8(c1, c));
h2 = svadd_u8_x(vl128, h2, svhistseg_u8(c2, c));
h3 = svadd_u8_x(vl128, h3, svhistseg_u8(c3, c));
symbolMax = svmax_u8_x(vl128, symbolMax, c);
}
hh0 = svaddwb_u16(hh0, h0);
hh1 = svaddwt_u16(hh1, h0);
hh2 = svaddwb_u16(hh2, h1);
hh3 = svaddwt_u16(hh3, h1);
hh4 = svaddwb_u16(hh4, h2);
hh5 = svaddwt_u16(hh5, h2);
hh6 = svaddwb_u16(hh6, h3);
hh7 = svaddwt_u16(hh7, h3);
}
maxSymbolValue = svmaxv_u8(vl128, symbolMax);
if (check && maxSymbolValue > *maxSymbolValuePtr) return ERROR(maxSymbolValue_tooSmall);
*maxSymbolValuePtr = maxSymbolValue;
/* If the buffer size is not divisible by 16, the last elements of the final
* vector register read will be zeros, and these elements must be subtracted
* from the histogram.
*/
hh0 = svsub_n_u16_m(svptrue_pat_b32(SV_VL1), hh0, -sourceSize & 15);
svst1_u32(svwhilelt_b32_u64( 0, maxCount), count + 0, svshllb_n_u32(hh0, 0));
svst1_u32(svwhilelt_b32_u64( 4, maxCount), count + 4, svshllt_n_u32(hh0, 0));
svst1_u32(svwhilelt_b32_u64( 8, maxCount), count + 8, svshllb_n_u32(hh1, 0));
svst1_u32(svwhilelt_b32_u64(12, maxCount), count + 12, svshllt_n_u32(hh1, 0));
svst1_u32(svwhilelt_b32_u64(16, maxCount), count + 16, svshllb_n_u32(hh2, 0));
svst1_u32(svwhilelt_b32_u64(20, maxCount), count + 20, svshllt_n_u32(hh2, 0));
svst1_u32(svwhilelt_b32_u64(24, maxCount), count + 24, svshllb_n_u32(hh3, 0));
svst1_u32(svwhilelt_b32_u64(28, maxCount), count + 28, svshllt_n_u32(hh3, 0));
svst1_u32(svwhilelt_b32_u64(32, maxCount), count + 32, svshllb_n_u32(hh4, 0));
svst1_u32(svwhilelt_b32_u64(36, maxCount), count + 36, svshllt_n_u32(hh4, 0));
svst1_u32(svwhilelt_b32_u64(40, maxCount), count + 40, svshllb_n_u32(hh5, 0));
svst1_u32(svwhilelt_b32_u64(44, maxCount), count + 44, svshllt_n_u32(hh5, 0));
svst1_u32(svwhilelt_b32_u64(48, maxCount), count + 48, svshllb_n_u32(hh6, 0));
svst1_u32(svwhilelt_b32_u64(52, maxCount), count + 52, svshllt_n_u32(hh6, 0));
svst1_u32(svwhilelt_b32_u64(56, maxCount), count + 56, svshllb_n_u32(hh7, 0));
svst1_u32(svwhilelt_b32_u64(60, maxCount), count + 60, svshllt_n_u32(hh7, 0));
hh0 = svmax_u16_x(vl128, hh0, hh1);
hh2 = svmax_u16_x(vl128, hh2, hh3);
hh4 = svmax_u16_x(vl128, hh4, hh5);
hh6 = svmax_u16_x(vl128, hh6, hh7);
hh0 = svmax_u16_x(vl128, hh0, hh2);
hh4 = svmax_u16_x(vl128, hh4, hh6);
max = svmax_u16_x(vl128, hh0, hh4);
maxSymbolValue = min_size(maxSymbolValue, maxCount);
if (maxSymbolValue >= 64) {
const svuint8_t c4 = svadd_n_u8_x(vl128, c0, 64);
const svuint8_t c5 = svadd_n_u8_x(vl128, c1, 64);
const svuint8_t c6 = svadd_n_u8_x(vl128, c2, 64);
const svuint8_t c7 = svadd_n_u8_x(vl128, c3, 64);
const svuint8_t c8 = svadd_n_u8_x(vl128, c0, 128);
const svuint8_t c9 = svadd_n_u8_x(vl128, c1, 128);
max = HIST_count_6_sve2(ip, sourceSize, count + 64, c4, c5, c6, c7,
c8, c9, max, maxCount - 64);
if (maxSymbolValue >= 160) {
const svuint8_t ca = svadd_n_u8_x(vl128, c2, 128);
const svuint8_t cb = svadd_n_u8_x(vl128, c3, 128);
const svuint8_t cc = svadd_n_u8_x(vl128, c4, 128);
const svuint8_t cd = svadd_n_u8_x(vl128, c5, 128);
const svuint8_t ce = svadd_n_u8_x(vl128, c6, 128);
const svuint8_t cf = svadd_n_u8_x(vl128, c7, 128);
max = HIST_count_6_sve2(ip, sourceSize, count + 160, ca, cb, cc,
cd, ce, cf, max, maxCount - 160);
} else if (maxCount > 160) {
ZSTD_memset(count + 160, 0, (maxCount - 160) * sizeof(*count));
}
} else if (maxCount > 64) {
ZSTD_memset(count + 64, 0, (maxCount - 64) * sizeof(*count));
}
return svmaxv_u16(vl128, max);
}
}
#endif
/* HIST_count_parallel_wksp() :
* store histogram into 4 intermediate tables, recombined at the end.
* this design makes better use of OoO cpus,
@ -73,8 +317,8 @@ typedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e;
* `workSpace` must be a U32 table of size >= HIST_WKSP_SIZE_U32.
* @return : largest histogram frequency,
* or an error code (notably when histogram's alphabet is larger than *maxSymbolValuePtr) */
static size_t HIST_count_parallel_wksp(
unsigned* count, unsigned* maxSymbolValuePtr,
static UNUSED_ATTR
size_t HIST_count_parallel_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
const void* source, size_t sourceSize,
HIST_checkInput_e check,
U32* const workSpace)
@ -151,11 +395,17 @@ size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
const void* source, size_t sourceSize,
void* workSpace, size_t workSpaceSize)
{
if (sourceSize < 1500) /* heuristic threshold */
if (sourceSize < HIST_FAST_THRESHOLD) /* heuristic threshold */
return HIST_count_simple(count, maxSymbolValuePtr, source, sourceSize);
#if defined(ZSTD_ARCH_ARM_SVE2)
(void)workSpace;
(void)workSpaceSize;
return HIST_count_sve2(count, maxSymbolValuePtr, source, sourceSize, trustInput);
#else
if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);
return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace);
#endif
}
/* HIST_count_wksp() :
@ -165,10 +415,15 @@ size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
const void* source, size_t sourceSize,
void* workSpace, size_t workSpaceSize)
{
#if defined(ZSTD_ARCH_ARM_SVE2)
if (*maxSymbolValuePtr < 255)
return HIST_count_sve2(count, maxSymbolValuePtr, source, sourceSize, checkMaxSymbolValue);
#else
if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);
if (*maxSymbolValuePtr < 255)
return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, checkMaxSymbolValue, (U32*)workSpace);
#endif
*maxSymbolValuePtr = 255;
return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize);
}

View file

@ -35,7 +35,11 @@ unsigned HIST_isError(size_t code); /**< tells if a return value is an error co
/* --- advanced histogram functions --- */
#if defined(__ARM_FEATURE_SVE2)
#define HIST_WKSP_SIZE_U32 0
#else
#define HIST_WKSP_SIZE_U32 1024
#endif
#define HIST_WKSP_SIZE (HIST_WKSP_SIZE_U32 * sizeof(unsigned))
/** HIST_count_wksp() :
* Same as HIST_count(), but using an externally provided scratch buffer.

View file

@ -425,6 +425,7 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 targetNbBits
* gain back half the rank.
*/
U32 nBitsToDecrease = ZSTD_highbit32((U32)totalCost) + 1;
assert(nBitsToDecrease <= HUF_TABLELOG_MAX+1);
for ( ; nBitsToDecrease > 1; nBitsToDecrease--) {
U32 const highPos = rankLast[nBitsToDecrease];
U32 const lowPos = rankLast[nBitsToDecrease-1];

View file

@ -56,6 +56,14 @@
# define ZSTD_HASHLOG3_MAX 17
#endif
/*-*************************************
* Forward declarations
***************************************/
size_t convertSequences_noRepcodes(SeqDef* dstSeqs, const ZSTD_Sequence* inSeqs,
size_t nbSequences);
/*-*************************************
* Helper functions
***************************************/
@ -237,10 +245,18 @@ static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_Para
/* Returns row matchfinder usage given an initial mode and cParams */
static ZSTD_ParamSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_ParamSwitch_e mode,
const ZSTD_compressionParameters* const cParams) {
#ifdef ZSTD_LINUX_KERNEL
/* The Linux Kernel does not use SIMD, and 128KB is a very common size, e.g. in BtrFS.
* The row match finder is slower for this size without SIMD, so disable it.
*/
const unsigned kWindowLogLowerBound = 17;
#else
const unsigned kWindowLogLowerBound = 14;
#endif
if (mode != ZSTD_ps_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */
mode = ZSTD_ps_disable;
if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode;
if (cParams->windowLog > 14) mode = ZSTD_ps_enable;
if (cParams->windowLog > kWindowLogLowerBound) mode = ZSTD_ps_enable;
return mode;
}
@ -1755,15 +1771,19 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
ZSTD_compressionParameters const cParams =
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
ldmParams_t ldmParams = params->ldmParams;
ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder,
&cParams);
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
if (ldmParams.enableLdm == ZSTD_ps_enable) {
ZSTD_ldm_adjustParameters(&ldmParams, &cParams);
}
/* estimateCCtxSize is for one-shot compression. So no buffers should
* be needed. However, we still allocate two 0-sized buffers, which can
* take space under ASAN. */
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
&cParams, &params->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);
&cParams, &ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);
}
size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
@ -1813,6 +1833,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
{ ZSTD_compressionParameters const cParams =
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
ldmParams_t ldmParams = params->ldmParams;
size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), (size_t)1 << cParams.windowLog);
size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered)
? ((size_t)1 << cParams.windowLog) + blockSize
@ -1822,8 +1843,11 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
: 0;
ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, &params->cParams);
if (ldmParams.enableLdm == ZSTD_ps_enable) {
ZSTD_ldm_adjustParameters(&ldmParams, &cParams);
}
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
&cParams, &params->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,
&cParams, &ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,
ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);
}
}
@ -7110,7 +7134,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx,
}
#if defined(__AVX2__)
#if defined(ZSTD_ARCH_X86_AVX2)
#include <immintrin.h> /* AVX2 intrinsics */
@ -7130,7 +7154,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx,
* @returns > 0 if there is one long length (> 65535),
* indicating the position, and type.
*/
static size_t convertSequences_noRepcodes(
size_t convertSequences_noRepcodes(
SeqDef* dstSeqs,
const ZSTD_Sequence* inSeqs,
size_t nbSequences)
@ -7276,13 +7300,378 @@ static size_t convertSequences_noRepcodes(
return longLen;
}
#elif defined (ZSTD_ARCH_RISCV_RVV)
#include <riscv_vector.h>
/*
* Convert `vl` sequences per iteration, using RVV intrinsics:
* - offset -> offBase = offset + 2
* - litLength -> (U16) litLength
* - matchLength -> (U16)(matchLength - 3)
* - rep is ignored
* Store only 8 bytes per SeqDef (offBase[4], litLength[2], mlBase[2]).
*
* @returns 0 on succes, with no long length detected
* @returns > 0 if there is one long length (> 65535),
* indicating the position, and type.
*/
size_t convertSequences_noRepcodes(SeqDef* dstSeqs, const ZSTD_Sequence* inSeqs, size_t nbSequences) {
size_t longLen = 0;
size_t vl = 0;
typedef uint32_t __attribute__((may_alias)) aliased_u32;
/* RVV depends on the specific definition of target structures */
ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, offset) == 0);
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) == 4);
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);
ZSTD_STATIC_ASSERT(sizeof(SeqDef) == 8);
ZSTD_STATIC_ASSERT(offsetof(SeqDef, offBase) == 0);
ZSTD_STATIC_ASSERT(offsetof(SeqDef, litLength) == 4);
ZSTD_STATIC_ASSERT(offsetof(SeqDef, mlBase) == 6);
for (size_t i = 0; i < nbSequences; i += vl) {
vl = __riscv_vsetvl_e32m2(nbSequences-i);
{
// Loading structure member variables
vuint32m2x4_t v_tuple = __riscv_vlseg4e32_v_u32m2x4(
(const aliased_u32*)((const void*)&inSeqs[i]),
vl
);
vuint32m2_t v_offset = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 0);
vuint32m2_t v_lit = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 1);
vuint32m2_t v_match = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 2);
// offset + ZSTD_REP_NUM
vuint32m2_t v_offBase = __riscv_vadd_vx_u32m2(v_offset, ZSTD_REP_NUM, vl);
// Check for integer overflow
// Cast to a 16-bit variable
vbool16_t lit_overflow = __riscv_vmsgtu_vx_u32m2_b16(v_lit, 65535, vl);
vuint16m1_t v_lit_clamped = __riscv_vncvt_x_x_w_u16m1(v_lit, vl);
vbool16_t ml_overflow = __riscv_vmsgtu_vx_u32m2_b16(v_match, 65535+MINMATCH, vl);
vuint16m1_t v_ml_clamped = __riscv_vncvt_x_x_w_u16m1(__riscv_vsub_vx_u32m2(v_match, MINMATCH, vl), vl);
// Pack two 16-bit fields into a 32-bit value (little-endian)
// The lower 16 bits contain litLength, and the upper 16 bits contain mlBase
vuint32m2_t v_lit_ml_combined = __riscv_vsll_vx_u32m2(
__riscv_vwcvtu_x_x_v_u32m2(v_ml_clamped, vl), // Convert matchLength to 32-bit
16,
vl
);
v_lit_ml_combined = __riscv_vor_vv_u32m2(
v_lit_ml_combined,
__riscv_vwcvtu_x_x_v_u32m2(v_lit_clamped, vl),
vl
);
{
// Create a vector of SeqDef structures
// Store the offBase, litLength, and mlBase in a vector of SeqDef
vuint32m2x2_t store_data = __riscv_vcreate_v_u32m2x2(
v_offBase,
v_lit_ml_combined
);
__riscv_vsseg2e32_v_u32m2x2(
(aliased_u32*)((void*)&dstSeqs[i]),
store_data,
vl
);
}
{
// Find the first index where an overflow occurs
int first_ml = __riscv_vfirst_m_b16(ml_overflow, vl);
int first_lit = __riscv_vfirst_m_b16(lit_overflow, vl);
if (UNLIKELY(first_ml != -1)) {
assert(longLen == 0);
longLen = i + first_ml + 1;
}
if (UNLIKELY(first_lit != -1)) {
assert(longLen == 0);
longLen = i + first_lit + 1 + nbSequences;
}
}
}
}
return longLen;
}
/* the vector implementation could also be ported to SSSE3,
* but since this implementation is targeting modern systems (>= Sapphire Rapid),
* it's not useful to develop and maintain code for older pre-AVX2 platforms */
#else /* no AVX2 */
#elif defined(ZSTD_ARCH_ARM_SVE2)
static size_t convertSequences_noRepcodes(
/*
* Checks if any active element in a signed 8-bit integer vector is greater
* than zero.
*
* @param g Governing predicate selecting active lanes.
* @param a Input vector of signed 8-bit integers.
*
* @return True if any active element in `a` is > 0, false otherwise.
*/
FORCE_INLINE_TEMPLATE int cmpgtz_any_s8(svbool_t g, svint8_t a)
{
svbool_t ptest = svcmpgt_n_s8(g, a, 0);
return svptest_any(ptest, ptest);
}
size_t convertSequences_noRepcodes(
SeqDef* dstSeqs,
const ZSTD_Sequence* inSeqs,
size_t nbSequences)
{
/* Process the input with `8 * VL / element` lanes. */
const size_t lanes = 8 * svcntb() / sizeof(ZSTD_Sequence);
size_t longLen = 0;
size_t n = 0;
/* SVE permutation depends on the specific definition of target structures. */
ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, offset) == 0);
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) == 4);
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);
ZSTD_STATIC_ASSERT(sizeof(SeqDef) == 8);
ZSTD_STATIC_ASSERT(offsetof(SeqDef, offBase) == 0);
ZSTD_STATIC_ASSERT(offsetof(SeqDef, litLength) == 4);
ZSTD_STATIC_ASSERT(offsetof(SeqDef, mlBase) == 6);
if (nbSequences >= lanes) {
const svbool_t ptrue = svptrue_b8();
/* 16-bit of {ZSTD_REP_NUM, 0, -MINMATCH, 0} extended to 32-bit lanes. */
const svuint32_t vaddition = svreinterpret_u32(
svunpklo_s32(svreinterpret_s16(svdup_n_u64(ZSTD_REP_NUM | (((U64)(U16)-MINMATCH) << 32)))));
/* For permutation of 16-bit units: 0, 1, 2, 4, 8, 9, 10, 12, ... */
const svuint16_t vmask = svreinterpret_u16(
svindex_u64(0x0004000200010000, 0x0008000800080008));
/* Upper bytes of `litLength` and `matchLength` will be packed into the
* middle of overflow check vector. */
const svbool_t pmid = svcmpne_n_u8(
ptrue, svreinterpret_u8(svdup_n_u64(0x0000FFFFFFFF0000)), 0);
do {
/* Load `lanes` number of `ZSTD_Sequence` into 8 vectors. */
const svuint32_t vin0 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 0);
const svuint32_t vin1 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 1);
const svuint32_t vin2 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 2);
const svuint32_t vin3 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 3);
const svuint32_t vin4 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 4);
const svuint32_t vin5 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 5);
const svuint32_t vin6 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 6);
const svuint32_t vin7 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 7);
/* Add {ZSTD_REP_NUM, 0, -MINMATCH, 0} to each structures. */
const svuint16x2_t vadd01 = svcreate2_u16(
svreinterpret_u16(svadd_u32_x(ptrue, vin0, vaddition)),
svreinterpret_u16(svadd_u32_x(ptrue, vin1, vaddition)));
const svuint16x2_t vadd23 = svcreate2_u16(
svreinterpret_u16(svadd_u32_x(ptrue, vin2, vaddition)),
svreinterpret_u16(svadd_u32_x(ptrue, vin3, vaddition)));
const svuint16x2_t vadd45 = svcreate2_u16(
svreinterpret_u16(svadd_u32_x(ptrue, vin4, vaddition)),
svreinterpret_u16(svadd_u32_x(ptrue, vin5, vaddition)));
const svuint16x2_t vadd67 = svcreate2_u16(
svreinterpret_u16(svadd_u32_x(ptrue, vin6, vaddition)),
svreinterpret_u16(svadd_u32_x(ptrue, vin7, vaddition)));
/* Shuffle and pack bytes so each vector contains SeqDef structures. */
const svuint16_t vout01 = svtbl2_u16(vadd01, vmask);
const svuint16_t vout23 = svtbl2_u16(vadd23, vmask);
const svuint16_t vout45 = svtbl2_u16(vadd45, vmask);
const svuint16_t vout67 = svtbl2_u16(vadd67, vmask);
/* Pack the upper 16-bits of 32-bit lanes for overflow check. */
const svuint16_t voverflow01 = svuzp2_u16(svget2_u16(vadd01, 0),
svget2_u16(vadd01, 1));
const svuint16_t voverflow23 = svuzp2_u16(svget2_u16(vadd23, 0),
svget2_u16(vadd23, 1));
const svuint16_t voverflow45 = svuzp2_u16(svget2_u16(vadd45, 0),
svget2_u16(vadd45, 1));
const svuint16_t voverflow67 = svuzp2_u16(svget2_u16(vadd67, 0),
svget2_u16(vadd67, 1));
/* We don't need the whole 16 bits of the overflow part. Only 1 bit
* is needed, so we pack tightly and merge multiple vectors to be
* able to use a single comparison to handle the overflow case.
* However, we also need to handle the possible negative values of
* matchLength parts, so we use signed comparison later. */
const svint8_t voverflow =
svmax_s8_x(pmid,
svtrn1_s8(svreinterpret_s8(voverflow01),
svreinterpret_s8(voverflow23)),
svtrn1_s8(svreinterpret_s8(voverflow45),
svreinterpret_s8(voverflow67)));
/* Store `lanes` number of `SeqDef` structures from 4 vectors. */
svst1_vnum_u32(ptrue, &dstSeqs[n].offBase, 0, svreinterpret_u32(vout01));
svst1_vnum_u32(ptrue, &dstSeqs[n].offBase, 1, svreinterpret_u32(vout23));
svst1_vnum_u32(ptrue, &dstSeqs[n].offBase, 2, svreinterpret_u32(vout45));
svst1_vnum_u32(ptrue, &dstSeqs[n].offBase, 3, svreinterpret_u32(vout67));
/* Check if any enabled lanes of the overflow vector is larger than
* zero, only one such may happen. */
if (UNLIKELY(cmpgtz_any_s8(pmid, voverflow))) {
/* Scalar search for long match is needed because we merged
* multiple overflow bytes with `max`. */
size_t i;
for (i = n; i < n + lanes; i++) {
if (inSeqs[i].matchLength > 65535 + MINMATCH) {
assert(longLen == 0);
longLen = i + 1;
}
if (inSeqs[i].litLength > 65535) {
assert(longLen == 0);
longLen = i + nbSequences + 1;
}
}
}
n += lanes;
} while(n <= nbSequences - lanes);
}
/* Handle remaining elements. */
for (; n < nbSequences; n++) {
dstSeqs[n].offBase = OFFSET_TO_OFFBASE(inSeqs[n].offset);
dstSeqs[n].litLength = (U16)inSeqs[n].litLength;
dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH);
/* Check for long length > 65535. */
if (UNLIKELY(inSeqs[n].matchLength > 65535 + MINMATCH)) {
assert(longLen == 0);
longLen = n + 1;
}
if (UNLIKELY(inSeqs[n].litLength > 65535)) {
assert(longLen == 0);
longLen = n + nbSequences + 1;
}
}
return longLen;
}
#elif defined(ZSTD_ARCH_ARM_NEON) && (defined(__aarch64__) || defined(_M_ARM64))
size_t convertSequences_noRepcodes(
SeqDef* dstSeqs,
const ZSTD_Sequence* inSeqs,
size_t nbSequences)
{
size_t longLen = 0;
size_t n = 0;
/* Neon permutation depends on the specific definition of target structures. */
ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, offset) == 0);
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) == 4);
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);
ZSTD_STATIC_ASSERT(sizeof(SeqDef) == 8);
ZSTD_STATIC_ASSERT(offsetof(SeqDef, offBase) == 0);
ZSTD_STATIC_ASSERT(offsetof(SeqDef, litLength) == 4);
ZSTD_STATIC_ASSERT(offsetof(SeqDef, mlBase) == 6);
if (nbSequences > 3) {
static const ZSTD_ALIGNED(16) U32 constAddition[4] = {
ZSTD_REP_NUM, 0, -MINMATCH, 0
};
static const ZSTD_ALIGNED(16) U8 constMask[16] = {
0, 1, 2, 3, 4, 5, 8, 9, 16, 17, 18, 19, 20, 21, 24, 25
};
static const ZSTD_ALIGNED(16) U16 constCounter[8] = {
1, 1, 1, 1, 2, 2, 2, 2
};
const uint32x4_t vaddition = vld1q_u32(constAddition);
const uint8x16_t vmask = vld1q_u8(constMask);
uint16x8_t vcounter = vld1q_u16(constCounter);
uint16x8_t vindex01 = vdupq_n_u16(0);
uint16x8_t vindex23 = vdupq_n_u16(0);
do {
/* Load 4 ZSTD_Sequence (64 bytes). */
const uint32x4_t vin0 = vld1q_u32(&inSeqs[n + 0].offset);
const uint32x4_t vin1 = vld1q_u32(&inSeqs[n + 1].offset);
const uint32x4_t vin2 = vld1q_u32(&inSeqs[n + 2].offset);
const uint32x4_t vin3 = vld1q_u32(&inSeqs[n + 3].offset);
/* Add {ZSTD_REP_NUM, 0, -MINMATCH, 0} to each vector. */
const uint8x16x2_t vadd01 = { {
vreinterpretq_u8_u32(vaddq_u32(vin0, vaddition)),
vreinterpretq_u8_u32(vaddq_u32(vin1, vaddition)),
} };
const uint8x16x2_t vadd23 = { {
vreinterpretq_u8_u32(vaddq_u32(vin2, vaddition)),
vreinterpretq_u8_u32(vaddq_u32(vin3, vaddition)),
} };
/* Shuffle and pack bytes so each vector contains 2 SeqDef structures. */
const uint8x16_t vout01 = vqtbl2q_u8(vadd01, vmask);
const uint8x16_t vout23 = vqtbl2q_u8(vadd23, vmask);
/* Pack the upper 16-bits of 32-bit lanes for overflow check. */
uint16x8_t voverflow01 = vuzp2q_u16(vreinterpretq_u16_u8(vadd01.val[0]),
vreinterpretq_u16_u8(vadd01.val[1]));
uint16x8_t voverflow23 = vuzp2q_u16(vreinterpretq_u16_u8(vadd23.val[0]),
vreinterpretq_u16_u8(vadd23.val[1]));
/* Store 4 SeqDef structures. */
vst1q_u32(&dstSeqs[n + 0].offBase, vreinterpretq_u32_u8(vout01));
vst1q_u32(&dstSeqs[n + 2].offBase, vreinterpretq_u32_u8(vout23));
/* Create masks in case of overflow. */
voverflow01 = vcgtzq_s16(vreinterpretq_s16_u16(voverflow01));
voverflow23 = vcgtzq_s16(vreinterpretq_s16_u16(voverflow23));
/* Update overflow indices. */
vindex01 = vbslq_u16(voverflow01, vcounter, vindex01);
vindex23 = vbslq_u16(voverflow23, vcounter, vindex23);
/* Update counter for overflow check. */
vcounter = vaddq_u16(vcounter, vdupq_n_u16(4));
n += 4;
} while(n < nbSequences - 3);
/* Fixup indices in the second vector, we saved an additional counter
in the loop to update the second overflow index, we need to add 2
here when the indices are not 0. */
{ uint16x8_t nonzero = vtstq_u16(vindex23, vindex23);
vindex23 = vsubq_u16(vindex23, nonzero);
vindex23 = vsubq_u16(vindex23, nonzero);
}
/* Merge indices in the vectors, maximums are needed. */
vindex01 = vmaxq_u16(vindex01, vindex23);
vindex01 = vmaxq_u16(vindex01, vextq_u16(vindex01, vindex01, 4));
/* Compute `longLen`, maximums of matchLength and litLength
with a preference on litLength. */
{ U64 maxLitMatchIndices = vgetq_lane_u64(vreinterpretq_u64_u16(vindex01), 0);
size_t maxLitIndex = (maxLitMatchIndices >> 16) & 0xFFFF;
size_t maxMatchIndex = (maxLitMatchIndices >> 32) & 0xFFFF;
longLen = maxLitIndex > maxMatchIndex ? maxLitIndex + nbSequences
: maxMatchIndex;
}
}
/* Handle remaining elements. */
for (; n < nbSequences; n++) {
dstSeqs[n].offBase = OFFSET_TO_OFFBASE(inSeqs[n].offset);
dstSeqs[n].litLength = (U16)inSeqs[n].litLength;
dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH);
/* Check for long length > 65535. */
if (UNLIKELY(inSeqs[n].matchLength > 65535 + MINMATCH)) {
assert(longLen == 0);
longLen = n + 1;
}
if (UNLIKELY(inSeqs[n].litLength > 65535)) {
assert(longLen == 0);
longLen = n + nbSequences + 1;
}
}
return longLen;
}
#else /* No vectorization. */
size_t convertSequences_noRepcodes(
SeqDef* dstSeqs,
const ZSTD_Sequence* inSeqs,
size_t nbSequences)
@ -7293,7 +7682,7 @@ static size_t convertSequences_noRepcodes(
dstSeqs[n].offBase = OFFSET_TO_OFFBASE(inSeqs[n].offset);
dstSeqs[n].litLength = (U16)inSeqs[n].litLength;
dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH);
/* check for long length > 65535 */
/* Check for long length > 65535. */
if (UNLIKELY(inSeqs[n].matchLength > 65535+MINMATCH)) {
assert(longLen == 0);
longLen = n + 1;
@ -7443,34 +7832,172 @@ BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs)
}
}
#else
#elif defined (ZSTD_ARCH_RISCV_RVV)
BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs)
{
size_t totalMatchSize = 0;
size_t litSize = 0;
size_t n;
assert(seqs);
for (n=0; n<nbSeqs; n++) {
totalMatchSize += seqs[n].matchLength;
litSize += seqs[n].litLength;
if (seqs[n].matchLength == 0) {
assert(seqs[n].offset == 0);
size_t i = 0;
int found_terminator = 0;
size_t vl_max = __riscv_vsetvlmax_e32m1();
typedef uint32_t __attribute__((may_alias)) aliased_u32;
vuint32m1_t v_lit_sum = __riscv_vmv_v_x_u32m1(0, vl_max);
vuint32m1_t v_match_sum = __riscv_vmv_v_x_u32m1(0, vl_max);
for (; i < nbSeqs; ) {
size_t vl = __riscv_vsetvl_e32m2(nbSeqs - i);
vuint32m2x4_t v_tuple = __riscv_vlseg4e32_v_u32m2x4(
(const aliased_u32*)((const void*)&seqs[i]),
vl
);
vuint32m2_t v_lit = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 1);
vuint32m2_t v_match = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 2);
// Check if any element has a matchLength of 0
vbool16_t mask = __riscv_vmseq_vx_u32m2_b16(v_match, 0, vl);
int first_zero = __riscv_vfirst_m_b16(mask, vl);
if (first_zero >= 0) {
// Find the first zero byte and set the effective length to that index + 1 to
// recompute the cumulative vector length of literals and matches
vl = first_zero + 1;
// recompute the cumulative vector length of literals and matches
v_lit_sum = __riscv_vredsum_vs_u32m2_u32m1(__riscv_vslidedown_vx_u32m2(v_lit, 0, vl), v_lit_sum, vl);
v_match_sum = __riscv_vredsum_vs_u32m2_u32m1(__riscv_vslidedown_vx_u32m2(v_match, 0, vl), v_match_sum, vl);
i += vl;
found_terminator = 1;
assert(seqs[i - 1].offset == 0);
break;
} else {
v_lit_sum = __riscv_vredsum_vs_u32m2_u32m1(v_lit, v_lit_sum, vl);
v_match_sum = __riscv_vredsum_vs_u32m2_u32m1(v_match, v_match_sum, vl);
i += vl;
}
}
if (n==nbSeqs) {
litSize = __riscv_vmv_x_s_u32m1_u32(v_lit_sum);
totalMatchSize = __riscv_vmv_x_s_u32m1_u32(v_match_sum);
if (!found_terminator && i==nbSeqs) {
BlockSummary bs;
bs.nbSequences = ERROR(externalSequences_invalid);
return bs;
}
{ BlockSummary bs;
bs.nbSequences = n+1;
bs.nbSequences = i;
bs.blockSize = litSize + totalMatchSize;
bs.litSize = litSize;
return bs;
}
}
#else
/*
* The function assumes `litMatchLength` is a packed 64-bit value where the
* lower 32 bits represent the match length. The check varies based on the
* system's endianness:
* - On little-endian systems, it verifies if the entire 64-bit value is at most
* 0xFFFFFFFF, indicating the match length (lower 32 bits) is zero.
* - On big-endian systems, it directly checks if the lower 32 bits are zero.
*
* @returns 1 if the match length is zero, 0 otherwise.
*/
FORCE_INLINE_TEMPLATE int matchLengthHalfIsZero(U64 litMatchLength)
{
if (MEM_isLittleEndian()) {
return litMatchLength <= 0xFFFFFFFFULL;
} else {
return (U32)litMatchLength == 0;
}
}
BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs)
{
/* Use multiple accumulators for efficient use of wide out-of-order machines. */
U64 litMatchSize0 = 0;
U64 litMatchSize1 = 0;
U64 litMatchSize2 = 0;
U64 litMatchSize3 = 0;
size_t n = 0;
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) + 4 == offsetof(ZSTD_Sequence, matchLength));
ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) + 4 == offsetof(ZSTD_Sequence, rep));
assert(seqs);
if (nbSeqs > 3) {
/* Process the input in 4 independent streams to reach high throughput. */
do {
/* Load `litLength` and `matchLength` as a packed `U64`. It is safe
* to use 64-bit unsigned arithmetic here because the sum of `litLength`
* and `matchLength` cannot exceed the block size, so the 32-bit
* subparts will never overflow. */
U64 litMatchLength = MEM_read64(&seqs[n].litLength);
litMatchSize0 += litMatchLength;
if (matchLengthHalfIsZero(litMatchLength)) {
assert(seqs[n].offset == 0);
goto _out;
}
litMatchLength = MEM_read64(&seqs[n + 1].litLength);
litMatchSize1 += litMatchLength;
if (matchLengthHalfIsZero(litMatchLength)) {
n += 1;
assert(seqs[n].offset == 0);
goto _out;
}
litMatchLength = MEM_read64(&seqs[n + 2].litLength);
litMatchSize2 += litMatchLength;
if (matchLengthHalfIsZero(litMatchLength)) {
n += 2;
assert(seqs[n].offset == 0);
goto _out;
}
litMatchLength = MEM_read64(&seqs[n + 3].litLength);
litMatchSize3 += litMatchLength;
if (matchLengthHalfIsZero(litMatchLength)) {
n += 3;
assert(seqs[n].offset == 0);
goto _out;
}
n += 4;
} while(n < nbSeqs - 3);
}
for (; n < nbSeqs; n++) {
U64 litMatchLength = MEM_read64(&seqs[n].litLength);
litMatchSize0 += litMatchLength;
if (matchLengthHalfIsZero(litMatchLength)) {
assert(seqs[n].offset == 0);
goto _out;
}
}
/* At this point n == nbSeqs, so no end terminator. */
{ BlockSummary bs;
bs.nbSequences = ERROR(externalSequences_invalid);
return bs;
}
_out:
litMatchSize0 += litMatchSize1 + litMatchSize2 + litMatchSize3;
{ BlockSummary bs;
bs.nbSequences = n + 1;
if (MEM_isLittleEndian()) {
bs.litSize = (U32)litMatchSize0;
bs.blockSize = bs.litSize + (litMatchSize0 >> 32);
} else {
bs.litSize = litMatchSize0 >> 32;
bs.blockSize = bs.litSize + (U32)litMatchSize0;
}
return bs;
}
}
#endif

View file

@ -707,7 +707,7 @@ ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE con
{
assert(iend > ilimit_w);
if (ip <= ilimit_w) {
ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap);
ZSTD_wildcopy(op, ip, (size_t)(ilimit_w - ip), ZSTD_no_overlap);
op += ilimit_w - ip;
ip = ilimit_w;
}
@ -800,7 +800,7 @@ ZSTD_storeSeq(SeqStore_t* seqStorePtr,
ZSTD_STATIC_ASSERT(WILDCOPY_OVERLENGTH >= 16);
ZSTD_copy16(seqStorePtr->lit, literals);
if (litLength > 16) {
ZSTD_wildcopy(seqStorePtr->lit+16, literals+16, (ptrdiff_t)litLength-16, ZSTD_no_overlap);
ZSTD_wildcopy(seqStorePtr->lit+16, literals+16, litLength-16, ZSTD_no_overlap);
}
} else {
ZSTD_safecopyLiterals(seqStorePtr->lit, literals, litEnd, litLimit_w);
@ -1523,7 +1523,7 @@ typedef struct {
/* for benchmark */
size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx,
const ZSTD_Sequence* const inSeqs, size_t nbSequences,
int const repcodeResolution);
int repcodeResolution);
typedef struct {
size_t nbSequences;

View file

@ -1050,6 +1050,44 @@ ZSTD_row_getNEONMask(const U32 rowEntries, const BYTE* const src, const BYTE tag
}
}
#endif
#if defined(ZSTD_ARCH_RISCV_RVV) && (__riscv_xlen == 64)
FORCE_INLINE_TEMPLATE ZSTD_VecMask
ZSTD_row_getRVVMask(int rowEntries, const BYTE* const src, const BYTE tag, const U32 head)
{
ZSTD_VecMask matches;
size_t vl;
if (rowEntries == 16) {
vl = __riscv_vsetvl_e8m1(16);
{
vuint8m1_t chunk = __riscv_vle8_v_u8m1(src, vl);
vbool8_t mask = __riscv_vmseq_vx_u8m1_b8(chunk, tag, vl);
vuint16m1_t mask_u16 = __riscv_vreinterpret_v_b8_u16m1(mask);
matches = __riscv_vmv_x_s_u16m1_u16(mask_u16);
return ZSTD_rotateRight_U16((U16)matches, head);
}
} else if (rowEntries == 32) {
vl = __riscv_vsetvl_e8m2(32);
{
vuint8m2_t chunk = __riscv_vle8_v_u8m2(src, vl);
vbool4_t mask = __riscv_vmseq_vx_u8m2_b4(chunk, tag, vl);
vuint32m1_t mask_u32 = __riscv_vreinterpret_v_b4_u32m1(mask);
matches = __riscv_vmv_x_s_u32m1_u32(mask_u32);
return ZSTD_rotateRight_U32((U32)matches, head);
}
} else { // rowEntries = 64
vl = __riscv_vsetvl_e8m4(64);
{
vuint8m4_t chunk = __riscv_vle8_v_u8m4(src, vl);
vbool2_t mask = __riscv_vmseq_vx_u8m4_b2(chunk, tag, vl);
vuint64m1_t mask_u64 = __riscv_vreinterpret_v_b2_u64m1(mask);
matches = __riscv_vmv_x_s_u64m1_u64(mask_u64);
return ZSTD_rotateRight_U64(matches, head);
}
}
}
#endif
/* Returns a ZSTD_VecMask (U64) that has the nth group (determined by
* ZSTD_row_matchMaskGroupWidth) of bits set to 1 if the newly-computed "tag"
@ -1069,14 +1107,20 @@ ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 headGr
return ZSTD_row_getSSEMask(rowEntries / 16, src, tag, headGrouped);
#else /* SW or NEON-LE */
#elif defined(ZSTD_ARCH_RISCV_RVV) && (__riscv_xlen == 64)
return ZSTD_row_getRVVMask(rowEntries, src, tag, headGrouped);
#else
#if defined(ZSTD_ARCH_ARM_NEON)
/* This NEON path only works for little endian - otherwise use SWAR below */
if (MEM_isLittleEndian()) {
return ZSTD_row_getNEONMask(rowEntries, src, tag, headGrouped);
}
# endif /* ZSTD_ARCH_ARM_NEON */
#endif
/* SWAR */
{ const int chunkSize = sizeof(size_t);
const size_t shiftAmount = ((chunkSize * 8) - chunkSize);

View file

@ -152,8 +152,12 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params,
}
}
if (params->hashLog == 0) {
if (params->windowLog <= params->hashRateLog) {
params->hashLog = ZSTD_HASHLOG_MIN;
} else {
params->hashLog = BOUNDED(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog, ZSTD_HASHLOG_MAX);
}
}
if (params->minMatchLength == 0) {
params->minMatchLength = LDM_MIN_MATCH_LENGTH;
if (cParams->strategy >= ZSTD_btultra)

View file

@ -1382,16 +1382,8 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
assert(storeEnd < ZSTD_OPT_SIZE);
DEBUGLOG(6, "last stretch copied into pos=%u (llen=%u,mlen=%u,ofc=%u)",
storeEnd, lastStretch.litlen, lastStretch.mlen, lastStretch.off);
if (lastStretch.litlen > 0) {
/* last "sequence" is unfinished: just a bunch of literals */
opt[storeEnd].litlen = lastStretch.litlen;
opt[storeEnd].mlen = 0;
storeStart = storeEnd-1;
opt[storeStart] = lastStretch;
} {
opt[storeEnd] = lastStretch; /* note: litlen will be fixed */
storeStart = storeEnd;
}
while (1) {
ZSTD_optimal_t nextStretch = opt[stretchPos];
opt[storeStart].litlen = nextStretch.litlen;

View file

@ -1008,6 +1008,7 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
{
unsigned jobID;
DEBUGLOG(3, "ZSTDMT_releaseAllJobResources");
if (mtctx->jobs) {
for (jobID=0; jobID <= mtctx->jobIDMask; jobID++) {
/* Copy the mutex/cond out */
ZSTD_pthread_mutex_t const mutex = mtctx->jobs[jobID].job_mutex;
@ -1021,6 +1022,7 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
mtctx->jobs[jobID].job_mutex = mutex;
mtctx->jobs[jobID].job_cond = cond;
}
}
mtctx->inBuff.buffer = g_nullBuffer;
mtctx->inBuff.filled = 0;
mtctx->allJobsCompleted = 1;
@ -1268,8 +1270,7 @@ size_t ZSTDMT_initCStream_internal(
if (mtctx->allJobsCompleted == 0) { /* previous compression not correctly finished */
ZSTDMT_waitForAllJobsCompleted(mtctx);
ZSTDMT_releaseAllJobResources(mtctx);
mtctx->allJobsCompleted = 1;
ZSTDMT_releaseAllJobResources(mtctx); /* Will set allJobsCompleted to 1 */
}
mtctx->params = params;

View file

@ -15,6 +15,7 @@
/* **************************************************************
* Dependencies
****************************************************************/
#include <stddef.h> /* size_t */
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */
#include "../common/compiler.h"
#include "../common/bitstream.h" /* BIT_* */
@ -195,7 +196,7 @@ static size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* ds
const BYTE* const istart = (const BYTE*)src;
BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize);
BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);
/* The fast decoding loop assumes 64-bit little-endian.
* This condition is false on x32.
@ -578,7 +579,7 @@ HUF_decompress1X1_usingDTable_internal_body(
const HUF_DTable* DTable)
{
BYTE* op = (BYTE*)dst;
BYTE* const oend = ZSTD_maybeNullPtrAdd(op, dstSize);
BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(op, (ptrdiff_t)dstSize);
const void* dtPtr = DTable + 1;
const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
BIT_DStream_t bitD;
@ -786,17 +787,17 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
#define HUF_4X1_DECODE_SYMBOL(_stream, _symbol) \
do { \
int const index = (int)(bits[(_stream)] >> 53); \
int const entry = (int)dtable[index]; \
bits[(_stream)] <<= (entry & 0x3F); \
op[(_stream)][(_symbol)] = (BYTE)((entry >> 8) & 0xFF); \
U64 const index = bits[(_stream)] >> 53; \
U16 const entry = dtable[index]; \
bits[(_stream)] <<= entry & 0x3F; \
op[(_stream)][(_symbol)] = (BYTE)(entry >> 8); \
} while (0)
#define HUF_4X1_RELOAD_STREAM(_stream) \
#define HUF_5X1_RELOAD_STREAM(_stream) \
do { \
int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
int const nbBits = ctz & 7; \
int const nbBytes = ctz >> 3; \
U64 const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
U64 const nbBits = ctz & 7; \
U64 const nbBytes = ctz >> 3; \
op[(_stream)] += 5; \
ip[(_stream)] -= nbBytes; \
bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1; \
@ -815,11 +816,11 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 4);
/* Reload each of the 4 the bitstreams */
HUF_4X_FOR_EACH_STREAM(HUF_4X1_RELOAD_STREAM);
HUF_4X_FOR_EACH_STREAM(HUF_5X1_RELOAD_STREAM);
} while (op[3] < olimit);
#undef HUF_4X1_DECODE_SYMBOL
#undef HUF_4X1_RELOAD_STREAM
#undef HUF_5X1_RELOAD_STREAM
}
_out:
@ -845,7 +846,7 @@ HUF_decompress4X1_usingDTable_internal_fast(
{
void const* dt = DTable + 1;
BYTE const* const ilowest = (BYTE const*)cSrc;
BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize);
BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);
HUF_DecompressFastArgs args;
{ size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
FORWARD_IF_ERROR(ret, "Failed to init fast loop args");
@ -1362,7 +1363,7 @@ HUF_decompress1X2_usingDTable_internal_body(
/* decode */
{ BYTE* const ostart = (BYTE*) dst;
BYTE* const oend = ZSTD_maybeNullPtrAdd(ostart, dstSize);
BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)dstSize);
const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */
const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
DTableDesc const dtd = HUF_getDTableDesc(DTable);
@ -1605,54 +1606,62 @@ void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
#define HUF_4X2_DECODE_SYMBOL(_stream, _decode3) \
do { \
if ((_decode3) || (_stream) != 3) { \
int const index = (int)(bits[(_stream)] >> 53); \
HUF_DEltX2 const entry = dtable[index]; \
MEM_write16(op[(_stream)], entry.sequence); \
bits[(_stream)] <<= (entry.nbBits) & 0x3F; \
op[(_stream)] += (entry.length); \
U64 const index = bits[(_stream)] >> 53; \
size_t const entry = MEM_readLE32(&dtable[index]); \
MEM_write16(op[(_stream)], (U16)entry); \
bits[(_stream)] <<= (entry >> 16) & 0x3F; \
op[(_stream)] += entry >> 24; \
} \
} while (0)
#define HUF_4X2_RELOAD_STREAM(_stream) \
#define HUF_5X2_RELOAD_STREAM(_stream, _decode3) \
do { \
HUF_4X2_DECODE_SYMBOL(3, 1); \
if (_decode3) HUF_4X2_DECODE_SYMBOL(3, 1); \
{ \
int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
int const nbBits = ctz & 7; \
int const nbBytes = ctz >> 3; \
U64 const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
U64 const nbBits = ctz & 7; \
U64 const nbBytes = ctz >> 3; \
ip[(_stream)] -= nbBytes; \
bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1; \
bits[(_stream)] <<= nbBits; \
} \
} while (0)
#if defined(__aarch64__)
# define HUF_4X2_4WAY 1
#else
# define HUF_4X2_4WAY 0
#endif
#define HUF_4X2_3WAY !HUF_4X2_4WAY
/* Manually unroll the loop because compilers don't consistently
* unroll the inner loops, which destroys performance.
*/
do {
/* Decode 5 symbols from each of the first 3 streams.
* The final stream will be decoded during the reload phase
* to reduce register pressure.
/* Decode 5 symbols from each of the first 3 or 4 streams.
* In the 3-way case the final stream will be decoded during
* the reload phase to reduce register pressure.
*/
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
/* Decode one symbol from the final stream */
HUF_4X2_DECODE_SYMBOL(3, 1);
/* In the 3-way case decode one symbol from the final stream. */
HUF_4X2_DECODE_SYMBOL(3, HUF_4X2_3WAY);
/* Decode 4 symbols from the final stream & reload bitstreams.
* The final stream is reloaded last, meaning that all 5 symbols
* are decoded from the final stream before it is reloaded.
/* In the 3-way case decode 4 symbols from the final stream &
* reload bitstreams. The final stream is reloaded last, meaning
* that all 5 symbols are decoded from the final stream before
* it is reloaded.
*/
HUF_4X_FOR_EACH_STREAM(HUF_4X2_RELOAD_STREAM);
HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_5X2_RELOAD_STREAM, HUF_4X2_3WAY);
} while (op[3] < olimit);
}
#undef HUF_4X2_DECODE_SYMBOL
#undef HUF_4X2_RELOAD_STREAM
#undef HUF_5X2_RELOAD_STREAM
_out:
@ -1671,7 +1680,7 @@ HUF_decompress4X2_usingDTable_internal_fast(
HUF_DecompressFastLoopFn loopFn) {
void const* dt = DTable + 1;
const BYTE* const ilowest = (const BYTE*)cSrc;
BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize);
BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);
HUF_DecompressFastArgs args;
{
size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);

View file

@ -38,6 +38,16 @@
#endif
// There appears to be an unreconcilable syntax difference between Linux and Darwin assemblers.
// Name of a private label (i.e. not exported to symbol table) on Darwin has to start with "L",
// on Linux has to start with ".". There's no way to have a name start with both "." and "L", so
// we have to use a macro.
#if defined(__APPLE__)
#define LOCAL_LABEL(label) L_ ## label
#else
#define LOCAL_LABEL(label) .L_ ## label
#endif
#if ZSTD_ENABLE_ASM_X86_64_BMI2
/* Calling convention:
@ -117,22 +127,55 @@ ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_fast_asm_loop)
_HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
ZSTD_CET_ENDBRANCH
.cfi_startproc
.cfi_def_cfa_offset 8
.cfi_offset %rip, -8
/* Save all registers - even if they are callee saved for simplicity. */
push %rax
.cfi_def_cfa_offset 16
.cfi_offset rax, -16
push %rbx
.cfi_def_cfa_offset 24
.cfi_offset rbx, -24
push %rcx
.cfi_def_cfa_offset 32
.cfi_offset rcx, -32
push %rdx
.cfi_def_cfa_offset 40
.cfi_offset rdx, -40
push %rbp
.cfi_def_cfa_offset 48
.cfi_offset rbp, -48
push %rsi
.cfi_def_cfa_offset 56
.cfi_offset rsi, -56
push %rdi
.cfi_def_cfa_offset 64
.cfi_offset rdi, -64
push %r8
.cfi_def_cfa_offset 72
.cfi_offset r8, -72
push %r9
.cfi_def_cfa_offset 80
.cfi_offset r9, -80
push %r10
.cfi_def_cfa_offset 88
.cfi_offset r10, -88
push %r11
.cfi_def_cfa_offset 96
.cfi_offset r11, -96
push %r12
.cfi_def_cfa_offset 104
.cfi_offset r12, -104
push %r13
.cfi_def_cfa_offset 112
.cfi_offset r13, -112
push %r14
.cfi_def_cfa_offset 120
.cfi_offset r14, -120
push %r15
.cfi_def_cfa_offset 128
.cfi_offset r15, -128
/* Read HUF_DecompressAsmArgs* args from %rax */
#if defined(_WIN32)
@ -154,13 +197,18 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
movq 88(%rax), %bits3
movq 96(%rax), %dtable
push %rax /* argument */
.cfi_def_cfa_offset 136
push 104(%rax) /* ilowest */
.cfi_def_cfa_offset 144
push 112(%rax) /* oend */
.cfi_def_cfa_offset 152
push %olimit /* olimit space */
.cfi_def_cfa_offset 160
subq $24, %rsp
.cfi_def_cfa_offset 184
.L_4X1_compute_olimit:
LOCAL_LABEL(4X1_compute_olimit):
/* Computes how many iterations we can do safely
* %r15, %rax may be clobbered
* rbx, rdx must be saved
@ -207,19 +255,19 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
/* If (op3 + 20 > olimit) */
movq %op3, %rax /* rax = op3 */
cmpq %rax, %olimit /* op3 == olimit */
je .L_4X1_exit
je LOCAL_LABEL(4X1_exit)
/* If (ip1 < ip0) go to exit */
cmpq %ip0, %ip1
jb .L_4X1_exit
jb LOCAL_LABEL(4X1_exit)
/* If (ip2 < ip1) go to exit */
cmpq %ip1, %ip2
jb .L_4X1_exit
jb LOCAL_LABEL(4X1_exit)
/* If (ip3 < ip2) go to exit */
cmpq %ip2, %ip3
jb .L_4X1_exit
jb LOCAL_LABEL(4X1_exit)
/* Reads top 11 bits from bits[n]
* Loads dt[bits[n]] into var[n]
@ -280,7 +328,7 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
.p2align 6
.L_4X1_loop_body:
LOCAL_LABEL(4X1_loop_body):
/* Decode 5 symbols in each of the 4 streams (20 total)
* Must have called GET_NEXT_DELT for each stream
*/
@ -318,7 +366,7 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
/* If op3 < olimit: continue the loop */
cmp %op3, 24(%rsp)
ja .L_4X1_loop_body
ja LOCAL_LABEL(4X1_loop_body)
/* Reload ip[1,2,3] from stack */
movq 0(%rsp), %ip1
@ -326,20 +374,25 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
movq 16(%rsp), %ip3
/* Re-compute olimit */
jmp .L_4X1_compute_olimit
jmp LOCAL_LABEL(4X1_compute_olimit)
#undef GET_NEXT_DELT
#undef DECODE_FROM_DELT
#undef DECODE
#undef RELOAD_BITS
.L_4X1_exit:
LOCAL_LABEL(4X1_exit):
addq $24, %rsp
.cfi_def_cfa_offset 160
/* Restore stack (oend & olimit) */
pop %rax /* olimit */
.cfi_def_cfa_offset 152
pop %rax /* oend */
.cfi_def_cfa_offset 144
pop %rax /* ilowest */
.cfi_def_cfa_offset 136
pop %rax /* arg */
.cfi_def_cfa_offset 128
/* Save ip / op / bits */
movq %ip0, 0(%rax)
@ -357,41 +410,105 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
/* Restore registers */
pop %r15
.cfi_restore r15
.cfi_def_cfa_offset 120
pop %r14
.cfi_restore r14
.cfi_def_cfa_offset 112
pop %r13
.cfi_restore r13
.cfi_def_cfa_offset 104
pop %r12
.cfi_restore r12
.cfi_def_cfa_offset 96
pop %r11
.cfi_restore r11
.cfi_def_cfa_offset 88
pop %r10
.cfi_restore r10
.cfi_def_cfa_offset 80
pop %r9
.cfi_restore r9
.cfi_def_cfa_offset 72
pop %r8
.cfi_restore r8
.cfi_def_cfa_offset 64
pop %rdi
.cfi_restore rdi
.cfi_def_cfa_offset 56
pop %rsi
.cfi_restore rsi
.cfi_def_cfa_offset 48
pop %rbp
.cfi_restore rbp
.cfi_def_cfa_offset 40
pop %rdx
.cfi_restore rdx
.cfi_def_cfa_offset 32
pop %rcx
.cfi_restore rcx
.cfi_def_cfa_offset 24
pop %rbx
.cfi_restore rbx
.cfi_def_cfa_offset 16
pop %rax
.cfi_restore rax
.cfi_def_cfa_offset 8
ret
.cfi_endproc
_HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
ZSTD_CET_ENDBRANCH
.cfi_startproc
.cfi_def_cfa_offset 8
.cfi_offset %rip, -8
/* Save all registers - even if they are callee saved for simplicity. */
push %rax
.cfi_def_cfa_offset 16
.cfi_offset rax, -16
push %rbx
.cfi_def_cfa_offset 24
.cfi_offset rbx, -24
push %rcx
.cfi_def_cfa_offset 32
.cfi_offset rcx, -32
push %rdx
.cfi_def_cfa_offset 40
.cfi_offset rdx, -40
push %rbp
.cfi_def_cfa_offset 48
.cfi_offset rbp, -48
push %rsi
.cfi_def_cfa_offset 56
.cfi_offset rsi, -56
push %rdi
.cfi_def_cfa_offset 64
.cfi_offset rdi, -64
push %r8
.cfi_def_cfa_offset 72
.cfi_offset r8, -72
push %r9
.cfi_def_cfa_offset 80
.cfi_offset r9, -80
push %r10
.cfi_def_cfa_offset 88
.cfi_offset r10, -88
push %r11
.cfi_def_cfa_offset 96
.cfi_offset r11, -96
push %r12
.cfi_def_cfa_offset 104
.cfi_offset r12, -104
push %r13
.cfi_def_cfa_offset 112
.cfi_offset r13, -112
push %r14
.cfi_def_cfa_offset 120
.cfi_offset r14, -120
push %r15
.cfi_def_cfa_offset 128
.cfi_offset r15, -128
/* Read HUF_DecompressAsmArgs* args from %rax */
#if defined(_WIN32)
@ -413,25 +530,33 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
movq 88(%rax), %bits3
movq 96(%rax), %dtable
push %rax /* argument */
.cfi_def_cfa_offset 136
push %rax /* olimit */
.cfi_def_cfa_offset 144
push 104(%rax) /* ilowest */
.cfi_def_cfa_offset 152
movq 112(%rax), %rax
push %rax /* oend3 */
.cfi_def_cfa_offset 160
movq %op3, %rax
push %rax /* oend2 */
.cfi_def_cfa_offset 168
movq %op2, %rax
push %rax /* oend1 */
.cfi_def_cfa_offset 176
movq %op1, %rax
push %rax /* oend0 */
.cfi_def_cfa_offset 184
/* Scratch space */
subq $8, %rsp
.cfi_def_cfa_offset 192
.L_4X2_compute_olimit:
LOCAL_LABEL(4X2_compute_olimit):
/* Computes how many iterations we can do safely
* %r15, %rax may be clobbered
* rdx must be saved
@ -495,19 +620,19 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
/* If (op3 + 10 > olimit) */
movq %op3, %rax /* rax = op3 */
cmpq %rax, %olimit /* op3 == olimit */
je .L_4X2_exit
je LOCAL_LABEL(4X2_exit)
/* If (ip1 < ip0) go to exit */
cmpq %ip0, %ip1
jb .L_4X2_exit
jb LOCAL_LABEL(4X2_exit)
/* If (ip2 < ip1) go to exit */
cmpq %ip1, %ip2
jb .L_4X2_exit
jb LOCAL_LABEL(4X2_exit)
/* If (ip3 < ip2) go to exit */
cmpq %ip2, %ip3
jb .L_4X2_exit
jb LOCAL_LABEL(4X2_exit)
#define DECODE(n, idx) \
movq %bits##n, %rax; \
@ -534,7 +659,7 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
.p2align 6
.L_4X2_loop_body:
LOCAL_LABEL(4X2_loop_body):
/* We clobber r8, so store it on the stack */
movq %r8, 0(%rsp)
@ -551,21 +676,29 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
FOR_EACH_STREAM(RELOAD_BITS)
cmp %op3, 48(%rsp)
ja .L_4X2_loop_body
jmp .L_4X2_compute_olimit
ja LOCAL_LABEL(4X2_loop_body)
jmp LOCAL_LABEL(4X2_compute_olimit)
#undef DECODE
#undef RELOAD_BITS
.L_4X2_exit:
LOCAL_LABEL(4X2_exit):
addq $8, %rsp
.cfi_def_cfa_offset 184
/* Restore stack (oend & olimit) */
pop %rax /* oend0 */
.cfi_def_cfa_offset 176
pop %rax /* oend1 */
.cfi_def_cfa_offset 168
pop %rax /* oend2 */
.cfi_def_cfa_offset 160
pop %rax /* oend3 */
.cfi_def_cfa_offset 152
pop %rax /* ilowest */
.cfi_def_cfa_offset 144
pop %rax /* olimit */
.cfi_def_cfa_offset 136
pop %rax /* arg */
.cfi_def_cfa_offset 128
/* Save ip / op / bits */
movq %ip0, 0(%rax)
@ -583,20 +716,51 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
/* Restore registers */
pop %r15
.cfi_restore r15
.cfi_def_cfa_offset 120
pop %r14
.cfi_restore r14
.cfi_def_cfa_offset 112
pop %r13
.cfi_restore r13
.cfi_def_cfa_offset 104
pop %r12
.cfi_restore r12
.cfi_def_cfa_offset 96
pop %r11
.cfi_restore r11
.cfi_def_cfa_offset 88
pop %r10
.cfi_restore r10
.cfi_def_cfa_offset 80
pop %r9
.cfi_restore r9
.cfi_def_cfa_offset 72
pop %r8
.cfi_restore r8
.cfi_def_cfa_offset 64
pop %rdi
.cfi_restore rdi
.cfi_def_cfa_offset 56
pop %rsi
.cfi_restore rsi
.cfi_def_cfa_offset 48
pop %rbp
.cfi_restore rbp
.cfi_def_cfa_offset 40
pop %rdx
.cfi_restore rdx
.cfi_def_cfa_offset 32
pop %rcx
.cfi_restore rcx
.cfi_def_cfa_offset 24
pop %rbx
.cfi_restore rbx
.cfi_def_cfa_offset 16
pop %rax
.cfi_restore rax
.cfi_def_cfa_offset 8
ret
.cfi_endproc
#endif

View file

@ -16,14 +16,13 @@
*********************************************************/
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
#include "../common/compiler.h" /* prefetch */
#include "../common/cpu.h" /* bmi2 */
#include "../common/mem.h" /* low level memory routines */
#include <stddef.h>
#define FSE_STATIC_LINKING_ONLY
#include "../common/fse.h"
#include "../common/huf.h"
#include "../common/zstd_internal.h"
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
#include "zstd_decompress_block.h"
#include "../common/bits.h" /* ZSTD_highbit32 */
@ -734,9 +733,10 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
ip++;
/* Build DTables */
assert(ip <= iend);
{ size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
LLtype, MaxLL, LLFSELog,
ip, iend-ip,
ip, (size_t)(iend-ip),
LL_base, LL_bits,
LL_defaultDTable, dctx->fseEntropy,
dctx->ddictIsCold, nbSeq,
@ -746,9 +746,10 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
ip += llhSize;
}
assert(ip <= iend);
{ size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
OFtype, MaxOff, OffFSELog,
ip, iend-ip,
ip, (size_t)(iend-ip),
OF_base, OF_bits,
OF_defaultDTable, dctx->fseEntropy,
dctx->ddictIsCold, nbSeq,
@ -758,9 +759,10 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
ip += ofhSize;
}
assert(ip <= iend);
{ size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
MLtype, MaxML, MLFSELog,
ip, iend-ip,
ip, (size_t)(iend-ip),
ML_base, ML_bits,
ML_defaultDTable, dctx->fseEntropy,
dctx->ddictIsCold, nbSeq,
@ -771,7 +773,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
}
}
return ip-istart;
return (size_t)(ip-istart);
}
@ -801,7 +803,8 @@ typedef struct {
* Precondition: *ip <= *op
* Postcondition: *op - *op >= 8
*/
HINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) {
HINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset)
{
assert(*ip <= *op);
if (offset < 8) {
/* close range match, overlap */
@ -834,7 +837,9 @@ HINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) {
* - ZSTD_overlap_src_before_dst: The src and dst may overlap and may be any distance apart.
* The src buffer must be before the dst buffer.
*/
static void ZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, ptrdiff_t length, ZSTD_overlap_e ovtype) {
static void
ZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, size_t length, ZSTD_overlap_e ovtype)
{
ptrdiff_t const diff = op - ip;
BYTE* const oend = op + length;
@ -849,7 +854,8 @@ static void ZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, pt
if (ovtype == ZSTD_overlap_src_before_dst) {
/* Copy 8 bytes and ensure the offset >= 8 when there can be overlap. */
assert(length >= 8);
ZSTD_overlapCopy8(&op, &ip, diff);
assert(diff > 0);
ZSTD_overlapCopy8(&op, &ip, (size_t)diff);
length -= 8;
assert(op - ip >= 8);
assert(op <= oend);
@ -863,7 +869,7 @@ static void ZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, pt
if (op <= oend_w) {
/* Wildcopy until we get close to the end. */
assert(oend > oend_w);
ZSTD_wildcopy(op, ip, oend_w - op, ovtype);
ZSTD_wildcopy(op, ip, (size_t)(oend_w - op), ovtype);
ip += oend_w - op;
op += oend_w - op;
}
@ -874,7 +880,8 @@ static void ZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, pt
/* ZSTD_safecopyDstBeforeSrc():
* This version allows overlap with dst before src, or handles the non-overlap case with dst after src
* Kept separate from more common ZSTD_safecopy case to avoid performance impact to the safecopy common case */
static void ZSTD_safecopyDstBeforeSrc(BYTE* op, const BYTE* ip, ptrdiff_t length) {
static void ZSTD_safecopyDstBeforeSrc(BYTE* op, const BYTE* ip, size_t length)
{
ptrdiff_t const diff = op - ip;
BYTE* const oend = op + length;
@ -885,7 +892,7 @@ static void ZSTD_safecopyDstBeforeSrc(BYTE* op, const BYTE* ip, ptrdiff_t length
}
if (op <= oend - WILDCOPY_OVERLENGTH && diff < -WILDCOPY_VECLEN) {
ZSTD_wildcopy(op, ip, oend - WILDCOPY_OVERLENGTH - op, ZSTD_no_overlap);
ZSTD_wildcopy(op, ip, (size_t)(oend - WILDCOPY_OVERLENGTH - op), ZSTD_no_overlap);
ip += oend - WILDCOPY_OVERLENGTH - op;
op += oend - WILDCOPY_OVERLENGTH - op;
}
@ -936,7 +943,7 @@ size_t ZSTD_execSequenceEnd(BYTE* op,
return sequenceLength;
}
/* span extDict & currentPrefixSegment */
{ size_t const length1 = dictEnd - match;
{ size_t const length1 = (size_t)(dictEnd - match);
ZSTD_memmove(oLitEnd, match, length1);
op = oLitEnd + length1;
sequence.matchLength -= length1;
@ -985,7 +992,7 @@ size_t ZSTD_execSequenceEndSplitLitBuffer(BYTE* op,
return sequenceLength;
}
/* span extDict & currentPrefixSegment */
{ size_t const length1 = dictEnd - match;
{ size_t const length1 = (size_t)(dictEnd - match);
ZSTD_memmove(oLitEnd, match, length1);
op = oLitEnd + length1;
sequence.matchLength -= length1;
@ -1058,7 +1065,7 @@ size_t ZSTD_execSequence(BYTE* op,
return sequenceLength;
}
/* span extDict & currentPrefixSegment */
{ size_t const length1 = dictEnd - match;
{ size_t const length1 = (size_t)(dictEnd - match);
ZSTD_memmove(oLitEnd, match, length1);
op = oLitEnd + length1;
sequence.matchLength -= length1;
@ -1079,7 +1086,7 @@ size_t ZSTD_execSequence(BYTE* op,
* longer than literals (in general). In silesia, ~10% of matches are longer
* than 16 bytes.
*/
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap);
ZSTD_wildcopy(op, match, sequence.matchLength, ZSTD_no_overlap);
return sequenceLength;
}
assert(sequence.offset < WILDCOPY_VECLEN);
@ -1090,7 +1097,7 @@ size_t ZSTD_execSequence(BYTE* op,
/* If the match length is > 8 bytes, then continue with the wildcopy. */
if (sequence.matchLength > 8) {
assert(op < oMatchEnd);
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8, ZSTD_overlap_src_before_dst);
ZSTD_wildcopy(op, match, sequence.matchLength - 8, ZSTD_overlap_src_before_dst);
}
return sequenceLength;
}
@ -1151,7 +1158,7 @@ size_t ZSTD_execSequenceSplitLitBuffer(BYTE* op,
return sequenceLength;
}
/* span extDict & currentPrefixSegment */
{ size_t const length1 = dictEnd - match;
{ size_t const length1 = (size_t)(dictEnd - match);
ZSTD_memmove(oLitEnd, match, length1);
op = oLitEnd + length1;
sequence.matchLength -= length1;
@ -1171,7 +1178,7 @@ size_t ZSTD_execSequenceSplitLitBuffer(BYTE* op,
* longer than literals (in general). In silesia, ~10% of matches are longer
* than 16 bytes.
*/
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap);
ZSTD_wildcopy(op, match, sequence.matchLength, ZSTD_no_overlap);
return sequenceLength;
}
assert(sequence.offset < WILDCOPY_VECLEN);
@ -1182,7 +1189,7 @@ size_t ZSTD_execSequenceSplitLitBuffer(BYTE* op,
/* If the match length is > 8 bytes, then continue with the wildcopy. */
if (sequence.matchLength > 8) {
assert(op < oMatchEnd);
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst);
ZSTD_wildcopy(op, match, sequence.matchLength-8, ZSTD_overlap_src_before_dst);
}
return sequenceLength;
}
@ -1229,6 +1236,10 @@ FORCE_INLINE_TEMPLATE seq_t
ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const int isLastSeq)
{
seq_t seq;
#if defined(__aarch64__)
size_t prevOffset0 = seqState->prevOffset[0];
size_t prevOffset1 = seqState->prevOffset[1];
size_t prevOffset2 = seqState->prevOffset[2];
/*
* ZSTD_seqSymbol is a 64 bits wide structure.
* It can be loaded in one operation
@ -1237,7 +1248,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
* operations that cause performance drop. This can be avoided by using this
* ZSTD_memcpy hack.
*/
#if defined(__aarch64__) && (defined(__GNUC__) && !defined(__clang__))
# if defined(__GNUC__) && !defined(__clang__)
ZSTD_seqSymbol llDInfoS, mlDInfoS, ofDInfoS;
ZSTD_seqSymbol* const llDInfo = &llDInfoS;
ZSTD_seqSymbol* const mlDInfo = &mlDInfoS;
@ -1250,6 +1261,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
const ZSTD_seqSymbol* const mlDInfo = seqState->stateML.table + seqState->stateML.state;
const ZSTD_seqSymbol* const ofDInfo = seqState->stateOffb.table + seqState->stateOffb.state;
# endif
(void)longOffsets;
seq.matchLength = mlDInfo->baseValue;
seq.litLength = llDInfo->baseValue;
{ U32 const ofBase = ofDInfo->baseValue;
@ -1268,10 +1280,98 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
assert(llBits <= MaxLLBits);
assert(mlBits <= MaxMLBits);
assert(ofBits <= MaxOff);
/*
* As gcc has better branch and block analyzers, sometimes it is only
* valuable to mark likeliness for clang, it gives around 3-4% of
* performance.
/* As GCC has better branch and block analyzers, sometimes it is only
* valuable to mark likeliness for Clang.
*/
/* sequence */
{ size_t offset;
if (ofBits > 1) {
ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 > LONG_OFFSETS_MAX_EXTRA_BITS_32);
ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 - LONG_OFFSETS_MAX_EXTRA_BITS_32 >= MaxMLBits);
offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
prevOffset2 = prevOffset1;
prevOffset1 = prevOffset0;
prevOffset0 = offset;
} else {
U32 const ll0 = (llDInfo->baseValue == 0);
if (LIKELY((ofBits == 0))) {
if (ll0) {
offset = prevOffset1;
prevOffset1 = prevOffset0;
prevOffset0 = offset;
} else {
offset = prevOffset0;
}
} else {
offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1);
{ size_t temp = (offset == 1) ? prevOffset1
: (offset == 3) ? prevOffset0 - 1
: (offset >= 2) ? prevOffset2
: prevOffset0;
/* 0 is not valid: input corrupted => force offset to -1 =>
* corruption detected at execSequence.
*/
temp -= !temp;
prevOffset2 = (offset == 1) ? prevOffset2 : prevOffset1;
prevOffset1 = prevOffset0;
prevOffset0 = offset = temp;
} } }
seq.offset = offset;
}
if (mlBits > 0)
seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/);
if (UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
BIT_reloadDStream(&seqState->DStream);
/* Ensure there are enough bits to read the rest of data in 64-bit mode. */
ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
if (llBits > 0)
seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/);
DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
if (!isLastSeq) {
/* Don't update FSE state for last sequence. */
ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llNext, llnbBits); /* <= 9 bits */
ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlNext, mlnbBits); /* <= 9 bits */
ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofNext, ofnbBits); /* <= 8 bits */
BIT_reloadDStream(&seqState->DStream);
}
}
seqState->prevOffset[0] = prevOffset0;
seqState->prevOffset[1] = prevOffset1;
seqState->prevOffset[2] = prevOffset2;
#else /* !defined(__aarch64__) */
const ZSTD_seqSymbol* const llDInfo = seqState->stateLL.table + seqState->stateLL.state;
const ZSTD_seqSymbol* const mlDInfo = seqState->stateML.table + seqState->stateML.state;
const ZSTD_seqSymbol* const ofDInfo = seqState->stateOffb.table + seqState->stateOffb.state;
seq.matchLength = mlDInfo->baseValue;
seq.litLength = llDInfo->baseValue;
{ U32 const ofBase = ofDInfo->baseValue;
BYTE const llBits = llDInfo->nbAdditionalBits;
BYTE const mlBits = mlDInfo->nbAdditionalBits;
BYTE const ofBits = ofDInfo->nbAdditionalBits;
BYTE const totalBits = llBits+mlBits+ofBits;
U16 const llNext = llDInfo->nextState;
U16 const mlNext = mlDInfo->nextState;
U16 const ofNext = ofDInfo->nextState;
U32 const llnbBits = llDInfo->nbBits;
U32 const mlnbBits = mlDInfo->nbBits;
U32 const ofnbBits = ofDInfo->nbBits;
assert(llBits <= MaxLLBits);
assert(mlBits <= MaxMLBits);
assert(ofBits <= MaxOff);
/* As GCC has better branch and block analyzers, sometimes it is only
* valuable to mark likeliness for Clang.
*/
/* sequence */
@ -1333,7 +1433,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
if (!isLastSeq) {
/* don't update FSE state for last Sequence */
/* Don't update FSE state for last sequence. */
ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llNext, llnbBits); /* <= 9 bits */
ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlNext, mlnbBits); /* <= 9 bits */
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
@ -1341,6 +1441,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
BIT_reloadDStream(&seqState->DStream);
}
}
#endif /* defined(__aarch64__) */
return seq;
}
@ -1405,10 +1506,8 @@ ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,
const void* seqStart, size_t seqSize, int nbSeq,
const ZSTD_longOffset_e isLongOffset)
{
const BYTE* ip = (const BYTE*)seqStart;
const BYTE* const iend = ip + seqSize;
BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ZSTD_maybeNullPtrAdd(ostart, maxDstSize);
BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)maxDstSize);
BYTE* op = ostart;
const BYTE* litPtr = dctx->litPtr;
const BYTE* litBufferEnd = dctx->litBufferEnd;
@ -1423,7 +1522,7 @@ ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,
dctx->fseEntropy = 1;
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
RETURN_ERROR_IF(
ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
ERR_isError(BIT_initDStream(&seqState.DStream, seqStart, seqSize)),
corruption_detected, "");
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
@ -1515,7 +1614,8 @@ ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,
/* If there are more sequences, they will need to read literals from litExtraBuffer; copy over the remainder from dst and update litPtr and litEnd */
if (nbSeq > 0) {
const size_t leftoverLit = dctx->litBufferEnd - litPtr;
const size_t leftoverLit = (size_t)(dctx->litBufferEnd - litPtr);
assert(dctx->litBufferEnd >= litPtr);
DEBUGLOG(6, "There are %i sequences left, and %zu/%zu literals left in buffer", nbSeq, leftoverLit, sequence.litLength);
if (leftoverLit) {
RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer");
@ -1617,10 +1717,10 @@ ZSTD_decompressSequences_body(ZSTD_DCtx* dctx,
const void* seqStart, size_t seqSize, int nbSeq,
const ZSTD_longOffset_e isLongOffset)
{
const BYTE* ip = (const BYTE*)seqStart;
const BYTE* const iend = ip + seqSize;
BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = dctx->litBufferLocation == ZSTD_not_in_dst ? ZSTD_maybeNullPtrAdd(ostart, maxDstSize) : dctx->litBuffer;
BYTE* const oend = (dctx->litBufferLocation == ZSTD_not_in_dst) ?
(BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)maxDstSize) :
dctx->litBuffer;
BYTE* op = ostart;
const BYTE* litPtr = dctx->litPtr;
const BYTE* const litEnd = litPtr + dctx->litSize;
@ -1635,7 +1735,7 @@ ZSTD_decompressSequences_body(ZSTD_DCtx* dctx,
dctx->fseEntropy = 1;
{ U32 i; for (i = 0; i < ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
RETURN_ERROR_IF(
ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend - ip)),
ERR_isError(BIT_initDStream(&seqState.DStream, seqStart, seqSize)),
corruption_detected, "");
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
@ -1719,8 +1819,8 @@ size_t ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence,
{ const BYTE* const matchBase = (sequence.offset > prefetchPos) ? dictEnd : prefixStart;
/* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
* No consequence though : memory address is only used for prefetching, not for dereferencing */
const BYTE* const match = ZSTD_wrappedPtrSub(ZSTD_wrappedPtrAdd(matchBase, prefetchPos), sequence.offset);
PREFETCH_L1(match); PREFETCH_L1(match+CACHELINE_SIZE); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
const BYTE* const match = (const BYTE*)ZSTD_wrappedPtrSub(ZSTD_wrappedPtrAdd(matchBase, (ptrdiff_t)prefetchPos), (ptrdiff_t)sequence.offset);
PREFETCH_L1(match); PREFETCH_L1(ZSTD_wrappedPtrAdd(match, CACHELINE_SIZE)); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
}
return prefetchPos + sequence.matchLength;
}
@ -1736,10 +1836,10 @@ ZSTD_decompressSequencesLong_body(
const void* seqStart, size_t seqSize, int nbSeq,
const ZSTD_longOffset_e isLongOffset)
{
const BYTE* ip = (const BYTE*)seqStart;
const BYTE* const iend = ip + seqSize;
BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = dctx->litBufferLocation == ZSTD_in_dst ? dctx->litBuffer : ZSTD_maybeNullPtrAdd(ostart, maxDstSize);
BYTE* const oend = (dctx->litBufferLocation == ZSTD_in_dst) ?
dctx->litBuffer :
(BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)maxDstSize);
BYTE* op = ostart;
const BYTE* litPtr = dctx->litPtr;
const BYTE* litBufferEnd = dctx->litBufferEnd;
@ -1761,9 +1861,8 @@ ZSTD_decompressSequencesLong_body(
dctx->fseEntropy = 1;
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
assert(dst != NULL);
assert(iend >= ip);
RETURN_ERROR_IF(
ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
ERR_isError(BIT_initDStream(&seqState.DStream, seqStart, seqSize)),
corruption_detected, "");
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
@ -1782,9 +1881,9 @@ ZSTD_decompressSequencesLong_body(
if (dctx->litBufferLocation == ZSTD_split && litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength > dctx->litBufferEnd) {
/* lit buffer is reaching split point, empty out the first buffer and transition to litExtraBuffer */
const size_t leftoverLit = dctx->litBufferEnd - litPtr;
if (leftoverLit)
{
const size_t leftoverLit = (size_t)(dctx->litBufferEnd - litPtr);
assert(dctx->litBufferEnd >= litPtr);
if (leftoverLit) {
RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer");
ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength -= leftoverLit;
@ -1828,7 +1927,8 @@ ZSTD_decompressSequencesLong_body(
for ( ; seqNb<nbSeq ; seqNb++) {
seq_t *sequence = &(sequences[seqNb&STORED_SEQS_MASK]);
if (dctx->litBufferLocation == ZSTD_split && litPtr + sequence->litLength > dctx->litBufferEnd) {
const size_t leftoverLit = dctx->litBufferEnd - litPtr;
const size_t leftoverLit = (size_t)(dctx->litBufferEnd - litPtr);
assert(dctx->litBufferEnd >= litPtr);
if (leftoverLit) {
RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer");
ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
@ -1867,7 +1967,8 @@ ZSTD_decompressSequencesLong_body(
/* last literal segment */
if (dctx->litBufferLocation == ZSTD_split) { /* first deplete literal buffer in dst, then copy litExtraBuffer */
size_t const lastLLSize = litBufferEnd - litPtr;
size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);
assert(litBufferEnd >= litPtr);
RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, "");
if (op != NULL) {
ZSTD_memmove(op, litPtr, lastLLSize);
@ -1876,7 +1977,8 @@ ZSTD_decompressSequencesLong_body(
litPtr = dctx->litExtraBuffer;
litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
}
{ size_t const lastLLSize = litBufferEnd - litPtr;
{ size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);
assert(litBufferEnd >= litPtr);
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
if (op != NULL) {
ZSTD_memmove(op, litPtr, lastLLSize);
@ -1993,9 +2095,9 @@ ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
* both the prefix and the extDict. At @p op any offset larger than this
* is invalid.
*/
static size_t ZSTD_totalHistorySize(BYTE* op, BYTE const* virtualStart)
static size_t ZSTD_totalHistorySize(void* curPtr, const void* virtualStart)
{
return (size_t)(op - virtualStart);
return (size_t)((char*)curPtr - (const char*)virtualStart);
}
typedef struct {
@ -2094,7 +2196,7 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
* Additionally, take the min with dstCapacity to ensure that the totalHistorySize fits in a size_t.
*/
size_t const blockSizeMax = MIN(dstCapacity, ZSTD_blockSizeMax(dctx));
size_t const totalHistorySize = ZSTD_totalHistorySize(ZSTD_maybeNullPtrAdd((BYTE*)dst, blockSizeMax), (BYTE const*)dctx->virtualStart);
size_t const totalHistorySize = ZSTD_totalHistorySize(ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)blockSizeMax), (BYTE const*)dctx->virtualStart);
/* isLongOffset must be true if there are long offsets.
* Offsets are long if they are larger than ZSTD_maxShortOffset().
* We don't expect that to be the case in 64-bit mode.

View file

@ -21,14 +21,18 @@
/*-*************************************
* Dependencies
***************************************/
/* qsort_r is an extension. */
#if defined(__linux) || defined(__linux__) || defined(linux) || defined(__gnu_linux__) || \
defined(__CYGWIN__) || defined(__MSYS__)
#if !defined(_GNU_SOURCE) && !defined(__ANDROID__) /* NDK doesn't ship qsort_r(). */
/* qsort_r is an extension.
*
* Android NDK does not ship qsort_r().
*/
#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__) || defined(__MSYS__)
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
#endif
#define __STDC_WANT_LIB_EXT1__ 1 /* request C11 Annex K, which includes qsort_s() */
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* malloc, free, qsort_r */
@ -39,6 +43,7 @@
# define ZDICT_STATIC_LINKING_ONLY
#endif
#include "../common/debug.h" /* DEBUG_STATIC_ASSERT */
#include "../common/mem.h" /* read */
#include "../common/pool.h" /* POOL_ctx */
#include "../common/threading.h" /* ZSTD_pthread_mutex_t */
@ -60,40 +65,58 @@
#define COVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB))
#define COVER_DEFAULT_SPLITPOINT 1.0
/**
* Select the qsort() variant used by cover
*/
#define ZDICT_QSORT_MIN 0
#define ZDICT_QSORT_C90 ZDICT_QSORT_MIN
#define ZDICT_QSORT_GNU 1
#define ZDICT_QSORT_APPLE 2
#define ZDICT_QSORT_MSVC 3
#define ZDICT_QSORT_C11 ZDICT_QSORT_MAX
#define ZDICT_QSORT_MAX 4
#ifndef ZDICT_QSORT
# if defined(__APPLE__)
# define ZDICT_QSORT ZDICT_QSORT_APPLE /* uses qsort_r() with a different order for parameters */
# elif (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__) || defined(__MSYS__)
# define ZDICT_QSORT ZDICT_QSORT_GNU /* uses qsort_r() */
# elif defined(_WIN32) && defined(_MSC_VER)
# define ZDICT_QSORT ZDICT_QSORT_MSVC /* uses qsort_s() with a different order for parameters */
# elif defined(STDC_LIB_EXT1) && (STDC_LIB_EXT1 > 0) /* C11 Annex K */
# define ZDICT_QSORT ZDICT_QSORT_C11 /* uses qsort_s() */
# else
# define ZDICT_QSORT ZDICT_QSORT_C90 /* uses standard qsort() which is not re-entrant (requires global variable) */
# endif
#endif
/*-*************************************
* Console display
*
* Captures the `displayLevel` variable in the local scope.
***************************************/
#ifndef LOCALDISPLAYLEVEL
static int g_displayLevel = 0;
#endif
#undef DISPLAY
#define DISPLAY(...) \
{ \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
}
#undef LOCALDISPLAYLEVEL
#define LOCALDISPLAYLEVEL(displayLevel, l, ...) \
#undef DISPLAYLEVEL
#define DISPLAYLEVEL(l, ...) \
if (displayLevel >= l) { \
DISPLAY(__VA_ARGS__); \
} /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */
#undef DISPLAYLEVEL
#define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__)
#ifndef LOCALDISPLAYUPDATE
static const clock_t g_refreshRate = CLOCKS_PER_SEC * 15 / 100;
static clock_t g_time = 0;
#endif
#undef LOCALDISPLAYUPDATE
#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \
#undef DISPLAYUPDATE
#define DISPLAYUPDATE(lastUpdateTime, l, ...) \
if (displayLevel >= l) { \
if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \
g_time = clock(); \
const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100; \
if ((clock() - lastUpdateTime > refreshRate) || (displayLevel >= 4)) { \
lastUpdateTime = clock(); \
DISPLAY(__VA_ARGS__); \
} \
}
#undef DISPLAYUPDATE
#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__)
/*-*************************************
* Hash table
@ -239,10 +262,11 @@ typedef struct {
U32 *freqs;
U32 *dmerAt;
unsigned d;
int displayLevel;
} COVER_ctx_t;
#if !defined(_GNU_SOURCE) && !defined(__APPLE__) && !defined(_MSC_VER)
/* C90 only offers qsort() that needs a global context. */
#if ZDICT_QSORT == ZDICT_QSORT_C90
/* Use global context for non-reentrant sort functions */
static COVER_ctx_t *g_coverCtx = NULL;
#endif
@ -288,9 +312,9 @@ static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) {
/**
* Same as COVER_cmp() except ties are broken by pointer value
*/
#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__)
#if (ZDICT_QSORT == ZDICT_QSORT_MSVC) || (ZDICT_QSORT == ZDICT_QSORT_APPLE)
static int WIN_CDECL COVER_strict_cmp(void* g_coverCtx, const void* lp, const void* rp) {
#elif defined(_GNU_SOURCE)
#elif (ZDICT_QSORT == ZDICT_QSORT_GNU) || (ZDICT_QSORT == ZDICT_QSORT_C11)
static int COVER_strict_cmp(const void *lp, const void *rp, void *g_coverCtx) {
#else /* C90 fallback.*/
static int COVER_strict_cmp(const void *lp, const void *rp) {
@ -304,9 +328,9 @@ static int COVER_strict_cmp(const void *lp, const void *rp) {
/**
* Faster version for d <= 8.
*/
#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__)
#if (ZDICT_QSORT == ZDICT_QSORT_MSVC) || (ZDICT_QSORT == ZDICT_QSORT_APPLE)
static int WIN_CDECL COVER_strict_cmp8(void* g_coverCtx, const void* lp, const void* rp) {
#elif defined(_GNU_SOURCE)
#elif (ZDICT_QSORT == ZDICT_QSORT_GNU) || (ZDICT_QSORT == ZDICT_QSORT_C11)
static int COVER_strict_cmp8(const void *lp, const void *rp, void *g_coverCtx) {
#else /* C90 fallback.*/
static int COVER_strict_cmp8(const void *lp, const void *rp) {
@ -323,26 +347,28 @@ static int COVER_strict_cmp8(const void *lp, const void *rp) {
* Hopefully when C11 become the norm, we will be able
* to clean it up.
*/
static void stableSort(COVER_ctx_t *ctx) {
#if defined(__APPLE__)
static void stableSort(COVER_ctx_t *ctx)
{
DEBUG_STATIC_ASSERT(ZDICT_QSORT_MIN <= ZDICT_QSORT && ZDICT_QSORT <= ZDICT_QSORT_MAX);
#if (ZDICT_QSORT == ZDICT_QSORT_APPLE)
qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32),
ctx,
(ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp));
#elif defined(_GNU_SOURCE)
#elif (ZDICT_QSORT == ZDICT_QSORT_GNU)
qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32),
(ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp),
ctx);
#elif defined(_WIN32) && defined(_MSC_VER)
#elif (ZDICT_QSORT == ZDICT_QSORT_MSVC)
qsort_s(ctx->suffix, ctx->suffixSize, sizeof(U32),
(ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp),
ctx);
#elif (ZDICT_QSORT == ZDICT_QSORT_C11)
qsort_s(ctx->suffix, ctx->suffixSize, sizeof(U32),
(ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp),
ctx);
#elif defined(__OpenBSD__)
g_coverCtx = ctx;
mergesort(ctx->suffix, ctx->suffixSize, sizeof(U32),
(ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp));
#else /* C90 fallback.*/
g_coverCtx = ctx;
/* TODO(cavalcanti): implement a reentrant qsort() when is not available. */
/* TODO(cavalcanti): implement a reentrant qsort() when _r is not available. */
qsort(ctx->suffix, ctx->suffixSize, sizeof(U32),
(ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp));
#endif
@ -601,7 +627,7 @@ static void COVER_ctx_destroy(COVER_ctx_t *ctx) {
*/
static size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
const size_t *samplesSizes, unsigned nbSamples,
unsigned d, double splitPoint)
unsigned d, double splitPoint, int displayLevel)
{
const BYTE *const samples = (const BYTE *)samplesBuffer;
const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples);
@ -610,6 +636,7 @@ static size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
const unsigned nbTestSamples = splitPoint < 1.0 ? nbSamples - nbTrainSamples : nbSamples;
const size_t trainingSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes, nbTrainSamples) : totalSamplesSize;
const size_t testSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes + nbTrainSamples, nbTestSamples) : totalSamplesSize;
ctx->displayLevel = displayLevel;
/* Checks */
if (totalSamplesSize < MAX(d, sizeof(U64)) ||
totalSamplesSize >= (size_t)COVER_MAX_SAMPLES_SIZE) {
@ -694,7 +721,7 @@ void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLeve
if (ratio >= 10) {
return;
}
LOCALDISPLAYLEVEL(displayLevel, 1,
DISPLAYLEVEL(1,
"WARNING: The maximum dictionary size %u is too large "
"compared to the source size %u! "
"size(source)/size(dictionary) = %f, but it should be >= "
@ -736,6 +763,8 @@ static size_t COVER_buildDictionary(const COVER_ctx_t *ctx, U32 *freqs,
const size_t maxZeroScoreRun = MAX(10, MIN(100, epochs.num >> 3));
size_t zeroScoreRun = 0;
size_t epoch;
clock_t lastUpdateTime = 0;
const int displayLevel = ctx->displayLevel;
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
(U32)epochs.num, (U32)epochs.size);
/* Loop through the epochs until there are no more segments or the dictionary
@ -769,6 +798,7 @@ static size_t COVER_buildDictionary(const COVER_ctx_t *ctx, U32 *freqs,
tail -= segmentSize;
memcpy(dict + tail, ctx->samples + segment.begin, segmentSize);
DISPLAYUPDATE(
lastUpdateTime,
2, "\r%u%% ",
(unsigned)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity));
}
@ -784,9 +814,8 @@ ZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_cover(
BYTE* const dict = (BYTE*)dictBuffer;
COVER_ctx_t ctx;
COVER_map_t activeDmers;
const int displayLevel = (int)parameters.zParams.notificationLevel;
parameters.splitPoint = 1.0;
/* Initialize global data */
g_displayLevel = (int)parameters.zParams.notificationLevel;
/* Checks */
if (!COVER_checkParameters(parameters, dictBufferCapacity)) {
DISPLAYLEVEL(1, "Cover parameters incorrect\n");
@ -804,12 +833,12 @@ ZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_cover(
/* Initialize context and activeDmers */
{
size_t const initVal = COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples,
parameters.d, parameters.splitPoint);
parameters.d, parameters.splitPoint, displayLevel);
if (ZSTD_isError(initVal)) {
return initVal;
}
}
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, g_displayLevel);
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, displayLevel);
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
COVER_ctx_destroy(&ctx);
@ -1132,6 +1161,7 @@ static void COVER_tryParameters(void *opaque)
BYTE* const dict = (BYTE*)malloc(dictBufferCapacity);
COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC));
U32* const freqs = (U32*)malloc(ctx->suffixSize * sizeof(U32));
const int displayLevel = ctx->displayLevel;
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
goto _cleanup;
@ -1183,21 +1213,22 @@ ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover(
(1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize);
const unsigned shrinkDict = 0;
/* Local variables */
const int displayLevel = parameters->zParams.notificationLevel;
int displayLevel = (int)parameters->zParams.notificationLevel;
unsigned iteration = 1;
unsigned d;
unsigned k;
COVER_best_t best;
POOL_ctx *pool = NULL;
int warned = 0;
clock_t lastUpdateTime = 0;
/* Checks */
if (splitPoint <= 0 || splitPoint > 1) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect parameters\n");
DISPLAYLEVEL(1, "Incorrect parameters\n");
return ERROR(parameter_outOfBound);
}
if (kMinK < kMaxD || kMaxK < kMinK) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect parameters\n");
DISPLAYLEVEL(1, "Incorrect parameters\n");
return ERROR(parameter_outOfBound);
}
if (nbSamples == 0) {
@ -1217,19 +1248,19 @@ ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover(
}
/* Initialization */
COVER_best_init(&best);
/* Turn down global display level to clean up display at level 2 and below */
g_displayLevel = displayLevel == 0 ? 0 : displayLevel - 1;
/* Loop through d first because each new value needs a new context */
LOCALDISPLAYLEVEL(displayLevel, 2, "Trying %u different sets of parameters\n",
DISPLAYLEVEL(2, "Trying %u different sets of parameters\n",
kIterations);
for (d = kMinD; d <= kMaxD; d += 2) {
/* Initialize the context for this value of d */
COVER_ctx_t ctx;
LOCALDISPLAYLEVEL(displayLevel, 3, "d=%u\n", d);
DISPLAYLEVEL(3, "d=%u\n", d);
{
const size_t initVal = COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint);
/* Turn down global display level to clean up display at level 2 and below */
const int childDisplayLevel = (displayLevel == 0) ? 0 : displayLevel - 1;
const size_t initVal = COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint, childDisplayLevel);
if (ZSTD_isError(initVal)) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n");
DISPLAYLEVEL(1, "Failed to initialize context\n");
COVER_best_destroy(&best);
POOL_free(pool);
return initVal;
@ -1244,9 +1275,9 @@ ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover(
/* Prepare the arguments */
COVER_tryParameters_data_t *data = (COVER_tryParameters_data_t *)malloc(
sizeof(COVER_tryParameters_data_t));
LOCALDISPLAYLEVEL(displayLevel, 3, "k=%u\n", k);
DISPLAYLEVEL(3, "k=%u\n", k);
if (!data) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to allocate parameters\n");
DISPLAYLEVEL(1, "Failed to allocate parameters\n");
COVER_best_destroy(&best);
COVER_ctx_destroy(&ctx);
POOL_free(pool);
@ -1261,7 +1292,7 @@ ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover(
data->parameters.splitPoint = splitPoint;
data->parameters.steps = kSteps;
data->parameters.shrinkDict = shrinkDict;
data->parameters.zParams.notificationLevel = g_displayLevel;
data->parameters.zParams.notificationLevel = (unsigned)ctx.displayLevel;
/* Check the parameters */
if (!COVER_checkParameters(data->parameters, dictBufferCapacity)) {
DISPLAYLEVEL(1, "Cover parameters incorrect\n");
@ -1276,14 +1307,14 @@ ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover(
COVER_tryParameters(data);
}
/* Print status */
LOCALDISPLAYUPDATE(displayLevel, 2, "\r%u%% ",
DISPLAYUPDATE(lastUpdateTime, 2, "\r%u%% ",
(unsigned)((iteration * 100) / kIterations));
++iteration;
}
COVER_best_wait(&best);
COVER_ctx_destroy(&ctx);
}
LOCALDISPLAYLEVEL(displayLevel, 2, "\r%79s\r", "");
DISPLAYLEVEL(2, "\r%79s\r", "");
/* Fill the output buffer and parameters with output of the best parameters */
{
const size_t dictSize = best.dictSize;

View file

@ -25,23 +25,22 @@
*/
/*- Compiler specifics -*/
#ifdef __clang__
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
#endif
#if defined(_MSC_VER)
# pragma warning(disable : 4244)
# pragma warning(disable : 4127) /* C4127 : Condition expression is constant */
#endif
/*- Dependencies -*/
#include <assert.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include "divsufsort.h"
#define PTRDIFF_TO_INT(x) (assert((x) <= INT_MAX && (x) >= INT_MIN), (int)(x))
/*- Constants -*/
#if defined(INLINE)
# undef INLINE
@ -199,8 +198,8 @@ ss_isqrt(int x) {
int y, e;
if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; }
e = (x & 0xffff0000) ?
((x & 0xff000000) ?
e = ((unsigned)x & 0xffff0000) ?
(((unsigned)x & 0xff000000) ?
24 + lg_table[(x >> 24) & 0xff] :
16 + lg_table[(x >> 16) & 0xff]) :
((x & 0x0000ff00) ?
@ -354,7 +353,7 @@ ss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) {
int *middle;
int t;
t = last - first;
t = PTRDIFF_TO_INT(last - first);
middle = first + t / 2;
if(t <= 512) {
@ -409,7 +408,7 @@ ss_mintrosort(const unsigned char *T, const int *PA,
int limit;
int v, x = 0;
for(ssize = 0, limit = ss_ilg(last - first);;) {
for(ssize = 0, limit = ss_ilg(PTRDIFF_TO_INT(last - first));;) {
if((last - first) <= SS_INSERTIONSORT_THRESHOLD) {
#if 1 < SS_INSERTIONSORT_THRESHOLD
@ -420,7 +419,7 @@ ss_mintrosort(const unsigned char *T, const int *PA,
}
Td = T + depth;
if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); }
if(limit-- == 0) { ss_heapsort(Td, PA, first, PTRDIFF_TO_INT(last - first)); }
if(limit < 0) {
for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) {
if((x = Td[PA[*a]]) != v) {
@ -435,16 +434,16 @@ ss_mintrosort(const unsigned char *T, const int *PA,
if((a - first) <= (last - a)) {
if(1 < (a - first)) {
STACK_PUSH(a, last, depth, -1);
last = a, depth += 1, limit = ss_ilg(a - first);
last = a, depth += 1, limit = ss_ilg(PTRDIFF_TO_INT(a - first));
} else {
first = a, limit = -1;
}
} else {
if(1 < (last - a)) {
STACK_PUSH(first, a, depth + 1, ss_ilg(a - first));
STACK_PUSH(first, a, depth + 1, ss_ilg(PTRDIFF_TO_INT(a - first)));
first = a, limit = -1;
} else {
last = a, depth += 1, limit = ss_ilg(a - first);
last = a, depth += 1, limit = ss_ilg(PTRDIFF_TO_INT(a - first));
}
}
continue;
@ -481,9 +480,9 @@ ss_mintrosort(const unsigned char *T, const int *PA,
if(a <= d) {
c = b - 1;
if((s = a - first) > (t = b - a)) { s = t; }
if((s = PTRDIFF_TO_INT(a - first)) > (t = PTRDIFF_TO_INT(b - a))) { s = t; }
for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
if((s = d - c) > (t = last - d - 1)) { s = t; }
if((s = PTRDIFF_TO_INT(d - c)) > (t = PTRDIFF_TO_INT(last - d - 1))) { s = t; }
for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
a = first + (b - a), c = last - (d - c);
@ -491,38 +490,38 @@ ss_mintrosort(const unsigned char *T, const int *PA,
if((a - first) <= (last - c)) {
if((last - c) <= (c - b)) {
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
STACK_PUSH(b, c, depth + 1, ss_ilg(PTRDIFF_TO_INT(c - b)));
STACK_PUSH(c, last, depth, limit);
last = a;
} else if((a - first) <= (c - b)) {
STACK_PUSH(c, last, depth, limit);
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
STACK_PUSH(b, c, depth + 1, ss_ilg(PTRDIFF_TO_INT(c - b)));
last = a;
} else {
STACK_PUSH(c, last, depth, limit);
STACK_PUSH(first, a, depth, limit);
first = b, last = c, depth += 1, limit = ss_ilg(c - b);
first = b, last = c, depth += 1, limit = ss_ilg(PTRDIFF_TO_INT(c - b));
}
} else {
if((a - first) <= (c - b)) {
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
STACK_PUSH(b, c, depth + 1, ss_ilg(PTRDIFF_TO_INT(c - b)));
STACK_PUSH(first, a, depth, limit);
first = c;
} else if((last - c) <= (c - b)) {
STACK_PUSH(first, a, depth, limit);
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
STACK_PUSH(b, c, depth + 1, ss_ilg(PTRDIFF_TO_INT(c - b)));
first = c;
} else {
STACK_PUSH(first, a, depth, limit);
STACK_PUSH(c, last, depth, limit);
first = b, last = c, depth += 1, limit = ss_ilg(c - b);
first = b, last = c, depth += 1, limit = ss_ilg(PTRDIFF_TO_INT(c - b));
}
}
} else {
limit += 1;
if(Td[PA[*first] - 1] < v) {
first = ss_partition(PA, first, last, depth);
limit = ss_ilg(last - first);
limit = ss_ilg(PTRDIFF_TO_INT(last - first));
}
depth += 1;
}
@ -551,7 +550,8 @@ void
ss_rotate(int *first, int *middle, int *last) {
int *a, *b, t;
int l, r;
l = middle - first, r = last - middle;
l = PTRDIFF_TO_INT(middle - first);
r = PTRDIFF_TO_INT(last - middle);
for(; (0 < l) && (0 < r);) {
if(l == r) { ss_blockswap(first, middle, l); break; }
if(l < r) {
@ -601,7 +601,7 @@ ss_inplacemerge(const unsigned char *T, const int *PA,
for(;;) {
if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); }
else { x = 0; p = PA + *(last - 1); }
for(a = first, len = middle - first, half = len >> 1, r = -1;
for(a = first, len = PTRDIFF_TO_INT(middle - first), half = len >> 1, r = -1;
0 < len;
len = half, half >>= 1) {
b = a + half;
@ -640,7 +640,7 @@ ss_mergeforward(const unsigned char *T, const int *PA,
int r;
bufend = buf + (middle - first) - 1;
ss_blockswap(buf, first, middle - first);
ss_blockswap(buf, first, PTRDIFF_TO_INT(middle - first));
for(t = *(a = first), b = buf, c = middle;;) {
r = ss_compare(T, PA + *b, PA + *c, depth);
@ -692,7 +692,7 @@ ss_mergebackward(const unsigned char *T, const int *PA,
int x;
bufend = buf + (last - middle) - 1;
ss_blockswap(buf, middle, last - middle);
ss_blockswap(buf, middle, PTRDIFF_TO_INT(last - middle));
x = 0;
if(*bufend < 0) { p1 = PA + ~*bufend; x |= 1; }
@ -781,7 +781,7 @@ ss_swapmerge(const unsigned char *T, const int *PA,
continue;
}
for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1;
for(m = 0, len = PTRDIFF_TO_INT(MIN(middle - first, last - middle)), half = len >> 1;
0 < len;
len = half, half >>= 1) {
if(ss_compare(T, PA + GETIDX(*(middle + m + half)),
@ -850,8 +850,8 @@ sssort(const unsigned char *T, const int *PA,
ss_mintrosort(T, PA, first, last, depth);
#else
if((bufsize < SS_BLOCKSIZE) &&
(bufsize < (last - first)) &&
(bufsize < (limit = ss_isqrt(last - first)))) {
(bufsize < PTRDIFF_TO_INT(last - first)) &&
(bufsize < (limit = ss_isqrt(PTRDIFF_TO_INT(last - first))))) {
if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; }
buf = middle = last - limit, bufsize = limit;
} else {
@ -863,7 +863,7 @@ sssort(const unsigned char *T, const int *PA,
#elif 1 < SS_BLOCKSIZE
ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth);
#endif
curbufsize = last - (a + SS_BLOCKSIZE);
curbufsize = PTRDIFF_TO_INT(last - (a + SS_BLOCKSIZE));
curbuf = a + SS_BLOCKSIZE;
if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; }
for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) {
@ -1016,7 +1016,7 @@ tr_pivot(const int *ISAd, int *first, int *last) {
int *middle;
int t;
t = last - first;
t = PTRDIFF_TO_INT(last - first);
middle = first + t / 2;
if(t <= 512) {
@ -1098,9 +1098,9 @@ tr_partition(const int *ISAd,
if(a <= d) {
c = b - 1;
if((s = a - first) > (t = b - a)) { s = t; }
if((s = PTRDIFF_TO_INT(a - first)) > (t = PTRDIFF_TO_INT(b - a))) { s = t; }
for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
if((s = d - c) > (t = last - d - 1)) { s = t; }
if((s = PTRDIFF_TO_INT(d - c)) > (t = PTRDIFF_TO_INT(last - d - 1))) { s = t; }
for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
first += (b - a), last -= (d - c);
}
@ -1117,17 +1117,17 @@ tr_copy(int *ISA, const int *SA,
int *c, *d, *e;
int s, v;
v = b - SA - 1;
v = PTRDIFF_TO_INT(b - SA - 1);
for(c = first, d = a - 1; c <= d; ++c) {
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
*++d = s;
ISA[s] = d - SA;
ISA[s] = PTRDIFF_TO_INT(d - SA);
}
}
for(c = last - 1, e = d + 1, d = b; e < d; --c) {
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
*--d = s;
ISA[s] = d - SA;
ISA[s] = PTRDIFF_TO_INT(d - SA);
}
}
}
@ -1141,13 +1141,13 @@ tr_partialcopy(int *ISA, const int *SA,
int s, v;
int rank, lastrank, newrank = -1;
v = b - SA - 1;
v = PTRDIFF_TO_INT(b - SA - 1);
lastrank = -1;
for(c = first, d = a - 1; c <= d; ++c) {
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
*++d = s;
rank = ISA[s + depth];
if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
if(lastrank != rank) { lastrank = rank; newrank = PTRDIFF_TO_INT(d - SA); }
ISA[s] = newrank;
}
}
@ -1155,7 +1155,7 @@ tr_partialcopy(int *ISA, const int *SA,
lastrank = -1;
for(e = d; first <= e; --e) {
rank = ISA[*e];
if(lastrank != rank) { lastrank = rank; newrank = e - SA; }
if(lastrank != rank) { lastrank = rank; newrank = PTRDIFF_TO_INT(e - SA); }
if(newrank != rank) { ISA[*e] = newrank; }
}
@ -1164,7 +1164,7 @@ tr_partialcopy(int *ISA, const int *SA,
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
*--d = s;
rank = ISA[s + depth];
if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
if(lastrank != rank) { lastrank = rank; newrank = PTRDIFF_TO_INT(d - SA); }
ISA[s] = newrank;
}
}
@ -1180,23 +1180,23 @@ tr_introsort(int *ISA, const int *ISAd,
int *a, *b, *c;
int t;
int v, x = 0;
int incr = ISAd - ISA;
int incr = PTRDIFF_TO_INT(ISAd - ISA);
int limit, next;
int ssize, trlink = -1;
for(ssize = 0, limit = tr_ilg(last - first);;) {
for(ssize = 0, limit = tr_ilg(PTRDIFF_TO_INT(last - first));;) {
if(limit < 0) {
if(limit == -1) {
/* tandem repeat partition */
tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1);
tr_partition(ISAd - incr, first, first, last, &a, &b, PTRDIFF_TO_INT(last - SA - 1));
/* update ranks */
if(a < last) {
for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
for(c = first, v = PTRDIFF_TO_INT(a - SA - 1); c < a; ++c) { ISA[*c] = v; }
}
if(b < last) {
for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; }
for(c = a, v = PTRDIFF_TO_INT(b - SA - 1); c < b; ++c) { ISA[*c] = v; }
}
/* push */
@ -1207,19 +1207,19 @@ tr_introsort(int *ISA, const int *ISAd,
}
if((a - first) <= (last - b)) {
if(1 < (a - first)) {
STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink);
last = a, limit = tr_ilg(a - first);
STACK_PUSH5(ISAd, b, last, tr_ilg(PTRDIFF_TO_INT(last - b)), trlink);
last = a, limit = tr_ilg(PTRDIFF_TO_INT(a - first));
} else if(1 < (last - b)) {
first = b, limit = tr_ilg(last - b);
first = b, limit = tr_ilg(PTRDIFF_TO_INT(last - b));
} else {
STACK_POP5(ISAd, first, last, limit, trlink);
}
} else {
if(1 < (last - b)) {
STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink);
first = b, limit = tr_ilg(last - b);
STACK_PUSH5(ISAd, first, a, tr_ilg(PTRDIFF_TO_INT(a - first)), trlink);
first = b, limit = tr_ilg(PTRDIFF_TO_INT(last - b));
} else if(1 < (a - first)) {
last = a, limit = tr_ilg(a - first);
last = a, limit = tr_ilg(PTRDIFF_TO_INT(a - first));
} else {
STACK_POP5(ISAd, first, last, limit, trlink);
}
@ -1228,26 +1228,26 @@ tr_introsort(int *ISA, const int *ISAd,
/* tandem repeat copy */
a = stack[--ssize].b, b = stack[ssize].c;
if(stack[ssize].d == 0) {
tr_copy(ISA, SA, first, a, b, last, ISAd - ISA);
tr_copy(ISA, SA, first, a, b, last, PTRDIFF_TO_INT(ISAd - ISA));
} else {
if(0 <= trlink) { stack[trlink].d = -1; }
tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA);
tr_partialcopy(ISA, SA, first, a, b, last, PTRDIFF_TO_INT(ISAd - ISA));
}
STACK_POP5(ISAd, first, last, limit, trlink);
} else {
/* sorted partition */
if(0 <= *first) {
a = first;
do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a));
do { ISA[*a] = PTRDIFF_TO_INT(a - SA); } while((++a < last) && (0 <= *a));
first = a;
}
if(first < last) {
a = first; do { *a = ~*a; } while(*++a < 0);
next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1;
if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } }
next = (ISA[*a] != ISAd[*a]) ? tr_ilg(PTRDIFF_TO_INT(a - first + 1)) : -1;
if(++a < last) { for(b = first, v = PTRDIFF_TO_INT(a - SA - 1); b < a; ++b) { ISA[*b] = v; } }
/* push */
if(trbudget_check(budget, a - first)) {
if(trbudget_check(budget, PTRDIFF_TO_INT(a - first))) {
if((a - first) <= (last - a)) {
STACK_PUSH5(ISAd, a, last, -3, trlink);
ISAd += incr, last = a, limit = next;
@ -1281,7 +1281,7 @@ tr_introsort(int *ISA, const int *ISAd,
}
if(limit-- == 0) {
tr_heapsort(ISAd, first, last - first);
tr_heapsort(ISAd, first, PTRDIFF_TO_INT(last - first));
for(a = last - 1; first < a; a = b) {
for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; }
}
@ -1297,14 +1297,14 @@ tr_introsort(int *ISA, const int *ISAd,
/* partition */
tr_partition(ISAd, first, first + 1, last, &a, &b, v);
if((last - first) != (b - a)) {
next = (ISA[*a] != v) ? tr_ilg(b - a) : -1;
next = (ISA[*a] != v) ? tr_ilg(PTRDIFF_TO_INT(b - a)) : -1;
/* update ranks */
for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } }
for(c = first, v = PTRDIFF_TO_INT(a - SA - 1); c < a; ++c) { ISA[*c] = v; }
if(b < last) { for(c = a, v = PTRDIFF_TO_INT(b - SA - 1); c < b; ++c) { ISA[*c] = v; } }
/* push */
if((1 < (b - a)) && (trbudget_check(budget, b - a))) {
if((1 < (b - a)) && (trbudget_check(budget, PTRDIFF_TO_INT(b - a)))) {
if((a - first) <= (last - b)) {
if((last - b) <= (b - a)) {
if(1 < (a - first)) {
@ -1381,8 +1381,8 @@ tr_introsort(int *ISA, const int *ISAd,
}
}
} else {
if(trbudget_check(budget, last - first)) {
limit = tr_ilg(last - first), ISAd += incr;
if(trbudget_check(budget, PTRDIFF_TO_INT(last - first))) {
limit = tr_ilg(PTRDIFF_TO_INT(last - first)), ISAd += incr;
} else {
if(0 <= trlink) { stack[trlink].d = -1; }
STACK_POP5(ISAd, first, last, limit, trlink);
@ -1420,7 +1420,7 @@ trsort(int *ISA, int *SA, int n, int depth) {
budget.count = 0;
tr_introsort(ISA, ISAd, SA, first, last, &budget);
if(budget.count != 0) { unsorted += budget.count; }
else { skip = first - last; }
else { skip = PTRDIFF_TO_INT(first - last); }
} else if((last - first) == 1) {
skip = -1;
}
@ -1634,7 +1634,7 @@ construct_SA(const unsigned char *T, int *SA,
c0 = T[--s];
if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
if(c0 != c2) {
if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
if(0 <= c2) { BUCKET_B(c2, c1) = PTRDIFF_TO_INT(k - SA); }
k = SA + BUCKET_B(c2 = c0, c1);
}
assert(k < j); assert(k != NULL);
@ -1658,7 +1658,7 @@ construct_SA(const unsigned char *T, int *SA,
c0 = T[--s];
if((s == 0) || (T[s - 1] < c0)) { s = ~s; }
if(c0 != c2) {
BUCKET_A(c2) = k - SA;
BUCKET_A(c2) = PTRDIFF_TO_INT(k - SA);
k = SA + BUCKET_A(c2 = c0);
}
assert(i < k);
@ -1698,7 +1698,7 @@ construct_BWT(const unsigned char *T, int *SA,
*j = ~((int)c0);
if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
if(c0 != c2) {
if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
if(0 <= c2) { BUCKET_B(c2, c1) = PTRDIFF_TO_INT(k - SA); }
k = SA + BUCKET_B(c2 = c0, c1);
}
assert(k < j); assert(k != NULL);
@ -1726,7 +1726,7 @@ construct_BWT(const unsigned char *T, int *SA,
*i = c0;
if((0 < s) && (T[s - 1] < c0)) { s = ~((int)T[s - 1]); }
if(c0 != c2) {
BUCKET_A(c2) = k - SA;
BUCKET_A(c2) = PTRDIFF_TO_INT(k - SA);
k = SA + BUCKET_A(c2 = c0);
}
assert(i < k);
@ -1738,7 +1738,7 @@ construct_BWT(const unsigned char *T, int *SA,
}
}
return orig - SA;
return PTRDIFF_TO_INT(orig - SA);
}
/* Constructs the burrows-wheeler transformed string directly
@ -1776,13 +1776,13 @@ construct_BWT_indexes(const unsigned char *T, int *SA,
assert(((s + 1) < n) && (T[s] <= T[s + 1]));
assert(T[s - 1] <= T[s]);
if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = j - SA;
if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = PTRDIFF_TO_INT(j - SA);
c0 = T[--s];
*j = ~((int)c0);
if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
if(c0 != c2) {
if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
if(0 <= c2) { BUCKET_B(c2, c1) = PTRDIFF_TO_INT(k - SA); }
k = SA + BUCKET_B(c2 = c0, c1);
}
assert(k < j); assert(k != NULL);
@ -1802,7 +1802,7 @@ construct_BWT_indexes(const unsigned char *T, int *SA,
the sorted order of type B suffixes. */
k = SA + BUCKET_A(c2 = T[n - 1]);
if (T[n - 2] < c2) {
if (((n - 1) & mod) == 0) indexes[(n - 1) / (mod + 1) - 1] = k - SA;
if (((n - 1) & mod) == 0) indexes[(n - 1) / (mod + 1) - 1] = PTRDIFF_TO_INT(k - SA);
*k++ = ~((int)T[n - 2]);
}
else {
@ -1814,17 +1814,17 @@ construct_BWT_indexes(const unsigned char *T, int *SA,
if(0 < (s = *i)) {
assert(T[s - 1] >= T[s]);
if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = i - SA;
if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = PTRDIFF_TO_INT(i - SA);
c0 = T[--s];
*i = c0;
if(c0 != c2) {
BUCKET_A(c2) = k - SA;
BUCKET_A(c2) = PTRDIFF_TO_INT(k - SA);
k = SA + BUCKET_A(c2 = c0);
}
assert(i < k);
if((0 < s) && (T[s - 1] < c0)) {
if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = k - SA;
if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = PTRDIFF_TO_INT(k - SA);
*k++ = ~((int)T[s - 1]);
} else
*k++ = s;
@ -1835,7 +1835,7 @@ construct_BWT_indexes(const unsigned char *T, int *SA,
}
}
return orig - SA;
return PTRDIFF_TO_INT(orig - SA);
}

View file

@ -49,38 +49,30 @@
/*-*************************************
* Console display
*
* Captures the `displayLevel` variable in the local scope.
***************************************/
#ifndef LOCALDISPLAYLEVEL
static int g_displayLevel = 0;
#endif
#undef DISPLAY
#define DISPLAY(...) \
{ \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
}
#undef LOCALDISPLAYLEVEL
#define LOCALDISPLAYLEVEL(displayLevel, l, ...) \
#undef DISPLAYLEVEL
#define DISPLAYLEVEL(l, ...) \
if (displayLevel >= l) { \
DISPLAY(__VA_ARGS__); \
} /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */
#undef DISPLAYLEVEL
#define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__)
#ifndef LOCALDISPLAYUPDATE
static const clock_t g_refreshRate = CLOCKS_PER_SEC * 15 / 100;
static clock_t g_time = 0;
#endif
#undef LOCALDISPLAYUPDATE
#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \
#undef DISPLAYUPDATE
#define DISPLAYUPDATE(lastUpdateTime, l, ...) \
if (displayLevel >= l) { \
if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \
g_time = clock(); \
const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100; \
if ((clock() - lastUpdateTime > refreshRate) || (displayLevel >= 4)) { \
lastUpdateTime = clock(); \
DISPLAY(__VA_ARGS__); \
} \
}
#undef DISPLAYUPDATE
#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__)
/*-*************************************
@ -136,6 +128,7 @@ typedef struct {
unsigned d;
unsigned f;
FASTCOVER_accel_t accelParams;
int displayLevel;
} FASTCOVER_ctx_t;
@ -314,7 +307,8 @@ FASTCOVER_ctx_init(FASTCOVER_ctx_t* ctx,
const void* samplesBuffer,
const size_t* samplesSizes, unsigned nbSamples,
unsigned d, double splitPoint, unsigned f,
FASTCOVER_accel_t accelParams)
FASTCOVER_accel_t accelParams,
int displayLevel)
{
const BYTE* const samples = (const BYTE*)samplesBuffer;
const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples);
@ -323,6 +317,7 @@ FASTCOVER_ctx_init(FASTCOVER_ctx_t* ctx,
const unsigned nbTestSamples = splitPoint < 1.0 ? nbSamples - nbTrainSamples : nbSamples;
const size_t trainingSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes, nbTrainSamples) : totalSamplesSize;
const size_t testSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes + nbTrainSamples, nbTestSamples) : totalSamplesSize;
ctx->displayLevel = displayLevel;
/* Checks */
if (totalSamplesSize < MAX(d, sizeof(U64)) ||
@ -409,7 +404,9 @@ FASTCOVER_buildDictionary(const FASTCOVER_ctx_t* ctx,
const COVER_epoch_info_t epochs = COVER_computeEpochs(
(U32)dictBufferCapacity, (U32)ctx->nbDmers, parameters.k, 1);
const size_t maxZeroScoreRun = 10;
const int displayLevel = ctx->displayLevel;
size_t zeroScoreRun = 0;
clock_t lastUpdateTime = 0;
size_t epoch;
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
(U32)epochs.num, (U32)epochs.size);
@ -447,6 +444,7 @@ FASTCOVER_buildDictionary(const FASTCOVER_ctx_t* ctx,
tail -= segmentSize;
memcpy(dict + tail, ctx->samples + segment.begin, segmentSize);
DISPLAYUPDATE(
lastUpdateTime,
2, "\r%u%% ",
(unsigned)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity));
}
@ -484,6 +482,7 @@ static void FASTCOVER_tryParameters(void* opaque)
BYTE *const dict = (BYTE*)malloc(dictBufferCapacity);
COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC));
U32* freqs = (U32*) malloc(((U64)1 << ctx->f) * sizeof(U32));
const int displayLevel = ctx->displayLevel;
if (!segmentFreqs || !dict || !freqs) {
DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n");
goto _cleanup;
@ -555,8 +554,7 @@ ZDICT_trainFromBuffer_fastCover(void* dictBuffer, size_t dictBufferCapacity,
FASTCOVER_ctx_t ctx;
ZDICT_cover_params_t coverParams;
FASTCOVER_accel_t accelParams;
/* Initialize global data */
g_displayLevel = (int)parameters.zParams.notificationLevel;
const int displayLevel = (int)parameters.zParams.notificationLevel;
/* Assign splitPoint and f if not provided */
parameters.splitPoint = 1.0;
parameters.f = parameters.f == 0 ? DEFAULT_F : parameters.f;
@ -585,13 +583,13 @@ ZDICT_trainFromBuffer_fastCover(void* dictBuffer, size_t dictBufferCapacity,
{
size_t const initVal = FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples,
coverParams.d, parameters.splitPoint, parameters.f,
accelParams);
accelParams, displayLevel);
if (ZSTD_isError(initVal)) {
DISPLAYLEVEL(1, "Failed to initialize context\n");
return initVal;
}
}
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, g_displayLevel);
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, displayLevel);
/* Build the dictionary */
DISPLAYLEVEL(2, "Building dictionary\n");
{
@ -646,25 +644,26 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
COVER_best_t best;
POOL_ctx *pool = NULL;
int warned = 0;
clock_t lastUpdateTime = 0;
/* Checks */
if (splitPoint <= 0 || splitPoint > 1) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect splitPoint\n");
DISPLAYLEVEL(1, "Incorrect splitPoint\n");
return ERROR(parameter_outOfBound);
}
if (accel == 0 || accel > FASTCOVER_MAX_ACCEL) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect accel\n");
DISPLAYLEVEL(1, "Incorrect accel\n");
return ERROR(parameter_outOfBound);
}
if (kMinK < kMaxD || kMaxK < kMinK) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect k\n");
DISPLAYLEVEL(1, "Incorrect k\n");
return ERROR(parameter_outOfBound);
}
if (nbSamples == 0) {
LOCALDISPLAYLEVEL(displayLevel, 1, "FASTCOVER must have at least one input file\n");
DISPLAYLEVEL(1, "FASTCOVER must have at least one input file\n");
return ERROR(srcSize_wrong);
}
if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {
LOCALDISPLAYLEVEL(displayLevel, 1, "dictBufferCapacity must be at least %u\n",
DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n",
ZDICT_DICTSIZE_MIN);
return ERROR(dstSize_tooSmall);
}
@ -679,19 +678,18 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
memset(&coverParams, 0 , sizeof(coverParams));
FASTCOVER_convertToCoverParams(*parameters, &coverParams);
accelParams = FASTCOVER_defaultAccelParameters[accel];
/* Turn down global display level to clean up display at level 2 and below */
g_displayLevel = displayLevel == 0 ? 0 : displayLevel - 1;
/* Loop through d first because each new value needs a new context */
LOCALDISPLAYLEVEL(displayLevel, 2, "Trying %u different sets of parameters\n",
kIterations);
DISPLAYLEVEL(2, "Trying %u different sets of parameters\n", kIterations);
for (d = kMinD; d <= kMaxD; d += 2) {
/* Initialize the context for this value of d */
FASTCOVER_ctx_t ctx;
LOCALDISPLAYLEVEL(displayLevel, 3, "d=%u\n", d);
DISPLAYLEVEL(3, "d=%u\n", d);
{
size_t const initVal = FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint, f, accelParams);
/* Turn down global display level to clean up display at level 2 and below */
const int childDisplayLevel = displayLevel == 0 ? 0 : displayLevel - 1;
size_t const initVal = FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint, f, accelParams, childDisplayLevel);
if (ZSTD_isError(initVal)) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n");
DISPLAYLEVEL(1, "Failed to initialize context\n");
COVER_best_destroy(&best);
POOL_free(pool);
return initVal;
@ -706,9 +704,9 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
/* Prepare the arguments */
FASTCOVER_tryParameters_data_t *data = (FASTCOVER_tryParameters_data_t *)malloc(
sizeof(FASTCOVER_tryParameters_data_t));
LOCALDISPLAYLEVEL(displayLevel, 3, "k=%u\n", k);
DISPLAYLEVEL(3, "k=%u\n", k);
if (!data) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to allocate parameters\n");
DISPLAYLEVEL(1, "Failed to allocate parameters\n");
COVER_best_destroy(&best);
FASTCOVER_ctx_destroy(&ctx);
POOL_free(pool);
@ -723,7 +721,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
data->parameters.splitPoint = splitPoint;
data->parameters.steps = kSteps;
data->parameters.shrinkDict = shrinkDict;
data->parameters.zParams.notificationLevel = (unsigned)g_displayLevel;
data->parameters.zParams.notificationLevel = (unsigned)ctx.displayLevel;
/* Check the parameters */
if (!FASTCOVER_checkParameters(data->parameters, dictBufferCapacity,
data->ctx->f, accel)) {
@ -739,14 +737,15 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
FASTCOVER_tryParameters(data);
}
/* Print status */
LOCALDISPLAYUPDATE(displayLevel, 2, "\r%u%% ",
DISPLAYUPDATE(lastUpdateTime,
2, "\r%u%% ",
(unsigned)((iteration * 100) / kIterations));
++iteration;
}
COVER_best_wait(&best);
FASTCOVER_ctx_destroy(&ctx);
}
LOCALDISPLAYLEVEL(displayLevel, 2, "\r%79s\r", "");
DISPLAYLEVEL(2, "\r%79s\r", "");
/* Fill the output buffer and parameters with output of the best parameters */
{
const size_t dictSize = best.dictSize;

View file

@ -168,7 +168,7 @@ static void ZDICT_initDictItem(dictItem* d)
#define MINMATCHLENGTH 7 /* heuristic determined experimentally */
static dictItem ZDICT_analyzePos(
BYTE* doneMarks,
const int* suffix, U32 start,
const unsigned* suffix, U32 start,
const void* buffer, U32 minRatio, U32 notificationLevel)
{
U32 lengthList[LLIMIT] = {0};
@ -293,8 +293,10 @@ static dictItem ZDICT_analyzePos(
for (i=(int)(maxLength-2); i>=0; i--)
cumulLength[i] = cumulLength[i+1] + lengthList[i];
for (i=LLIMIT-1; i>=MINMATCHLENGTH; i--) if (cumulLength[i]>=minRatio) break;
maxLength = i;
{ unsigned u;
for (u=LLIMIT-1; u>=MINMATCHLENGTH; u--) if (cumulLength[u]>=minRatio) break;
maxLength = u;
}
/* reduce maxLength in case of final into repetitive data */
{ U32 l = (U32)maxLength;
@ -306,8 +308,10 @@ static dictItem ZDICT_analyzePos(
/* calculate savings */
savings[5] = 0;
for (i=MINMATCHLENGTH; i<=(int)maxLength; i++)
savings[i] = savings[i-1] + (lengthList[i] * (i-3));
{ unsigned u;
for (u=MINMATCHLENGTH; u<=maxLength; u++)
savings[u] = savings[u-1] + (lengthList[u] * (u-3));
}
DISPLAYLEVEL(4, "Selected dict at position %u, of length %u : saves %u (ratio: %.2f) \n",
(unsigned)pos, (unsigned)maxLength, (unsigned)savings[maxLength], (double)savings[maxLength] / (double)maxLength);
@ -383,11 +387,11 @@ static U32 ZDICT_tryMerge(dictItem* table, dictItem elt, U32 eltNbToSkip, const
if ((table[u].pos + table[u].length >= elt.pos) && (table[u].pos < elt.pos)) { /* overlap, existing < new */
/* append */
int const addedLength = (int)eltEnd - (int)(table[u].pos + table[u].length);
int const addedLength = (int)eltEnd - (int)(table[u].pos + table[u].length); /* note: can be negative */
table[u].savings += elt.length / 8; /* rough approx bonus */
if (addedLength > 0) { /* otherwise, elt fully included into existing */
table[u].length += addedLength;
table[u].savings += elt.savings * addedLength / elt.length; /* rough approx */
table[u].length += (unsigned)addedLength;
table[u].savings += elt.savings * (unsigned)addedLength / elt.length; /* rough approx */
}
/* sort : improve rank */
elt = table[u];
@ -399,7 +403,7 @@ static U32 ZDICT_tryMerge(dictItem* table, dictItem elt, U32 eltNbToSkip, const
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 );
size_t const addedLength = MAX( elt.length - 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);
@ -467,8 +471,8 @@ static size_t ZDICT_trainBuffer_legacy(dictItem* dictList, U32 dictListSize,
const size_t* fileSizes, unsigned nbFiles,
unsigned minRatio, U32 notificationLevel)
{
int* const suffix0 = (int*)malloc((bufferSize+2)*sizeof(*suffix0));
int* const suffix = suffix0+1;
unsigned* const suffix0 = (unsigned*)malloc((bufferSize+2)*sizeof(*suffix0));
unsigned* const suffix = suffix0+1;
U32* reverseSuffix = (U32*)malloc((bufferSize)*sizeof(*reverseSuffix));
BYTE* doneMarks = (BYTE*)malloc((bufferSize+16)*sizeof(*doneMarks)); /* +16 for overflow security */
U32* filePos = (U32*)malloc(nbFiles * sizeof(*filePos));
@ -503,11 +507,11 @@ static size_t ZDICT_trainBuffer_legacy(dictItem* dictList, U32 dictListSize,
/* sort */
DISPLAYLEVEL(2, "sorting %u files of total size %u MB ...\n", nbFiles, (unsigned)(bufferSize>>20));
{ int const divSuftSortResult = divsufsort((const unsigned char*)buffer, suffix, (int)bufferSize, 0);
{ int const divSuftSortResult = divsufsort((const unsigned char*)buffer, (int*)suffix, (int)bufferSize, 0);
if (divSuftSortResult != 0) { result = ERROR(GENERIC); goto _cleanup; }
}
suffix[bufferSize] = (int)bufferSize; /* leads into noise */
suffix0[0] = (int)bufferSize; /* leads into noise */
suffix[bufferSize] = (unsigned)bufferSize; /* leads into noise */
suffix0[0] = (unsigned)bufferSize; /* leads into noise */
/* build reverse suffix sort */
{ size_t pos;
for (pos=0; pos < bufferSize; pos++)

View file

@ -1,20 +1,55 @@
@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_internal.h bin\example\
COPY lib\common\error_private.h bin\example\
COPY lib\common\xxhash.h bin\example\
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 lib\zstd.h bin\include\
COPY lib\common\zstd_errors.h bin\include\
COPY lib\dictBuilder\zdict.h bin\include\
COPY programs\zstd.exe bin\zstd.exe
@echo off
setlocal
rem Detect build type based on available files
set BUILD_TYPE=make
if exist "build\cmake\build\lib\Release\zstd_static.lib" set BUILD_TYPE=cmake
echo Detected build type: %BUILD_TYPE%
rem Create required directories
mkdir bin\dll bin\static bin\example bin\include
rem Copy common files using a subroutine. Exits immediately on failure.
call :copyFile "tests\fullbench.c" "bin\example\"
call :copyFile "programs\datagen.c" "bin\example\"
call :copyFile "programs\datagen.h" "bin\example\"
call :copyFile "programs\util.h" "bin\example\"
call :copyFile "programs\platform.h" "bin\example\"
call :copyFile "lib\common\mem.h" "bin\example\"
call :copyFile "lib\common\zstd_internal.h" "bin\example\"
call :copyFile "lib\common\error_private.h" "bin\example\"
call :copyFile "lib\common\xxhash.h" "bin\example\"
call :copyFile "lib\dll\example\Makefile" "bin\example\"
call :copyFile "lib\dll\example\fullbench-dll.*" "bin\example\"
call :copyFile "lib\zstd.h" "bin\include\"
call :copyFile "lib\zstd_errors.h" "bin\include\"
call :copyFile "lib\zdict.h" "bin\include\"
rem Copy build-specific files
if "%BUILD_TYPE%"=="cmake" (
echo Copying CMake build artifacts...
call :copyFile "build\cmake\build\lib\Release\zstd_static.lib" "bin\static\libzstd_static.lib"
call :copyFile "build\cmake\build\lib\Release\zstd.dll" "bin\dll\libzstd.dll"
call :copyFile "build\cmake\build\lib\Release\zstd.lib" "bin\dll\zstd.lib"
call :copyFile "build\cmake\build\programs\Release\zstd.exe" "bin\zstd.exe"
call :copyFile "lib\dll\example\README.md" "bin\README.md"
) else (
echo Copying Make build artifacts...
call :copyFile "lib\libzstd.a" "bin\static\libzstd_static.lib"
call :copyFile "lib\dll\libzstd.*" "bin\dll\"
call :copyFile "programs\zstd.exe" "bin\zstd.exe"
call :copyFile "lib\dll\example\README.md" "bin\"
)
echo Build package created successfully for %BUILD_TYPE% build!
endlocal
exit /b 0
:copyFile
copy "%~1" "%~2"
if errorlevel 1 (
echo Failed to copy "%~1"
exit 1
)
exit /b

17
lib/install_oses.mk Normal file
View file

@ -0,0 +1,17 @@
# ################################################################
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under both the BSD-style license (found in the
# LICENSE file in the root directory of this source tree) and the GPLv2 (found
# in the COPYING file in the root directory of this source tree).
# You may select, at your option, one of the above-listed licenses.
# ################################################################
# This included Makefile provides the following variables :
# UNAME, INSTALL_OS_LIST
UNAME := $(shell sh -c 'MSYSTEM="MSYS" uname')
# List of OSes for which target install is supported
INSTALL_OS_LIST ?= Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX MSYS_NT% CYGWIN_NT%

View file

@ -430,7 +430,7 @@ static unsigned FSE_isError(size_t code) { return (code > (size_t)(-FSE_ERROR_ma
static short FSE_abs(short a)
{
return a<0? -a : a;
return a<0? (short)-a : a;
}
@ -1823,11 +1823,12 @@ static size_t ZSTD_decompressSequences(
BYTE* const ostart = (BYTE* const)dst;
BYTE* op = ostart;
BYTE* const oend = ostart + maxDstSize;
size_t errorCode, dumpsLength;
size_t errorCode = 0;
size_t dumpsLength = 0;
const BYTE* litPtr = litStart;
const BYTE* const litEnd = litStart + litSize;
int nbSeq;
const BYTE* dumps;
int nbSeq = 0;
const BYTE* dumps = NULL;
U32* DTableLL = dctx->LLTable;
U32* DTableML = dctx->MLTable;
U32* DTableOffb = dctx->OffTable;
@ -1915,7 +1916,7 @@ size_t ZSTDv01_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const voi
size_t remainingSize = srcSize;
U32 magicNumber;
size_t errorCode=0;
blockProperties_t blockProperties;
blockProperties_t blockProperties = { 0 };
/* Frame Header */
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);

View file

@ -1111,7 +1111,7 @@ static unsigned FSE_isError(size_t code) { return ERR_isError(code); }
****************************************************************/
static short FSE_abs(short a)
{
return a<0 ? -a : a;
return a<0 ? (short)-a : a;
}
static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,

View file

@ -1094,7 +1094,7 @@ static unsigned FSE_isError(size_t code) { return ERR_isError(code); }
****************************************************************/
static short FSE_abs(short a)
{
return a<0 ? -a : a;
return a<0 ? (short)-a : a;
}
static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,

View file

@ -1224,7 +1224,7 @@ const char* FSEv05_getErrorName(size_t code) { return ERR_getErrorName(code); }
/*-**************************************************************
* FSEv05 NCount encoding-decoding
****************************************************************/
static short FSEv05_abs(short a) { return a<0 ? -a : a; }
static short FSEv05_abs(short a) { return a<0 ? (short)-a : a; }
size_t FSEv05_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
@ -3972,8 +3972,15 @@ size_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* zbc, void* dst, size_t* maxDst
zbc->outStart += flushedSize;
if (flushedSize == toFlushSize) {
zbc->stage = ZBUFFv05ds_read;
if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize)
zbc->outStart = zbc->outEnd = 0;
if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize) {
/* Not enough room for next block - need to wrap buffer.
* Preserve history: copy the last windowSize bytes to the
* beginning so that back-references can still find valid data. */
size_t const windowSize = (size_t)1 << zbc->params.windowLog;
size_t const preserveSize = MIN(zbc->outEnd, windowSize);
memmove(zbc->outBuff, zbc->outBuff + zbc->outEnd - preserveSize, preserveSize);
zbc->outStart = zbc->outEnd = preserveSize;
}
break;
}
/* cannot flush everything */

View file

@ -1202,7 +1202,7 @@ static unsigned HUFv06_isError(size_t code) { return ERR_isError(code); }
/*-**************************************************************
* FSE NCount encoding-decoding
****************************************************************/
static short FSEv06_abs(short a) { return a<0 ? -a : a; }
static short FSEv06_abs(short a) { return a<0 ? (short)-a : a; }
size_t FSEv06_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
const void* headerBuffer, size_t hbSize)

View file

@ -28,12 +28,8 @@ LIB_BINDIR ?= $(LIB_SRCDIR)
# configures a bunch of other variables to space-optimized defaults.
ZSTD_LIB_MINIFY ?= 0
# Legacy support
ifneq ($(ZSTD_LIB_MINIFY), 0)
# Legacy support disabled by default
ZSTD_LEGACY_SUPPORT ?= 0
else
ZSTD_LEGACY_SUPPORT ?= 5
endif
ZSTD_LEGACY_MULTITHREADED_API ?= 0
# Build size optimizations
@ -206,7 +202,10 @@ endif
endif
CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
UNAME := $(shell sh -c 'MSYSTEM="MSYS" uname')
# Include install_oses.mk from the same directory
include $(dir $(lastword $(MAKEFILE_LIST)))/install_oses.mk
LN ?= ln
CP ?= cp -f
ifndef BUILD_DIR
ifeq ($(UNAME), Darwin)

View file

@ -14,3 +14,4 @@ Version: @VERSION@
Libs: -L${libdir} -lzstd @LIBS_MT@
Libs.private: @LIBS_PRIVATE@
Cflags: -I${includedir} @LIBS_MT@
License: BSD-3-Clause OR GPL-2.0-only

View file

@ -1,27 +1,6 @@
module libzstd [extern_c] {
header "zstd.h"
export *
config_macros [exhaustive] \
/* zstd.h */ \
ZSTD_STATIC_LINKING_ONLY, \
ZSTDLIB_VISIBILITY, \
ZSTDLIB_VISIBLE, \
ZSTDLIB_HIDDEN, \
ZSTD_DLL_EXPORT, \
ZSTDLIB_STATIC_API, \
ZSTD_DISABLE_DEPRECATE_WARNINGS, \
ZSTD_CLEVEL_DEFAULT, \
/* zdict.h */ \
ZDICT_STATIC_LINKING_ONLY, \
ZDICTLIB_VISIBLE, \
ZDICTLIB_HIDDEN, \
ZDICTLIB_VISIBILITY, \
ZDICTLIB_STATIC_API, \
ZDICT_DISABLE_DEPRECATE_WARNINGS, \
/* zstd_errors.h */ \
ZSTDERRORLIB_VISIBLE, \
ZSTDERRORLIB_HIDDEN, \
ZSTDERRORLIB_VISIBILITY
module dictbuilder [extern_c] {
header "zdict.h"

View file

@ -110,8 +110,8 @@ extern "C" {
/*------ Version ------*/
#define ZSTD_VERSION_MAJOR 1
#define ZSTD_VERSION_MINOR 5
#define ZSTD_VERSION_RELEASE 7
#define ZSTD_VERSION_MINOR 6
#define ZSTD_VERSION_RELEASE 0
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
/*! ZSTD_versionNumber() :
@ -176,30 +176,30 @@ ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
/*====== Decompression helper functions ======*/
/*! ZSTD_getFrameContentSize() : requires v1.3.0+
* `src` should point to the start of a ZSTD encoded frame.
* `srcSize` must be at least as large as the frame header.
* hint : any size >= `ZSTD_frameHeaderSize_max` is large enough.
* @return : - decompressed size of `src` frame content, if known
* - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
* - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small)
* note 1 : a 0 return value means the frame is valid but "empty".
* When invoking this method on a skippable frame, it will return 0.
* note 2 : decompressed size is an optional field, it may not be present (typically in streaming mode).
* When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.
* In which case, it's necessary to use streaming mode to decompress data.
* Optionally, application can rely on some implicit limit,
* as ZSTD_decompress() only needs an upper bound of decompressed size.
* (For example, data could be necessarily cut into blocks <= 16 KB).
* note 3 : decompressed size is always present when compression is completed using single-pass functions,
* such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict().
* note 4 : 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 5 : If source is untrusted, decompressed size could be wrong or intentionally modified.
* Always ensure return value fits within application's authorized limits.
* Each application can set its own limits.
* note 6 : This function replaces ZSTD_getDecompressedSize() */
/*! @brief Returns the decompressed content size stored in a ZSTD frame header.
*
* @since v1.3.0
*
* @param src Pointer to the beginning of a ZSTD encoded frame.
* @param srcSize Size of the buffer pointed to by @p src. It must be at least as large as the frame header.
* Any value greater than or equal to `ZSTD_frameHeaderSize_max` is sufficient.
* @return The decompressed size in bytes when the value is available in the frame header.
* @retval ZSTD_CONTENTSIZE_UNKNOWN The frame does not encode a decompressed size (typical for streaming).
* @retval ZSTD_CONTENTSIZE_ERROR An error occurred (e.g. invalid magic number, @p srcSize too small).
*
* @note The return value is not compatible with `ZSTD_isError()`.
* @note A return value of 0 denotes a valid but empty frame. Skippable frames also report 0.
* @note The decompressed size field is optional. When it is absent (the function returns @c ZSTD_CONTENTSIZE_UNKNOWN),
* the caller must rely on streaming decompression or an application-specific upper bound. `ZSTD_decompress()`
* only requires an upper bound, so applications may enforce their own block limits (for example 16 KB).
* @note The decompressed size is guaranteed to be present when compression was performed with single-pass APIs such as
* `ZSTD_compress()`, `ZSTD_compressCCtx()`, `ZSTD_compress_usingDict()`, or `ZSTD_compress_usingCDict()`.
* @note The decompressed size is a 64-bit value and may exceed the addressable space of the system. Use streaming
* decompression when the value is too large to materialize in contiguous memory.
* @warning When processing untrusted input, validate the returned size against the application's limits; attackers may
* forge an arbitrarily large value.
* @note This function replaces `ZSTD_getDecompressedSize()`.
*/
#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
@ -1868,15 +1868,14 @@ ZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict(
typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
typedef void (*ZSTD_freeFunction) (void* opaque, void* address);
typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;
static
#ifdef __GNUC__
__attribute__((__unused__))
#endif
#if defined(__clang__) && __clang_major__ >= 5
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
static
#ifdef __GNUC__
__attribute__((__unused__))
#endif
ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */
#if defined(__clang__) && __clang_major__ >= 5
#pragma clang diagnostic pop
@ -3138,6 +3137,18 @@ ZSTDLIB_STATIC_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
/*! ZSTD_isDeterministicBuild() :
* Returns 1 if the library is built using standard compilation flags,
* and participates in determinism guarantees with other builds of the
* same version.
* If this function returns 0, it means the library was compiled with
* non-standard compilation flags that change the output of the
* compressor.
* This is mainly used for Zstd's determinism test suite, which is only
* run when this function returns 1.
*/
ZSTDLIB_API int ZSTD_isDeterministicBuild(void);
/* ========================================= */
/** Block level API (DEPRECATED) */

View file

@ -170,7 +170,7 @@ endif
zstd : $(BUILD_DIR)/zstd
if [ $(BIN_ISDIFFERENT) -eq 1 ]; then \
cp -f $<$(EXT) $@$(EXT); \
$(CP) $<$(EXT) $@$(EXT); \
echo zstd build completed; \
else \
echo zstd already built; \
@ -271,7 +271,7 @@ zstd-dictBuilder: $(ZSTDLIB_COMMON_SRC) $(ZSTDLIB_COMPRESS_SRC) $(ZDICT_SRC) zst
CLEAN += zstdmt
zstdmt: zstd
ln -sf zstd zstdmt
$(LN) -sf zstd zstdmt
.PHONY: generate_res
generate_res: $(RES64_FILE) $(RES32_FILE)
@ -345,7 +345,7 @@ include $(wildcard $(DEPFILES))
#-----------------------------------------------------------------------------
# make install is validated only for Linux, macOS, BSD, Hurd and Solaris targets
#-----------------------------------------------------------------------------
ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX MSYS_NT% CYGWIN_NT%,$(UNAME)))
ifneq (,$(filter $(INSTALL_OS_LIST),$(UNAME)))
HAVE_COLORNEVER = $(shell echo a | egrep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0)
EGREP_OPTIONS ?=
@ -414,15 +414,15 @@ install:
[ -e $(DESTDIR)$(MAN1DIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(MAN1DIR)/
@echo Installing binaries
$(INSTALL_PROGRAM) zstd$(EXT) $(DESTDIR)$(BINDIR)/zstd$(EXT)
ln -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/zstdcat$(EXT)
ln -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/unzstd$(EXT)
ln -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/zstdmt$(EXT)
$(LN) -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/zstdcat$(EXT)
$(LN) -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/unzstd$(EXT)
$(LN) -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/zstdmt$(EXT)
$(INSTALL_SCRIPT) zstdless $(DESTDIR)$(BINDIR)/zstdless
$(INSTALL_SCRIPT) zstdgrep $(DESTDIR)$(BINDIR)/zstdgrep
@echo Installing man pages
$(INSTALL_MAN) zstd.1 $(DESTDIR)$(MAN1DIR)/zstd.1
ln -sf zstd.1 $(DESTDIR)$(MAN1DIR)/zstdcat.1
ln -sf zstd.1 $(DESTDIR)$(MAN1DIR)/unzstd.1
$(LN) -sf zstd.1 $(DESTDIR)$(MAN1DIR)/zstdcat.1
$(LN) -sf zstd.1 $(DESTDIR)$(MAN1DIR)/unzstd.1
$(INSTALL_MAN) zstdgrep.1 $(DESTDIR)$(MAN1DIR)/zstdgrep.1
$(INSTALL_MAN) zstdless.1 $(DESTDIR)$(MAN1DIR)/zstdless.1
@echo zstd installation completed

View file

@ -79,6 +79,13 @@ There are however other Makefile targets that create different variations of CLI
This can be useful to produce smaller binaries.
A corresponding `Makefile` target using this ability is `zstd-compress`.
- __ZSTD_DISPLAY_LEVEL_DEFAULT__ : Controls the default verbosity level of `zstd` output.
The default value is `2`. Lower values (e.g., `1`) reduce output verbosity,
while higher values (e.g., `3`) increase it.
This allows setting preferred verbosity at compile time,
rather than passing `-q` or `-v` flags at runtime.
Example : `CPPFLAGS="-DZSTD_DISPLAY_LEVEL_DEFAULT=1" make`
- __BACKTRACE__ : `zstd` can display a stack backtrace when execution
generates a runtime exception. By default, this feature may be
degraded/disabled on some platforms unless additional compiler directives are
@ -153,7 +160,7 @@ Usage: zstd [OPTIONS...] [INPUT... | -] [-o OUTPUT]
Options:
-o OUTPUT Write output to a single file, OUTPUT.
-k, --keep Preserve INPUT file(s). [Default]
--rm Remove INPUT file(s) after successful (de)compression.
--rm Remove INPUT file(s) after successful (de)compression to file.
-# Desired compression level, where `#` is a number between 1 and 19;
lower numbers provide faster compression, higher numbers yield

View file

@ -208,7 +208,7 @@ BMK_advancedParams_t BMK_initAdvancedParams(void)
BMK_advancedParams_t const res = {
BMK_both, /* mode */
BMK_TIMETEST_DEFAULT_S, /* nbSeconds */
0, /* blockSize */
0, /* chunkSizeMax */
0, /* targetCBlockSize */
0, /* nbWorkers */
0, /* realTime */
@ -227,16 +227,6 @@ BMK_advancedParams_t BMK_initAdvancedParams(void)
/* ********************************************************
* Bench functions
**********************************************************/
typedef struct {
const void* srcPtr;
size_t srcSize;
void* cPtr;
size_t cRoom;
size_t cSize;
void* resPtr;
size_t resSize;
} blockParam_t;
#undef MIN
#undef MAX
#define MIN(a, b) ((a) < (b) ? (a) : (b))
@ -435,16 +425,16 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc(
const char* displayName,
const BMK_advancedParams_t* adv)
{
size_t const blockSize =
((adv->blockSize >= 32 && (adv->mode != BMK_decodeOnly))
? adv->blockSize
size_t const chunkSizeMax =
((adv->chunkSizeMax >= 32 && (adv->mode != BMK_decodeOnly))
? adv->chunkSizeMax
: srcSize)
+ (!srcSize); /* avoid div by 0 */
BMK_benchResult_t benchResult;
size_t const loadedCompressedSize = srcSize;
size_t cSize = 0;
double ratio = 0.;
U32 nbBlocks;
U32 nbChunks = 0;
assert(cctx != NULL);
assert(dctx != NULL);
@ -500,41 +490,42 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc(
}
}
/* Init data blocks */
/* Init data chunks */
{
const char* srcPtr = (const char*)srcBuffer;
char* cPtr = (char*)compressedBuffer;
char* resPtr = (char*)(*resultBufferPtr);
U32 fileNb;
for (nbBlocks = 0, fileNb = 0; fileNb < nbFiles; fileNb++) {
U32 fileNb, chunkID;
for (chunkID = 0, fileNb = 0; fileNb < nbFiles; fileNb++) {
size_t remaining = fileSizes[fileNb];
U32 const nbBlocksforThisFile = (adv->mode == BMK_decodeOnly)
U32 const nbChunksforThisFile = (adv->mode == BMK_decodeOnly)
? 1
: (U32)((remaining + (blockSize - 1)) / blockSize);
U32 const blockEnd = nbBlocks + nbBlocksforThisFile;
for (; nbBlocks < blockEnd; nbBlocks++) {
size_t const thisBlockSize = MIN(remaining, blockSize);
srcPtrs[nbBlocks] = srcPtr;
srcSizes[nbBlocks] = thisBlockSize;
cPtrs[nbBlocks] = cPtr;
cCapacities[nbBlocks] = (adv->mode == BMK_decodeOnly)
? thisBlockSize
: ZSTD_compressBound(thisBlockSize);
resPtrs[nbBlocks] = resPtr;
resSizes[nbBlocks] = (adv->mode == BMK_decodeOnly)
: (U32)((remaining + (chunkSizeMax - 1)) / chunkSizeMax);
U32 const chunkIdEnd = chunkID + nbChunksforThisFile;
for (; chunkID < chunkIdEnd; chunkID++) {
size_t const chunkSize = MIN(remaining, chunkSizeMax);
srcPtrs[chunkID] = srcPtr;
srcSizes[chunkID] = chunkSize;
cPtrs[chunkID] = cPtr;
cCapacities[chunkID] = (adv->mode == BMK_decodeOnly)
? chunkSize
: ZSTD_compressBound(chunkSize);
resPtrs[chunkID] = resPtr;
resSizes[chunkID] = (adv->mode == BMK_decodeOnly)
? (size_t)ZSTD_findDecompressedSize(
srcPtr, thisBlockSize)
: thisBlockSize;
srcPtr += thisBlockSize;
cPtr += cCapacities[nbBlocks];
resPtr += thisBlockSize;
remaining -= thisBlockSize;
srcPtr, chunkSize)
: chunkSize;
srcPtr += chunkSize;
cPtr += cCapacities[chunkID];
resPtr += chunkSize;
remaining -= chunkSize;
if (adv->mode == BMK_decodeOnly) {
cSizes[nbBlocks] = thisBlockSize;
benchResult.cSize = thisBlockSize;
cSizes[chunkID] = chunkSize;
benchResult.cSize = chunkSize;
}
}
}
nbChunks = chunkID;
}
/* warming up `compressedBuffer` */
@ -569,7 +560,7 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc(
cbp.initFn = local_initCCtx; /* BMK_initCCtx */
cbp.initPayload = &cctxprep;
cbp.errorFn = ZSTD_isError;
cbp.blockCount = nbBlocks;
cbp.blockCount = nbChunks;
cbp.srcBuffers = srcPtrs;
cbp.srcSizes = srcSizes;
cbp.dstBuffers = cPtrs;
@ -588,7 +579,7 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc(
dbp.initFn = local_initDCtx;
dbp.initPayload = &dctxprep;
dbp.errorFn = ZSTD_isError;
dbp.blockCount = nbBlocks;
dbp.blockCount = nbChunks;
dbp.srcBuffers = (const void* const*)cPtrs;
dbp.srcSizes = cSizes;
dbp.dstBuffers = resPtrs;
@ -690,8 +681,7 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc(
} /* while (!(compressionCompleted && decompressionCompleted)) */
/* CRC Checking */
{
const BYTE* resultBuffer = (const BYTE*)(*resultBufferPtr);
{ const BYTE* resultBuffer = (const BYTE*)(*resultBufferPtr);
U64 const crcCheck = XXH64(resultBuffer, srcSize, 0);
if ((adv->mode == BMK_both) && (crcOrig != crcCheck)) {
size_t u;
@ -704,14 +694,14 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc(
unsigned segNb, bNb, pos;
size_t bacc = 0;
DISPLAY("Decoding error at pos %u ", (unsigned)u);
for (segNb = 0; segNb < nbBlocks; segNb++) {
for (segNb = 0; segNb < nbChunks; segNb++) {
if (bacc + srcSizes[segNb] > u)
break;
bacc += srcSizes[segNb];
}
pos = (U32)(u - bacc);
bNb = pos / (128 KB);
DISPLAY("(sample %u, block %u, pos %u) \n",
DISPLAY("(sample %u, chunk %u, pos %u) \n",
segNb,
bNb,
pos);
@ -795,25 +785,24 @@ BMK_benchOutcome_t BMK_benchMemAdvanced(
int const dstParamsError =
!dstBuffer ^ !dstCapacity; /* must be both NULL or none */
size_t const blockSize =
((adv->blockSize >= 32 && (adv->mode != BMK_decodeOnly))
? adv->blockSize
size_t const chunkSize =
((adv->chunkSizeMax >= 32 && (adv->mode != BMK_decodeOnly))
? adv->chunkSizeMax
: srcSize)
+ (!srcSize) /* avoid div by 0 */;
U32 const maxNbBlocks =
(U32)((srcSize + (blockSize - 1)) / blockSize) + nbFiles;
U32 const nbChunksMax =
(U32)((srcSize + (chunkSize - 1)) / chunkSize) + nbFiles;
/* these are the blockTable parameters, just split up */
const void** const srcPtrs =
(const void**)malloc(maxNbBlocks * sizeof(void*));
size_t* const srcSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
(const void**)malloc(nbChunksMax * sizeof(void*));
size_t* const srcSizes = (size_t*)malloc(nbChunksMax * sizeof(size_t));
void** const cPtrs = (void**)malloc(maxNbBlocks * sizeof(void*));
size_t* const cSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
size_t* const cCapacities = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
void** const cPtrs = (void**)malloc(nbChunksMax * sizeof(void*));
size_t* const cSizes = (size_t*)malloc(nbChunksMax * sizeof(size_t));
size_t* const cCapacities = (size_t*)malloc(nbChunksMax * sizeof(size_t));
void** const resPtrs = (void**)malloc(maxNbBlocks * sizeof(void*));
size_t* const resSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
void** const resPtrs = (void**)malloc(nbChunksMax * sizeof(void*));
size_t* const resSizes = (size_t*)malloc(nbChunksMax * sizeof(size_t));
BMK_timedFnState_t* timeStateCompress = BMK_createTimedFnState(
adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS);
@ -825,7 +814,7 @@ BMK_benchOutcome_t BMK_benchMemAdvanced(
const size_t maxCompressedSize = dstCapacity
? dstCapacity
: ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024);
: ZSTD_compressBound(srcSize) + (nbChunksMax * 1024);
void* const internalDstBuffer =
dstBuffer ? NULL : malloc(maxCompressedSize);
@ -964,12 +953,12 @@ static int BMK_benchCLevels(
}
if (displayLevel == 1 && !adv->additionalParam) /* --quiet mode */
OUTPUT("bench %s %s: input %u bytes, %u seconds, %u KB blocks\n",
OUTPUT("bench %s %s: input %u bytes, %u seconds, %u KB chunks\n",
ZSTD_VERSION_STRING,
ZSTD_GIT_COMMIT_STRING,
(unsigned)benchedSize,
adv->nbSeconds,
(unsigned)(adv->blockSize >> 10));
(unsigned)(adv->chunkSizeMax >> 10));
for (level = startCLevel; level <= endCLevel; level++) {
BMK_benchOutcome_t res = BMK_benchMemAdvanced(
@ -1000,7 +989,7 @@ int BMK_syntheticTest(
{
char nameBuff[20] = { 0 };
const char* name = nameBuff;
size_t const benchedSize = adv->blockSize ? adv->blockSize : 10000000;
size_t const benchedSize = adv->chunkSizeMax ? adv->chunkSizeMax : 10000000;
/* Memory allocation */
void* const srcBuffer = malloc(benchedSize);

View file

@ -92,9 +92,9 @@ typedef enum {
} BMK_mode_t;
typedef struct {
BMK_mode_t mode; /* 0: all, 1: compress only 2: decode only */
BMK_mode_t mode; /* 0: both, 1: compress only 2: decode only */
unsigned nbSeconds; /* default timing is in nbSeconds */
size_t blockSize; /* Maximum size of each block*/
size_t chunkSizeMax; /* Maximum size of each independent chunk */
size_t targetCBlockSize;/* Approximative size of compressed blocks */
int nbWorkers; /* multithreading */
unsigned realTime; /* real time priority */

View file

@ -280,8 +280,15 @@ static fileStats DiB_fileStats(const char** fileNamesTable, int nbFiles, size_t
for (n=0; n<nbFiles; n++) {
S64 const fileSize = DiB_getFileSize(fileNamesTable[n]);
/* TODO: is there a minimum sample size? What if the file is 1-byte? */
if (fileSize == 0) {
DISPLAYLEVEL(3, "Sample file '%s' has zero size, skipping...\n", fileNamesTable[n]);
/* Skip empty or invalid files */
if (fileSize <= 0) {
if (fileSize < 0) {
DISPLAYLEVEL(3, "Sample file '%s' is unreadable or stat failed, skipping...\n",
fileNamesTable[n]);
} else {
DISPLAYLEVEL(3, "Sample file '%s' has zero size, skipping...\n",
fileNamesTable[n]);
}
continue;
}
@ -364,7 +371,7 @@ int DiB_trainFromFiles(const char* dictFileName, size_t maxDictSize,
if (fs.nbSamples < 5) {
DISPLAYLEVEL(2, "! Warning : nb of samples too low for proper processing !\n");
DISPLAYLEVEL(2, "! Please provide _one file per sample_.\n");
DISPLAYLEVEL(2, "! Alternatively, split files into fixed-size blocks representative of samples, with -B# \n");
DISPLAYLEVEL(2, "! Alternatively, split file(s) into fixed-size samples, with --split=#\n");
EXM_THROW(14, "nb of samples too low"); /* we now clearly forbid this case */
}
if (fs.totalSizeToLoad < (S64)maxDictSize * 8) {

View file

@ -125,6 +125,271 @@ char const* FIO_lzmaVersion(void)
#define TEMPORARY_FILE_PERMISSIONS (0600)
#endif
#ifndef ZSTD_NOCOMPRESS
/* *************************************
* Synchronous compression IO helpers
* Lightweight wrapper used by compression paths to manage buffered
* reads/writes without the async job machinery.
***************************************/
typedef struct {
const FIO_prefs_t* prefs;
FILE* srcFile;
FILE* dstFile;
unsigned storedSkips;
U8* inBuffer;
size_t inCapacity;
U8* srcBuffer;
size_t srcBufferLoaded;
U8* outBuffer;
size_t outCapacity;
} FIO_SyncCompressIO;
static void FIO_SyncCompressIO_init(FIO_SyncCompressIO* io,
const FIO_prefs_t* prefs,
size_t inCapacity,
size_t outCapacity);
static void FIO_SyncCompressIO_destroy(FIO_SyncCompressIO* io);
static void FIO_SyncCompressIO_setSrc(FIO_SyncCompressIO* io, FILE* file);
static void FIO_SyncCompressIO_clearSrc(FIO_SyncCompressIO* io);
static void FIO_SyncCompressIO_setDst(FIO_SyncCompressIO* io, FILE* file);
static int FIO_SyncCompressIO_closeDst(FIO_SyncCompressIO* io);
static size_t FIO_SyncCompressIO_fillBuffer(FIO_SyncCompressIO* io, size_t minToHave);
static void FIO_SyncCompressIO_consumeBytes(FIO_SyncCompressIO* io, size_t n);
static void FIO_SyncCompressIO_commitOut(FIO_SyncCompressIO* io, const void* buffer, size_t size);
static void FIO_SyncCompressIO_finish(FIO_SyncCompressIO* io);
static unsigned FIO_sparseWrite(FILE* file,
const void* buffer, size_t bufferSize,
const FIO_prefs_t* const prefs,
unsigned storedSkips)
{
const size_t* const bufferT = (const size_t*)buffer; /* Buffer is supposed malloc'ed, hence aligned on size_t */
size_t bufferSizeT = bufferSize / sizeof(size_t);
const size_t* const bufferTEnd = bufferT + bufferSizeT;
const size_t* ptrT = bufferT;
static const size_t segmentSizeT = (32 KB) / sizeof(size_t); /* check every 32 KB */
if (prefs->testMode) return 0; /* do not output anything in test mode */
if (!prefs->sparseFileSupport) { /* normal write */
size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file);
if (sizeCheck != bufferSize)
EXM_THROW(70, "Write error : cannot write block : %s",
strerror(errno));
return 0;
}
/* avoid int overflow */
if (storedSkips > 1 GB) {
if (LONG_SEEK(file, 1 GB, SEEK_CUR) != 0)
EXM_THROW(91, "1 GB skip error (sparse file support)");
storedSkips -= 1 GB;
}
while (ptrT < bufferTEnd) {
size_t nb0T;
/* adjust last segment if < 32 KB */
size_t seg0SizeT = segmentSizeT;
if (seg0SizeT > bufferSizeT) seg0SizeT = bufferSizeT;
bufferSizeT -= seg0SizeT;
/* count leading zeroes */
for (nb0T=0; (nb0T < seg0SizeT) && (ptrT[nb0T] == 0); nb0T++) ;
storedSkips += (unsigned)(nb0T * sizeof(size_t));
if (nb0T != seg0SizeT) { /* not all 0s */
size_t const nbNon0ST = seg0SizeT - nb0T;
/* skip leading zeros */
if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0)
EXM_THROW(92, "Sparse skip error ; try --no-sparse");
storedSkips = 0;
/* write the rest */
if (fwrite(ptrT + nb0T, sizeof(size_t), nbNon0ST, file) != nbNon0ST)
EXM_THROW(93, "Write error : cannot write block : %s",
strerror(errno));
}
ptrT += seg0SizeT;
}
{ static size_t const maskT = sizeof(size_t)-1;
if (bufferSize & maskT) {
/* size not multiple of sizeof(size_t) : implies end of block */
const char* const restStart = (const char*)bufferTEnd;
const char* restPtr = restStart;
const char* const restEnd = (const char*)buffer + bufferSize;
assert(restEnd > restStart && restEnd < restStart + sizeof(size_t));
for ( ; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ;
storedSkips += (unsigned) (restPtr - restStart);
if (restPtr != restEnd) {
/* not all remaining bytes are 0 */
size_t const restSize = (size_t)(restEnd - restPtr);
if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0)
EXM_THROW(92, "Sparse skip error ; try --no-sparse");
if (fwrite(restPtr, 1, restSize, file) != restSize)
EXM_THROW(95, "Write error : cannot write end of decoded block : %s",
strerror(errno));
storedSkips = 0;
} } }
return storedSkips;
}
static void FIO_sparseWriteEnd(const FIO_prefs_t* const prefs, FILE* file, unsigned storedSkips)
{
if (file == NULL) return;
if (prefs->testMode) {
assert(storedSkips == 0);
return;
}
if (storedSkips>0) {
assert(prefs->sparseFileSupport > 0); /* storedSkips>0 implies sparse support is enabled */
if (LONG_SEEK(file, storedSkips-1, SEEK_CUR) != 0)
EXM_THROW(69, "Final skip error (sparse file support)");
/* last zero must be explicitly written,
* so that skipped ones get implicitly translated as zero by FS */
{ const char lastZeroByte[1] = { 0 };
if (fwrite(lastZeroByte, 1, 1, file) != 1)
EXM_THROW(69, "Write error : cannot write last zero : %s", strerror(errno));
}
}
}
static void FIO_SyncCompressIO_init(FIO_SyncCompressIO* io,
const FIO_prefs_t* prefs,
size_t inCapacity,
size_t outCapacity)
{
memset(io, 0, sizeof(*io));
io->prefs = prefs;
io->inCapacity = inCapacity;
io->outCapacity = outCapacity;
io->inBuffer = (U8*)malloc(inCapacity);
if (!io->inBuffer)
EXM_THROW(101, "Allocation error : not enough memory");
io->outBuffer = (U8*)malloc(outCapacity);
if (!io->outBuffer) {
free(io->inBuffer);
io->inBuffer = NULL;
EXM_THROW(101, "Allocation error : not enough memory");
}
io->srcBuffer = io->inBuffer;
io->srcBufferLoaded = 0;
}
static void FIO_SyncCompressIO_destroy(FIO_SyncCompressIO* io)
{
if (!io) return;
free(io->inBuffer);
free(io->outBuffer);
io->inBuffer = NULL;
io->outBuffer = NULL;
io->srcBuffer = NULL;
io->srcBufferLoaded = 0;
io->srcFile = NULL;
io->dstFile = NULL;
io->storedSkips = 0;
}
static void FIO_SyncCompressIO_setSrc(FIO_SyncCompressIO* io, FILE* file)
{
io->srcFile = file;
io->srcBuffer = io->inBuffer;
io->srcBufferLoaded = 0;
}
static void FIO_SyncCompressIO_clearSrc(FIO_SyncCompressIO* io)
{
io->srcFile = NULL;
io->srcBuffer = io->inBuffer;
io->srcBufferLoaded = 0;
}
static void FIO_SyncCompressIO_setDst(FIO_SyncCompressIO* io, FILE* file)
{
io->dstFile = file;
io->storedSkips = 0;
}
static int FIO_SyncCompressIO_closeDst(FIO_SyncCompressIO* io)
{
int result = 0;
if (io->dstFile != NULL) {
FIO_SyncCompressIO_finish(io);
result = fclose(io->dstFile);
io->dstFile = NULL;
}
return result;
}
static size_t FIO_SyncCompressIO_fillBuffer(FIO_SyncCompressIO* io, size_t minToHave)
{
size_t added = 0;
if (io->srcFile == NULL)
return 0;
if (minToHave > io->inCapacity)
minToHave = io->inCapacity;
if (io->srcBufferLoaded >= minToHave)
return 0;
if (io->srcBuffer != io->inBuffer) {
if (io->srcBufferLoaded > 0)
memmove(io->inBuffer, io->srcBuffer, io->srcBufferLoaded);
io->srcBuffer = io->inBuffer;
}
while (io->srcBufferLoaded < minToHave) {
size_t const toRead = io->inCapacity - io->srcBufferLoaded;
size_t const readBytes = fread(io->inBuffer + io->srcBufferLoaded, 1, toRead, io->srcFile);
if (readBytes == 0) {
if (ferror(io->srcFile))
EXM_THROW(37, "Read error");
break; /* EOF */
}
io->srcBufferLoaded += readBytes;
added += readBytes;
if (readBytes < toRead)
break;
}
return added;
}
static void FIO_SyncCompressIO_consumeBytes(FIO_SyncCompressIO* io, size_t n)
{
assert(n <= io->srcBufferLoaded);
io->srcBuffer += n;
io->srcBufferLoaded -= n;
if (io->srcBufferLoaded == 0)
io->srcBuffer = io->inBuffer;
}
static void FIO_SyncCompressIO_commitOut(FIO_SyncCompressIO* io, const void* buffer, size_t size)
{
if (size == 0)
return;
if (io->dstFile == NULL) {
assert(io->prefs->testMode);
return;
}
io->storedSkips = FIO_sparseWrite(io->dstFile, buffer, size, io->prefs, io->storedSkips);
}
static void FIO_SyncCompressIO_finish(FIO_SyncCompressIO* io)
{
if (io->dstFile == NULL)
return;
FIO_sparseWriteEnd(io->prefs, io->dstFile, io->storedSkips);
io->storedSkips = 0;
}
#endif /* ZSTD_NOCOMPRESS */
/*-************************************
* Signal (Ctrl-C trapping)
**************************************/
@ -288,7 +553,7 @@ FIO_prefs_t* FIO_createPreferences(void)
ret->removeSrcFile = 0;
ret->memLimit = 0;
ret->nbWorkers = 1;
ret->blockSize = 0;
ret->jobSize = 0;
ret->overlapLog = FIO_OVERLAP_LOG_NOTSET;
ret->adaptiveMode = 0;
ret->rsyncable = 0;
@ -377,10 +642,10 @@ void FIO_setExcludeCompressedFile(FIO_prefs_t* const prefs, int excludeCompresse
void FIO_setAllowBlockDevices(FIO_prefs_t* const prefs, int allowBlockDevices) { prefs->allowBlockDevices = allowBlockDevices; }
void FIO_setBlockSize(FIO_prefs_t* const prefs, int blockSize) {
if (blockSize && prefs->nbWorkers==0)
void FIO_setJobSize(FIO_prefs_t* const prefs, int jobSize) {
if (jobSize && prefs->nbWorkers==0)
DISPLAYLEVEL(2, "Setting block size is useless in single-thread mode \n");
prefs->blockSize = blockSize;
prefs->jobSize = jobSize;
}
void FIO_setOverlapLog(FIO_prefs_t* const prefs, int overlapLog){
@ -538,13 +803,15 @@ static int FIO_removeFile(const char* path)
}
/** FIO_openSrcFile() :
* condition : `srcFileName` must be non-NULL. `prefs` may be NULL.
* condition : `srcFileName` must be non-NULL.
* optional: `prefs` may be NULL.
* @result : FILE* to `srcFileName`, or NULL if it fails */
static FILE* FIO_openSrcFile(const FIO_prefs_t* const prefs, const char* srcFileName, stat_t* statbuf)
{
int allowBlockDevices = prefs != NULL ? prefs->allowBlockDevices : 0;
assert(srcFileName != NULL);
assert(statbuf != NULL);
if (!strcmp(srcFileName, stdinmark)) {
DISPLAYLEVEL(4,"Using stdin for input \n");
SET_BINARY_MODE(stdin);
@ -557,8 +824,10 @@ static FILE* FIO_openSrcFile(const FIO_prefs_t* const prefs, const char* srcFile
return NULL;
}
/* Accept regular files, FIFOs, and process substitution file descriptors */
if (!UTIL_isRegularFileStat(statbuf)
&& !UTIL_isFIFOStat(statbuf)
&& !UTIL_isFileDescriptorPipe(srcFileName) /* Process substitution support */
&& !(allowBlockDevices && UTIL_isBlockDevStat(statbuf))
) {
DISPLAYLEVEL(1, "zstd: %s is not a regular file -- ignored \n",
@ -581,8 +850,6 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
const char* srcFileName, const char* dstFileName,
const int mode)
{
int isDstRegFile;
if (prefs->testMode) return NULL; /* do not open file in test mode */
assert(dstFileName != NULL);
@ -602,16 +869,7 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
return NULL;
}
isDstRegFile = UTIL_isRegularFile(dstFileName); /* invoke once */
if (prefs->sparseFileSupport == 1) {
prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
if (!isDstRegFile) {
prefs->sparseFileSupport = 0;
DISPLAYLEVEL(4, "Sparse File Support is disabled when output is not a file \n");
}
}
if (isDstRegFile) {
if (UTIL_isRegularFile(dstFileName)) {
/* Check if destination file already exists */
#if !defined(_WIN32)
/* this test does not work on Windows :
@ -637,6 +895,7 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
}
{
int isDstRegFile;
#if defined(_WIN32)
/* Windows requires opening the file as a "binary" file to avoid
* mangling. This macro doesn't exist on unix. */
@ -654,8 +913,23 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
f = fdopen(fd, "wb");
}
#endif
/* Check regular file after opening with O_CREAT */
isDstRegFile = UTIL_isFdRegularFile(fd);
if (prefs->sparseFileSupport == 1) {
prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
if (!isDstRegFile) {
prefs->sparseFileSupport = 0;
DISPLAYLEVEL(4, "Sparse File Support is disabled when output is not a file \n");
}
}
if (f == NULL) {
if (UTIL_isFileDescriptorPipe(dstFileName)) {
DISPLAYLEVEL(1, "zstd: error: no output specified (use -o or -c). \n");
} else {
DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno));
}
} else {
/* An increased buffer size can provide a significant performance
* boost on some platforms. Note that providing a NULL buf with a
@ -776,7 +1050,9 @@ static size_t FIO_setDictBufferMMap(FIO_Dict_t* dict, const char* fileName, FIO_
}
*bufferPtr = mmap(NULL, (size_t)fileSize, PROT_READ, MAP_PRIVATE, fileHandle, 0);
if (*bufferPtr==NULL) EXM_THROW(34, "%s", strerror(errno));
if (*bufferPtr == MAP_FAILED) {
EXM_THROW(34, "%s", strerror(errno))
}
close(fileHandle);
return (size_t)fileSize;
@ -1069,8 +1345,7 @@ typedef struct {
const char* dictFileName;
stat_t dictFileStat;
ZSTD_CStream* cctx;
WritePoolCtx_t *writeCtx;
ReadPoolCtx_t *readCtx;
FIO_SyncCompressIO io;
} cRess_t;
/** ZSTD_cycleLog() :
@ -1138,8 +1413,7 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs,
dictBufferType = (useMMap && !forceNoUseMMap) ? FIO_mmapDict : FIO_mallocDict;
FIO_initDict(&ress.dict, dictFileName, prefs, &ress.dictFileStat, dictBufferType); /* works with dictFileName==NULL */
ress.writeCtx = AIO_WritePool_create(prefs, ZSTD_CStreamOutSize());
ress.readCtx = AIO_ReadPool_create(prefs, ZSTD_CStreamInSize());
FIO_SyncCompressIO_init(&ress.io, prefs, ZSTD_CStreamInSize(), ZSTD_CStreamOutSize());
/* Advanced parameters, including dictionary */
if (dictFileName && (ress.dict.dictBuffer==NULL))
@ -1183,7 +1457,7 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs,
#ifdef ZSTD_MULTITHREAD
DISPLAYLEVEL(5,"set nb workers = %u \n", prefs->nbWorkers);
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_nbWorkers, prefs->nbWorkers) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, prefs->blockSize) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, prefs->jobSize) );
if (prefs->overlapLog != FIO_OVERLAP_LOG_NOTSET) {
DISPLAYLEVEL(3,"set overlapLog = %u \n", prefs->overlapLog);
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_overlapLog, prefs->overlapLog) );
@ -1203,21 +1477,20 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs,
static void FIO_freeCResources(cRess_t* const ress)
{
FIO_freeDict(&(ress->dict));
AIO_WritePool_free(ress->writeCtx);
AIO_ReadPool_free(ress->readCtx);
FIO_SyncCompressIO_destroy(&ress->io);
ZSTD_freeCStream(ress->cctx); /* never fails */
}
#ifdef ZSTD_GZCOMPRESS
static unsigned long long
FIO_compressGzFrame(const cRess_t* ress, /* buffers & handlers are used, but not changed */
FIO_compressGzFrame(cRess_t* ress,
const char* srcFileName, U64 const srcFileSize,
int compressionLevel, U64* readsize)
{
FIO_SyncCompressIO* const syncIO = &ress->io;
unsigned long long inFileSize = 0, outFileSize = 0;
z_stream strm;
IOJob_t *writeJob = NULL;
if (compressionLevel > Z_BEST_COMPRESSION)
compressionLevel = Z_BEST_COMPRESSION;
@ -1233,37 +1506,36 @@ FIO_compressGzFrame(const cRess_t* ress, /* buffers & handlers are used, but no
EXM_THROW(71, "zstd: %s: deflateInit2 error %d \n", srcFileName, ret);
} }
writeJob = AIO_WritePool_acquireJob(ress->writeCtx);
strm.next_in = 0;
strm.avail_in = 0;
strm.next_out = (Bytef*)writeJob->buffer;
strm.avail_out = (uInt)writeJob->bufferSize;
strm.next_out = (Bytef*)syncIO->outBuffer;
strm.avail_out = (uInt)syncIO->outCapacity;
while (1) {
int ret;
if (strm.avail_in == 0) {
AIO_ReadPool_fillBuffer(ress->readCtx, ZSTD_CStreamInSize());
if (ress->readCtx->srcBufferLoaded == 0) break;
inFileSize += ress->readCtx->srcBufferLoaded;
strm.next_in = (z_const unsigned char*)ress->readCtx->srcBuffer;
strm.avail_in = (uInt)ress->readCtx->srcBufferLoaded;
size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, ZSTD_CStreamInSize());
if (syncIO->srcBufferLoaded == 0) break;
inFileSize += added;
*readsize += added;
strm.next_in = (z_const unsigned char*)syncIO->srcBuffer;
strm.avail_in = (uInt)syncIO->srcBufferLoaded;
}
{
size_t const availBefore = strm.avail_in;
ret = deflate(&strm, Z_NO_FLUSH);
AIO_ReadPool_consumeBytes(ress->readCtx, availBefore - strm.avail_in);
FIO_SyncCompressIO_consumeBytes(syncIO, availBefore - strm.avail_in);
}
if (ret != Z_OK)
EXM_THROW(72, "zstd: %s: deflate error %d \n", srcFileName, ret);
{ size_t const cSize = writeJob->bufferSize - strm.avail_out;
{ size_t const cSize = (size_t)((uInt)syncIO->outCapacity - strm.avail_out);
if (cSize) {
writeJob->usedBufferSize = cSize;
AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, cSize);
outFileSize += cSize;
strm.next_out = (Bytef*)writeJob->buffer;
strm.avail_out = (uInt)writeJob->bufferSize;
strm.next_out = (Bytef*)syncIO->outBuffer;
strm.avail_out = (uInt)syncIO->outCapacity;
} }
if (srcFileSize == UTIL_FILESIZE_UNKNOWN) {
DISPLAYUPDATE_PROGRESS(
@ -1279,13 +1551,12 @@ FIO_compressGzFrame(const cRess_t* ress, /* buffers & handlers are used, but no
while (1) {
int const ret = deflate(&strm, Z_FINISH);
{ size_t const cSize = writeJob->bufferSize - strm.avail_out;
{ size_t const cSize = (size_t)((uInt)syncIO->outCapacity - strm.avail_out);
if (cSize) {
writeJob->usedBufferSize = cSize;
AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, cSize);
outFileSize += cSize;
strm.next_out = (Bytef*)writeJob->buffer;
strm.avail_out = (uInt)writeJob->bufferSize;
strm.next_out = (Bytef*)syncIO->outBuffer;
strm.avail_out = (uInt)syncIO->outCapacity;
} }
if (ret == Z_STREAM_END) break;
if (ret != Z_BUF_ERROR)
@ -1297,8 +1568,7 @@ FIO_compressGzFrame(const cRess_t* ress, /* buffers & handlers are used, but no
EXM_THROW(79, "zstd: %s: deflateEnd error %d \n", srcFileName, ret);
} }
*readsize = inFileSize;
AIO_WritePool_releaseIoJob(writeJob);
AIO_WritePool_sparseWriteEnd(ress->writeCtx);
FIO_SyncCompressIO_finish(syncIO);
return outFileSize;
}
#endif
@ -1310,11 +1580,11 @@ FIO_compressLzmaFrame(cRess_t* ress,
const char* srcFileName, U64 const srcFileSize,
int compressionLevel, U64* readsize, int plain_lzma)
{
FIO_SyncCompressIO* const syncIO = &ress->io;
unsigned long long inFileSize = 0, outFileSize = 0;
lzma_stream strm = LZMA_STREAM_INIT;
lzma_action action = LZMA_RUN;
lzma_ret ret;
IOJob_t *writeJob = NULL;
if (compressionLevel < 0) compressionLevel = 0;
if (compressionLevel > 9) compressionLevel = 9;
@ -1332,37 +1602,35 @@ FIO_compressLzmaFrame(cRess_t* ress,
EXM_THROW(83, "zstd: %s: lzma_easy_encoder error %d", srcFileName, ret);
}
writeJob =AIO_WritePool_acquireJob(ress->writeCtx);
strm.next_out = (BYTE*)writeJob->buffer;
strm.avail_out = writeJob->bufferSize;
strm.next_out = (BYTE*)syncIO->outBuffer;
strm.avail_out = syncIO->outCapacity;
strm.next_in = 0;
strm.avail_in = 0;
while (1) {
if (strm.avail_in == 0) {
size_t const inSize = AIO_ReadPool_fillBuffer(ress->readCtx, ZSTD_CStreamInSize());
if (ress->readCtx->srcBufferLoaded == 0) action = LZMA_FINISH;
inFileSize += inSize;
strm.next_in = (BYTE const*)ress->readCtx->srcBuffer;
strm.avail_in = ress->readCtx->srcBufferLoaded;
size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, ZSTD_CStreamInSize());
if (syncIO->srcBufferLoaded == 0) action = LZMA_FINISH;
inFileSize += added;
*readsize += added;
strm.next_in = (BYTE const*)syncIO->srcBuffer;
strm.avail_in = syncIO->srcBufferLoaded;
}
{
size_t const availBefore = strm.avail_in;
ret = lzma_code(&strm, action);
AIO_ReadPool_consumeBytes(ress->readCtx, availBefore - strm.avail_in);
FIO_SyncCompressIO_consumeBytes(syncIO, availBefore - strm.avail_in);
}
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
EXM_THROW(84, "zstd: %s: lzma_code encoding error %d", srcFileName, ret);
{ size_t const compBytes = writeJob->bufferSize - strm.avail_out;
{ size_t const compBytes = syncIO->outCapacity - strm.avail_out;
if (compBytes) {
writeJob->usedBufferSize = compBytes;
AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, compBytes);
outFileSize += compBytes;
strm.next_out = (BYTE*)writeJob->buffer;
strm.avail_out = writeJob->bufferSize;
strm.next_out = (BYTE*)syncIO->outBuffer;
strm.avail_out = syncIO->outCapacity;
} }
if (srcFileSize == UTIL_FILESIZE_UNKNOWN)
DISPLAYUPDATE_PROGRESS("\rRead : %u MB ==> %.2f%%",
@ -1378,8 +1646,7 @@ FIO_compressLzmaFrame(cRess_t* ress,
lzma_end(&strm);
*readsize = inFileSize;
AIO_WritePool_releaseIoJob(writeJob);
AIO_WritePool_sparseWriteEnd(ress->writeCtx);
FIO_SyncCompressIO_finish(syncIO);
return outFileSize;
}
@ -1400,21 +1667,20 @@ FIO_compressLz4Frame(cRess_t* ress,
int compressionLevel, int checksumFlag,
U64* readsize)
{
FIO_SyncCompressIO* const syncIO = &ress->io;
const size_t blockSize = FIO_LZ4_GetBlockSize_FromBlockId(LZ4F_max64KB);
unsigned long long inFileSize = 0, outFileSize = 0;
LZ4F_preferences_t prefs;
LZ4F_compressionContext_t ctx;
IOJob_t* writeJob = AIO_WritePool_acquireJob(ress->writeCtx);
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));
assert(blockSize <= ress->readCtx->base.jobBufferSize);
assert(blockSize <= syncIO->inCapacity);
/* autoflush off to mitigate a bug in lz4<=1.9.3 for compression level 12 */
prefs.autoFlush = 0;
@ -1425,25 +1691,26 @@ FIO_compressLz4Frame(cRess_t* ress,
#if LZ4_VERSION_NUMBER >= 10600
prefs.frameInfo.contentSize = (srcFileSize==UTIL_FILESIZE_UNKNOWN) ? 0 : srcFileSize;
#endif
assert(LZ4F_compressBound(blockSize, &prefs) <= writeJob->bufferSize);
assert(LZ4F_compressBound(blockSize, &prefs) <= syncIO->outCapacity);
{
size_t headerSize = LZ4F_compressBegin(ctx, writeJob->buffer, writeJob->bufferSize, &prefs);
size_t headerSize = LZ4F_compressBegin(ctx, syncIO->outBuffer, syncIO->outCapacity, &prefs);
if (LZ4F_isError(headerSize))
EXM_THROW(33, "File header generation failed : %s",
LZ4F_getErrorName(headerSize));
writeJob->usedBufferSize = headerSize;
AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, headerSize);
outFileSize += headerSize;
/* Read first block */
inFileSize += AIO_ReadPool_fillBuffer(ress->readCtx, blockSize);
{
size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, blockSize);
inFileSize += added;
*readsize += added;
}
/* Main Loop */
while (ress->readCtx->srcBufferLoaded) {
size_t inSize = MIN(blockSize, ress->readCtx->srcBufferLoaded);
size_t const outSize = LZ4F_compressUpdate(ctx, writeJob->buffer, writeJob->bufferSize,
ress->readCtx->srcBuffer, inSize, NULL);
while (syncIO->srcBufferLoaded) {
size_t const inSize = MIN(blockSize, syncIO->srcBufferLoaded);
size_t const outSize = LZ4F_compressUpdate(ctx, syncIO->outBuffer, syncIO->outCapacity,
syncIO->srcBuffer, inSize, NULL);
if (LZ4F_isError(outSize))
EXM_THROW(35, "zstd: %s: lz4 compression failed : %s",
srcFileName, LZ4F_getErrorName(outSize));
@ -1458,30 +1725,27 @@ FIO_compressLz4Frame(cRess_t* ress,
(double)outFileSize/(double)inFileSize*100);
}
/* Write Block */
writeJob->usedBufferSize = outSize;
AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, outSize);
/* Read next block */
AIO_ReadPool_consumeBytes(ress->readCtx, inSize);
inFileSize += AIO_ReadPool_fillBuffer(ress->readCtx, blockSize);
FIO_SyncCompressIO_consumeBytes(syncIO, inSize);
{
size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, blockSize);
inFileSize += added;
*readsize += added;
}
}
/* End of Stream mark */
headerSize = LZ4F_compressEnd(ctx, writeJob->buffer, writeJob->bufferSize, NULL);
headerSize = LZ4F_compressEnd(ctx, syncIO->outBuffer, syncIO->outCapacity, NULL);
if (LZ4F_isError(headerSize))
EXM_THROW(38, "zstd: %s: lz4 end of file generation failed : %s",
srcFileName, LZ4F_getErrorName(headerSize));
writeJob->usedBufferSize = headerSize;
AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, headerSize);
outFileSize += headerSize;
}
*readsize = inFileSize;
LZ4F_freeCompressionContext(ctx);
AIO_WritePool_releaseIoJob(writeJob);
AIO_WritePool_sparseWriteEnd(ress->writeCtx);
FIO_SyncCompressIO_finish(syncIO);
return outFileSize;
}
@ -1490,12 +1754,11 @@ FIO_compressLz4Frame(cRess_t* ress,
static unsigned long long
FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
FIO_prefs_t* const prefs,
const cRess_t* ressPtr,
cRess_t* ress,
const char* srcFileName, U64 fileSize,
int compressionLevel, U64* readsize)
{
cRess_t const ress = *ressPtr;
IOJob_t* writeJob = AIO_WritePool_acquireJob(ressPtr->writeCtx);
FIO_SyncCompressIO* const syncIO = &ress->io;
U64 compressedfilesize = 0;
ZSTD_EndDirective directive = ZSTD_e_continue;
@ -1520,16 +1783,16 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
/* init */
if (fileSize != UTIL_FILESIZE_UNKNOWN) {
pledgedSrcSize = fileSize;
CHECK(ZSTD_CCtx_setPledgedSrcSize(ress.cctx, fileSize));
CHECK(ZSTD_CCtx_setPledgedSrcSize(ress->cctx, fileSize));
} else if (prefs->streamSrcSize > 0) {
/* unknown source size; use the declared stream size */
pledgedSrcSize = prefs->streamSrcSize;
CHECK( ZSTD_CCtx_setPledgedSrcSize(ress.cctx, prefs->streamSrcSize) );
CHECK( ZSTD_CCtx_setPledgedSrcSize(ress->cctx, prefs->streamSrcSize) );
}
{ int windowLog;
UTIL_HumanReadableSize_t windowSize;
CHECK(ZSTD_CCtx_getParameter(ress.cctx, ZSTD_c_windowLog, &windowLog));
CHECK(ZSTD_CCtx_getParameter(ress->cctx, ZSTD_c_windowLog, &windowLog));
if (windowLog == 0) {
if (prefs->ldmFlag) {
/* If long mode is set without a window size libzstd will set this size internally */
@ -1547,12 +1810,12 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
do {
size_t stillToFlush;
/* Fill input Buffer */
size_t const inSize = AIO_ReadPool_fillBuffer(ress.readCtx, ZSTD_CStreamInSize());
ZSTD_inBuffer inBuff = setInBuffer( ress.readCtx->srcBuffer, ress.readCtx->srcBufferLoaded, 0 );
size_t const inSize = FIO_SyncCompressIO_fillBuffer(syncIO, ZSTD_CStreamInSize());
ZSTD_inBuffer inBuff = setInBuffer( syncIO->srcBuffer, syncIO->srcBufferLoaded, 0 );
DISPLAYLEVEL(6, "fread %u bytes from source \n", (unsigned)inSize);
*readsize += inSize;
if ((ress.readCtx->srcBufferLoaded == 0) || (*readsize == fileSize))
if ((syncIO->srcBufferLoaded == 0) || (*readsize == fileSize))
directive = ZSTD_e_end;
stillToFlush = 1;
@ -1560,10 +1823,10 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
|| (directive == ZSTD_e_end && stillToFlush != 0) ) {
size_t const oldIPos = inBuff.pos;
ZSTD_outBuffer outBuff = setOutBuffer( writeJob->buffer, writeJob->bufferSize, 0 );
size_t const toFlushNow = ZSTD_toFlushNow(ress.cctx);
CHECK_V(stillToFlush, ZSTD_compressStream2(ress.cctx, &outBuff, &inBuff, directive));
AIO_ReadPool_consumeBytes(ress.readCtx, inBuff.pos - oldIPos);
ZSTD_outBuffer outBuff = setOutBuffer( syncIO->outBuffer, syncIO->outCapacity, 0 );
size_t const toFlushNow = ZSTD_toFlushNow(ress->cctx);
CHECK_V(stillToFlush, ZSTD_compressStream2(ress->cctx, &outBuff, &inBuff, directive));
FIO_SyncCompressIO_consumeBytes(syncIO, inBuff.pos - oldIPos);
/* count stats */
inputPresented++;
@ -1574,14 +1837,13 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
DISPLAYLEVEL(6, "ZSTD_compress_generic(end:%u) => input pos(%u)<=(%u)size ; output generated %u bytes \n",
(unsigned)directive, (unsigned)inBuff.pos, (unsigned)inBuff.size, (unsigned)outBuff.pos);
if (outBuff.pos) {
writeJob->usedBufferSize = outBuff.pos;
AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, outBuff.pos);
compressedfilesize += outBuff.pos;
}
/* adaptive mode : statistics measurement and speed correction */
if (prefs->adaptiveMode && UTIL_clockSpanMicro(lastAdaptTime) > adaptEveryMicro) {
ZSTD_frameProgression const zfp = ZSTD_getFrameProgression(ress.cctx);
ZSTD_frameProgression const zfp = ZSTD_getFrameProgression(ress->cctx);
lastAdaptTime = UTIL_getTime();
@ -1654,14 +1916,14 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
if (compressionLevel > ZSTD_maxCLevel()) compressionLevel = ZSTD_maxCLevel();
if (compressionLevel > prefs->maxAdaptLevel) compressionLevel = prefs->maxAdaptLevel;
compressionLevel += (compressionLevel == 0); /* skip 0 */
ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, compressionLevel);
ZSTD_CCtx_setParameter(ress->cctx, ZSTD_c_compressionLevel, compressionLevel);
}
if (speedChange == faster) {
DISPLAYLEVEL(6, "faster speed , lighter compression \n")
compressionLevel --;
if (compressionLevel < prefs->minAdaptLevel) compressionLevel = prefs->minAdaptLevel;
compressionLevel -= (compressionLevel == 0); /* skip 0 */
ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, compressionLevel);
ZSTD_CCtx_setParameter(ress->cctx, ZSTD_c_compressionLevel, compressionLevel);
}
speedChange = noChange;
@ -1671,7 +1933,7 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
/* display notification */
if (SHOULD_DISPLAY_PROGRESS() && READY_FOR_UPDATE()) {
ZSTD_frameProgression const zfp = ZSTD_getFrameProgression(ress.cctx);
ZSTD_frameProgression const zfp = ZSTD_getFrameProgression(ress->cctx);
double const cShare = (double)zfp.produced / (double)(zfp.consumed + !zfp.consumed/*avoid div0*/) * 100;
UTIL_HumanReadableSize_t const buffered_hrs = UTIL_makeHumanReadableSize(zfp.ingested - zfp.consumed);
UTIL_HumanReadableSize_t const consumed_hrs = UTIL_makeHumanReadableSize(zfp.consumed);
@ -1718,8 +1980,7 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
(unsigned long long)*readsize, (unsigned long long)fileSize);
}
AIO_WritePool_releaseIoJob(writeJob);
AIO_WritePool_sparseWriteEnd(ressPtr->writeCtx);
FIO_SyncCompressIO_finish(syncIO);
return compressedfilesize;
}
@ -1732,7 +1993,7 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
static int
FIO_compressFilename_internal(FIO_ctx_t* const fCtx,
FIO_prefs_t* const prefs,
cRess_t ress,
cRess_t* ress,
const char* dstFileName, const char* srcFileName,
int compressionLevel)
{
@ -1747,12 +2008,12 @@ FIO_compressFilename_internal(FIO_ctx_t* const fCtx,
switch (prefs->compressionType) {
default:
case FIO_zstdCompression:
compressedfilesize = FIO_compressZstdFrame(fCtx, prefs, &ress, srcFileName, fileSize, compressionLevel, &readsize);
compressedfilesize = FIO_compressZstdFrame(fCtx, prefs, ress, srcFileName, fileSize, compressionLevel, &readsize);
break;
case FIO_gzipCompression:
#ifdef ZSTD_GZCOMPRESS
compressedfilesize = FIO_compressGzFrame(&ress, srcFileName, fileSize, compressionLevel, &readsize);
compressedfilesize = FIO_compressGzFrame(ress, srcFileName, fileSize, compressionLevel, &readsize);
#else
(void)compressionLevel;
EXM_THROW(20, "zstd: %s: file cannot be compressed as gzip (zstd compiled without ZSTD_GZCOMPRESS) -- ignored \n",
@ -1763,7 +2024,7 @@ FIO_compressFilename_internal(FIO_ctx_t* const fCtx,
case FIO_xzCompression:
case FIO_lzmaCompression:
#ifdef ZSTD_LZMACOMPRESS
compressedfilesize = FIO_compressLzmaFrame(&ress, srcFileName, fileSize, compressionLevel, &readsize, prefs->compressionType==FIO_lzmaCompression);
compressedfilesize = FIO_compressLzmaFrame(ress, srcFileName, fileSize, compressionLevel, &readsize, prefs->compressionType==FIO_lzmaCompression);
#else
(void)compressionLevel;
EXM_THROW(20, "zstd: %s: file cannot be compressed as xz/lzma (zstd compiled without ZSTD_LZMACOMPRESS) -- ignored \n",
@ -1773,7 +2034,7 @@ FIO_compressFilename_internal(FIO_ctx_t* const fCtx,
case FIO_lz4Compression:
#ifdef ZSTD_LZ4COMPRESS
compressedfilesize = FIO_compressLz4Frame(&ress, srcFileName, fileSize, compressionLevel, prefs->checksumFlag, &readsize);
compressedfilesize = FIO_compressLz4Frame(ress, srcFileName, fileSize, compressionLevel, prefs->checksumFlag, &readsize);
#else
(void)compressionLevel;
EXM_THROW(20, "zstd: %s: file cannot be compressed as lz4 (zstd compiled without ZSTD_LZ4COMPRESS) -- ignored \n",
@ -1829,7 +2090,7 @@ FIO_compressFilename_internal(FIO_ctx_t* const fCtx,
*/
static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
FIO_prefs_t* const prefs,
cRess_t ress,
cRess_t* ress,
const char* dstFileName,
const char* srcFileName,
const stat_t* srcFileStat,
@ -1840,8 +2101,7 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
int transferStat = 0;
int dstFd = -1;
assert(AIO_ReadPool_getFile(ress.readCtx) != NULL);
if (AIO_WritePool_getFile(ress.writeCtx) == NULL) {
if (ress->io.dstFile == NULL) {
int dstFileInitialPermissions = DEFAULT_FILE_PERMISSIONS;
if ( strcmp (srcFileName, stdinmark)
&& strcmp (dstFileName, stdoutmark)
@ -1852,15 +2112,13 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
closeDstFile = 1;
DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s \n", dstFileName);
{ FILE *dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFileInitialPermissions);
{
FILE *dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFileInitialPermissions);
if (dstFile==NULL) return 1; /* could not open dstFileName */
dstFd = fileno(dstFile);
AIO_WritePool_setFile(ress.writeCtx, dstFile);
FIO_SyncCompressIO_setDst(&ress->io, dstFile);
}
/* Must only be added after FIO_openDstFile() succeeds.
* Otherwise we may delete the destination file if it already exists,
* and the user presses Ctrl-C when asked if they wish to overwrite.
*/
/* Must only be added after FIO_openDstFile() succeeds. */
addHandler(dstFileName);
}
@ -1874,7 +2132,7 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
}
DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: closing dst: %s \n", dstFileName);
if (AIO_WritePool_closeFile(ress.writeCtx)) { /* error closing file */
if (FIO_SyncCompressIO_closeDst(&ress->io)) { /* error closing file */
DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno));
result=1;
}
@ -1883,10 +2141,9 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
UTIL_utime(dstFileName, srcFileStat);
}
if ( (result != 0) /* operation failure */
&& strcmp(dstFileName, stdoutmark) /* special case : don't remove() stdout */
) {
FIO_removeFile(dstFileName); /* remove compression artefact; note don't do anything special if remove() fails */
if ( (result != 0)
&& strcmp(dstFileName, stdoutmark) ) {
FIO_removeFile(dstFileName);
}
}
@ -2020,7 +2277,7 @@ static const char *compressedFileExtensions[] = {
static int
FIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,
FIO_prefs_t* const prefs,
cRess_t ress,
cRess_t* ress,
const char* dstFileName,
const char* srcFileName,
int compressionLevel)
@ -2042,7 +2299,7 @@ FIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,
}
/* ensure src is not the same as dict (if present) */
if (ress.dictFileName != NULL && UTIL_isSameFileStat(srcFileName, ress.dictFileName, &srcFileStat, &ress.dictFileStat)) {
if (ress->dictFileName != NULL && UTIL_isSameFileStat(srcFileName, ress->dictFileName, &srcFileStat, &ress->dictFileStat)) {
DISPLAYLEVEL(1, "zstd: cannot use %s as an input file and dictionary \n", srcFileName);
return 1;
}
@ -2061,23 +2318,21 @@ FIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,
srcFile = FIO_openSrcFile(prefs, srcFileName, &srcFileStat);
if (srcFile == NULL) return 1; /* srcFile could not be opened */
/* Don't use AsyncIO for small files */
if (strcmp(srcFileName, stdinmark)) /* Stdin doesn't have stats */
fileSize = UTIL_getFileSizeStat(&srcFileStat);
if(fileSize != UTIL_FILESIZE_UNKNOWN && fileSize < ZSTD_BLOCKSIZE_MAX * 3) {
AIO_ReadPool_setAsync(ress.readCtx, 0);
AIO_WritePool_setAsync(ress.writeCtx, 0);
} else {
AIO_ReadPool_setAsync(ress.readCtx, 1);
AIO_WritePool_setAsync(ress.writeCtx, 1);
}
(void)fileSize;
AIO_ReadPool_setFile(ress.readCtx, srcFile);
FIO_SyncCompressIO_setSrc(&ress->io, srcFile);
result = FIO_compressFilename_dstFile(
fCtx, prefs, ress,
dstFileName, srcFileName,
&srcFileStat, compressionLevel);
AIO_ReadPool_closeFile(ress.readCtx);
FIO_SyncCompressIO_clearSrc(&ress->io);
if (srcFile != NULL && fclose(srcFile)) {
DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno));
return 1;
}
if ( prefs->removeSrcFile /* --rm */
&& result == 0 /* success */
@ -2118,7 +2373,7 @@ void FIO_displayCompressionParameters(const FIO_prefs_t* prefs)
DISPLAY("%s", INDEX(sparseOptions, prefs->sparseFileSupport));
DISPLAY("%s", prefs->dictIDFlag ? "" : " --no-dictID");
DISPLAY("%s", INDEX(checkSumOptions, prefs->checksumFlag));
DISPLAY(" --block-size=%d", prefs->blockSize);
DISPLAY(" --jobsize=%d", prefs->jobSize);
if (prefs->adaptiveMode)
DISPLAY(" --adapt=min=%d,max=%d", prefs->minAdaptLevel, prefs->maxAdaptLevel);
DISPLAY("%s", INDEX(rowMatchFinderOptions, prefs->useRowMatchFinder));
@ -2144,9 +2399,11 @@ int FIO_compressFilename(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs, const
int compressionLevel, ZSTD_compressionParameters comprParams)
{
cRess_t ress = FIO_createCResources(prefs, dictFileName, UTIL_getFileSize(srcFileName), compressionLevel, comprParams);
int const result = FIO_compressFilename_srcFile(fCtx, prefs, ress, dstFileName, srcFileName, compressionLevel);
int const result = FIO_compressFilename_srcFile(fCtx, prefs, &ress, dstFileName, srcFileName, compressionLevel);
#define DISPLAY_LEVEL_DEFAULT 2
#ifndef ZSTD_DISPLAY_LEVEL_DEFAULT
# define ZSTD_DISPLAY_LEVEL_DEFAULT 2
#endif
FIO_freeCResources(&ress);
return result;
@ -2241,13 +2498,13 @@ int FIO_compressMultipleFilenames(FIO_ctx_t* const fCtx,
if (dstFile == NULL) { /* could not open outFileName */
error = 1;
} else {
AIO_WritePool_setFile(ress.writeCtx, dstFile);
FIO_SyncCompressIO_setDst(&ress.io, dstFile);
for (; fCtx->currFileIdx < fCtx->nbFilesTotal; ++fCtx->currFileIdx) {
status = FIO_compressFilename_srcFile(fCtx, prefs, ress, outFileName, inFileNamesTable[fCtx->currFileIdx], compressionLevel);
status = FIO_compressFilename_srcFile(fCtx, prefs, &ress, outFileName, inFileNamesTable[fCtx->currFileIdx], compressionLevel);
if (!status) fCtx->nbFilesProcessed++;
error |= status;
}
if (AIO_WritePool_closeFile(ress.writeCtx))
if (FIO_SyncCompressIO_closeDst(&ress.io))
EXM_THROW(29, "Write error (%s) : cannot properly close %s",
strerror(errno), outFileName);
}
@ -2271,7 +2528,7 @@ int FIO_compressMultipleFilenames(FIO_ctx_t* const fCtx,
} else {
dstFileName = FIO_determineCompressedName(srcFileName, outDirName, suffix); /* cannot fail */
}
status = FIO_compressFilename_srcFile(fCtx, prefs, ress, dstFileName, srcFileName, compressionLevel);
status = FIO_compressFilename_srcFile(fCtx, prefs, &ress, dstFileName, srcFileName, compressionLevel);
if (!status) fCtx->nbFilesProcessed++;
error |= status;
}

View file

@ -70,7 +70,7 @@ void FIO_setAdaptiveMode(FIO_prefs_t* const prefs, int adapt);
void FIO_setAdaptMin(FIO_prefs_t* const prefs, int minCLevel);
void FIO_setAdaptMax(FIO_prefs_t* const prefs, int maxCLevel);
void FIO_setUseRowMatchFinder(FIO_prefs_t* const prefs, int useRowMatchFinder);
void FIO_setBlockSize(FIO_prefs_t* const prefs, int blockSize);
void FIO_setJobSize(FIO_prefs_t* const prefs, int jobSize);
void FIO_setChecksumFlag(FIO_prefs_t* const prefs, int checksumFlag);
void FIO_setDictIDFlag(FIO_prefs_t* const prefs, int dictIDFlag);
void FIO_setLdmBucketSizeLog(FIO_prefs_t* const prefs, int ldmBucketSizeLog);

View file

@ -37,7 +37,7 @@ typedef struct FIO_prefs_s {
int sparseFileSupport; /* 0: no sparse allowed; 1: auto (file yes, stdout no); 2: force sparse */
int dictIDFlag;
int checksumFlag;
int blockSize;
int jobSize;
int overlapLog;
int adaptiveMode;
int useRowMatchFinder;

View file

@ -35,6 +35,7 @@
|| defined __x86_64__ || defined _M_X64 /* x86 64-bit */ \
|| defined __arm64__ || defined __aarch64__ || defined __ARM64_ARCH_8__ /* ARM 64-bit */ \
|| (defined __mips && (__mips == 64 || __mips == 4 || __mips == 3)) /* MIPS 64-bit */ \
|| (defined(__riscv) && __riscv_xlen == 64) /* RISC-V 64-bit */ \
|| defined _LP64 || defined __LP64__ /* NetBSD, OpenBSD */ || defined __64BIT__ /* AIX */ || defined _ADDR64 /* Cray */ \
|| (defined __SIZEOF_POINTER__ && __SIZEOF_POINTER__ == 8) /* gcc */
# if !defined(__64BIT__)

Some files were not shown because too many files have changed in this diff Show more