Compare commits

..
243 Commits
Author SHA1 Message Date
Nick TerrellandGitHub 83b51e9f88 Merge pull request #1586 from facebook/dev
v1.4.0
2019-04-16 15:37:24 -07:00
Nick TerrellandGitHub b85f7d7790 Merge pull request #1589 from terrelln/appveyorTest
[libzstd] Require ZSTD_MULTITHREAD to create a ZSTDMT_CCtx
2019-04-16 12:32:19 -07:00
Nick Terrell a17fe4c9e5 [visual] Fix unreachable code warning 2019-04-16 11:32:35 -07:00
Yann ColletandGitHub 41ad46f1a9 Merge pull request #1588 from terrelln/release-prep
[fullbench] Fix speed measurements
2019-04-16 10:11:28 -07:00
Nick Terrell 82d5a9870e [visual] Compile with ZSTD_MULTITHREAD=1
This branch `appveyorTests` runs the tests that `master` runs, so
passing Appveyor means that the tests are fixed.
2019-04-15 23:04:46 -07:00
Nick Terrell de0499f7fa [libzstd] Require ZSTD_MULTITHREAD to create a ZSTDMT_CCtx
ZSTDMT was broken when compiled without ZSTD_MULTITHREAD defined,
because `ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbWorkerss)`
failed. It was detected by the MSVC test which runs the fuzzer with
multithreading disabled.

This is a very niche use case of a deprecated API, because the API is
inefficient and synchronous, since `threading.h` will be synchronous.
Users almost certainly don't want this, and anyone who tested their code
should realize that it is broken. Therefore, I think it is safe to
require `ZSTD_MULTITHREAD` to be defined to use ZSTDMT.
2019-04-15 23:04:46 -07:00
Nick Terrell a48e32ca50 [fullbench] Fix measurements 2019-04-15 21:01:48 -07:00
Nick TerrellandGitHub a821aee3b1 Merge pull request #1587 from terrelln/release-prep
[playTets] Don't pass status=none to dd
2019-04-15 16:42:26 -07:00
Nick Terrell 6996804d05 [playTets] Don't pass status=none to dd
The OS X test machine on TravisCI doesn't recognize the parameter
https://travis-ci.org/facebook/zstd/jobs/520517933.
2019-04-15 16:21:46 -07:00
Nick TerrellandGitHub d86c7ad458 Merge pull request #1585 from terrelln/release-prep
Prepare for the zstd-1.4.0 release
2019-04-15 14:41:50 -07:00
Nick Terrell bef61221a3 Update the changelog for zstd-1.4.0 2019-04-15 14:33:46 -07:00
Nick Terrell 203aac5bc6 Update benchmarks in README 2019-04-15 13:57:14 -07:00
Josh SorefandNick Terrell a880ca239b Spelling (#1582)
* spelling: accidentally

* spelling: across

* spelling: additionally

* spelling: addresses

* spelling: appropriate

* spelling: assumed

* spelling: available

* spelling: builder

* spelling: capacity

* spelling: compiler

* spelling: compressibility

* spelling: compressor

* spelling: compression

* spelling: contract

* spelling: convenience

* spelling: decompress

* spelling: description

* spelling: deflate

* spelling: deterministically

* spelling: dictionary

* spelling: display

* spelling: eliminate

* spelling: preemptively

* spelling: exclude

* spelling: failure

* spelling: independence

* spelling: independent

* spelling: intentionally

* spelling: matching

* spelling: maximum

* spelling: meaning

* spelling: mishandled

* spelling: memory

* spelling: occasionally

* spelling: occurrence

* spelling: official

* spelling: offsets

* spelling: original

* spelling: output

* spelling: overflow

* spelling: overridden

* spelling: parameter

* spelling: performance

* spelling: probability

* spelling: receives

* spelling: redundant

* spelling: recompression

* spelling: resources

* spelling: sanity

* spelling: segment

* spelling: series

* spelling: specified

* spelling: specify

* spelling: subtracted

* spelling: successful

* spelling: return

* spelling: translation

* spelling: update

* spelling: unrelated

* spelling: useless

* spelling: variables

* spelling: variety

* spelling: verbatim

* spelling: verification

* spelling: visited

* spelling: warming

* spelling: workers

* spelling: with
2019-04-12 11:18:11 -07:00
Nick TerrellandGitHub 13fddac46d Merge pull request #1583 from lzutao/meson
Fix tests and meson build
2019-04-12 11:13:20 -07:00
Lzu Tao e31e7ca9ed travis: Make Mesonbuild non-optional 2019-04-12 23:43:34 +07:00
Lzu Tao 6c9b023f3e meson: Fix build 2019-04-12 21:28:36 +07:00
Lzu Tao fb6901b2c0 tests: Add missing header timefn.h 2019-04-12 21:28:17 +07:00
Yann ColletandGitHub 8ac2831f3d Merge pull request #1581 from facebook/benchfn
benchfn's reduced dependencies
2019-04-11 14:23:04 -07:00
Yann Collet 1e01560b83 fixed timespec_get() initialization bug on some targets
not sure why, but msan fires an "unitialized variable" error
when time gets properly initialized by timespec_get().
Maybe in some cases, not all bytes of the structure are initialized ?
Or maybe msan fails to detect the initialization ?

Anyway, pre-initializing the variable before passing it to timespec_get() works.
2019-04-11 13:46:30 -07:00
Yann Collet 058da605cb fixed minor conversion warning 2019-04-11 12:25:27 -07:00
Yann Collet f8e9bec73a fixed poolTests on Windows
must use ZSTD_ prefix in front of pthread types
so that they get properly translated for Windows.
2019-04-11 12:03:42 -07:00
Yann Collet 8f56fa2f58 fixed poolTests
added poolTests to all
2019-04-11 09:50:39 -07:00
Nick TerrellandGitHub 9563fb4bfc Merge pull request #1580 from terrelln/dict-fuzz
[libzstd] Fix decompression dictionary bugs and clean up initialization
2019-04-10 19:29:09 -07:00
Yann Collet 30c26ab726 fixed minor warning
unused variable when assert() turned off in fileio.c
2019-04-10 17:48:56 -07:00
Yann Collet fbdd30d68e fixed cmake build script for test programs 2019-04-10 17:47:01 -07:00
Nick Terrell aafe97b67d [libzstd] Switch dictUses to an enum 2019-04-10 16:50:35 -07:00
Yann Collet 526ec646b7 alternate static assert
to circumvent Visual's C4804 warning
2019-04-10 16:05:02 -07:00
Yann Collet 9703a59121 fixed minor conversion warning 2019-04-10 15:54:55 -07:00
Yann Collet 885476fb5b FreeBSD_11 specific fix
C11 mandates the definition of timespec_get() and TIME_UTC.
However, FreeBSD11 announce C11 compliance, but does not provifr timespec_get(),
breaking link stage for benchfn.
Since it does not provide TIME_UTC either, which is also required by C11,
test this macro: this will automatically rule out FreeBSD 11 for this code path
(it will use the backup C90 path instead, based on clock_t).

The issue seeems fixed in FreeBSD 12.
2019-04-10 15:22:18 -07:00
Yann Collet 2fa4f2e246 updated Visual projects
added timefn
2019-04-10 15:07:36 -07:00
Yann Collet 2c6b14ed22 fixed Windows header
cmake build script: added timefn
2019-04-10 14:54:13 -07:00
Yann Collet 3d346579d8 no more need for CLOCK_MONOTONIC 2019-04-10 14:16:39 -07:00
Yann Collet 36d2dfd846 moved C11 code path to timespec_get 2019-04-10 14:15:11 -07:00
Yann Collet 4765929271 fixed perror include 2019-04-10 14:04:11 -07:00
Yann Collet 70802cde6d fixed error message
using stdlib's perror()
2019-04-10 14:01:18 -07:00
Yann Collet 4b8185c7fc tried a blindfix for unix + c11 2019-04-10 13:26:27 -07:00
Nick Terrell 50b9c41196 [libzstd] Fix decompression dictionary bugs and clean up initialization
Bugs:

* `ZSTD_DCtx_refPrefix()` didn't clear the dictionary after the first
  use. Fix and add a test case.
* `ZSTD_DCtx_reset()` always cleared the dictionary. Fix and add a test
  case.
* After calling `ZSTD_resetDStream()` you could no longer load a
  dictionary, since the stage was set to `zdss_loadHeader`. Fix and add
  a test case.

Cleanup:

* Make `ZSTD_initDStream*()` and `ZSTD_resetDStream()` wrap the new
 advanced API, and add test cases.
* Document the equivalent of these functions in the advanced API and
  document the unstable functions as deprecated.
2019-04-10 12:59:02 -07:00
Yann Collet 59a7116cc2 benchfn dependencies reduced to only timefn
benchfn used to rely on mem.h, and util,
which in turn relied on platform.h.
Using benchfn outside of zstd required to bring all these dependencies.

Now, dependency is reduced to timefn only.
This required to create a separate timefn from util,
and rewrite benchfn and timefn to no longer need mem.h.

Separating timefn from util has a wide effect accross the code base,
as usage of time functions is widespread.
A lot of build scripts had to be updated to also include timefn.
2019-04-10 12:37:03 -07:00
Yann Collet 094c000904 Merge branch 'dev' into benchfn 2019-04-10 11:57:05 -07:00
Nick TerrellandGitHub f86d4bd1d5 Merge pull request #1576 from terrelln/dict-fuzz
Add new fuzzers and fix exposed bugs
2019-04-10 11:29:15 -07:00
Nick TerrellandGitHub 5f6ca3c6ce Merge pull request #1578 from orip/r-flag-typo
Fixed `-r` typo
2019-04-10 11:19:02 -07:00
Yann Collet 90c0462d63 minor presentation refactoring
and removed some // comment style
2019-04-10 10:03:06 -07:00
Ori Peleg bdeb4786b5 Fixed -r typo 2019-04-10 13:37:41 +03:00
Nick Terrell c45dec12c5 [fuzzer] Use ZSTD_DCtx_loadDictionary_advanced() half the time 2019-04-09 18:02:22 -07:00
Nick Terrell 10a3d4dca9 [fuzzer] Make the regression_driver work while fuzzers are active 2019-04-09 18:01:49 -07:00
Nick Terrell 824aaa695f [libzstd] Fix ZSTD_decompressDCtx() with a dictionary
* `ZSTD_decompressDCtx()` did not use the dictionary loaded by
  `ZSTD_DCtx_loadDictionary()`.
* Add a unit test.
* A stacked diff uses `ZSTD_decompressDCtx()` in the
  `dictionary_round_trip` and `dictionary_decompress` fuzzers.
2019-04-09 17:59:27 -07:00
Nick Terrell c5d70b7dbb [fuzzer] Sometimes fuzz with one less output byte
Zstd compression sometimes does different stuff when it has at least
`ZSTD_compressBound()` output bytes, or not. Half of the time fuzz with
`ZSTD_compressBound() - 1` output bytes. Ensure that we have at least
one byte of overhead by disabling either the dictionary ID or checksum.
2019-04-09 16:47:59 -07:00
Nick Terrell 48a6427d22 [libzstd] Fix ZSTD_compress2() for multithreaded compression
`ZSTD_compress2()` wouldn't wait for multithreaded compression to
finish. We didn't find this because ZSTDMT will block when it can
compress all in one go, but it can't do that if it doesn't have enough
output space, or if `ZSTD_c_rsyncable` is enabled.

Since we will already sometimes block when using `ZSTD_e_end`, I've
changed `ZSTD_e_end` and `ZSTD_e_flush` to guarantee maximum forward
progress. This simplifies the API, and helps users avoid the easy bug
that was made in `ZSTD_compress2()`

* Found by the libfuzzer fuzzers.
* Added a test case that catches the problem.
* I will make the fuzzers sometimes allocate less than
  `ZSTD_compressBound()` output space.
2019-04-09 16:24:17 -07:00
Nick Terrell 7a1fde2957 [fuzzer] Add dictionary fuzzers 2019-04-08 21:07:28 -07:00
Nick Terrell 462918560c [fuzzer] Fix stream_round_trip for the new options 2019-04-08 21:06:19 -07:00
Nick Terrell f871b5144e [fuzz] Use the new advanced API 2019-04-08 20:01:38 -07:00
Nick Terrell e649fad7aa [dictBuilder] Fix displayLevel for corpus warning
Pass the displaylevel into the corpus warning, because it is used in
fast cover and cover, so it needs to respect the local level.
2019-04-08 20:00:18 -07:00
Nick Terrell bfcd5b81d7 [libzstd] Don't check the dictID in fuzzing mode
When `FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` is defined don't check
the dictID. This check makes the fuzzers job harder, and it is at the
very beginning.
2019-04-08 19:57:41 -07:00
Nick TerrellandGitHub 1a90133b15 Merge pull request #1575 from terrelln/zstdmt
[libzstd] Remove ZSTDMT from the shared library
2019-04-08 16:51:40 -07:00
Nick Terrell 947548c24f Remove double the from README 2019-04-08 16:50:18 -07:00
Nick Terrell 641e594309 [libzstd] Remove ZSTDMT from the shared object
* Remove ZSTDMT from the shared object by default.
* Provide a macro `ZSTD_LEGACY_MULTITHREADED_API` to override it.
* Document it in `lib/README.md`.
2019-04-07 18:47:52 -07:00
Nick TerrellandGitHub d5910a5d94 Merge pull request #1574 from terrelln/examples
Stabilize ZSTD_getDictID_*() functions and clean up examples
2019-04-05 23:29:32 -07:00
Nick Terrell 1d0c1707d1 [examples] Clean up and comment the examples 2019-04-05 21:02:07 -07:00
Nick Terrell 1dfe37fea9 [libzstd] Stabilize ZSTD_getDictID_*() functions 2019-04-05 18:59:30 -07:00
Nick Terrell ce388fe4d2 [libzstd] Fix return value docs for ZSTD_compressStream2() 2019-04-05 17:44:07 -07:00
Nick TerrellandGitHub a63aaaa2cc Merge pull request #1573 from terrelln/regression
[regression] Update results.csv for level 1 change
2019-04-05 11:06:35 -07:00
Nick TerrellandGitHub dbc8a59a0a Merge pull request #1569 from terrelln/stable
Stabilize the advanced API
2019-04-05 10:47:48 -07:00
Nick Terrell 50c634b86e [regression] Update results.csv for level 1 change 2019-04-05 10:46:22 -07:00
Nick Terrell 7231ea72a8 [libzstd] Reword the streaming docs for the new API 2019-04-03 19:21:05 -07:00
Nick Terrell cf7d601bf5 Move the dictionary API and mark the legacy API
* Move the dictionary API below the streaming API
* Mark the legacy streaming API as redundant
2019-04-03 19:16:40 -07:00
Nick Terrell d7d89513d6 Stabilize advance API
This commit moves the candidate advanced API to the stable section.
It makes some minor whitespace changes, but it doesn't change any
of the wording of the documentation.

I'll put up a separate PR that tweaks some of the documentation
once this lands, so that it is easier to review.

NOTE: Even though these functions are now in stable, they aren't
stable until the next release (in under 1 month). It is possible
that they change until then.
2019-04-03 18:43:20 -07:00
Nick Terrell 0827edeace [libzstd] Bump the library version to 1.4.0
Bumps the library version to 1.4.0 in preparation to stabilize the
advanced API.
2019-04-03 18:43:20 -07:00
Nick TerrellandGitHub 72a3fbc0e4 Merge pull request #1562 from terrelln/2fast
[libzstd] Speed up single segment zstd_fast by 5%
2019-04-03 18:08:15 -07:00
Nick TerrellandGitHub 56261001ea Merge pull request #1567 from terrelln/examples2
[examples] Update streaming_decompression.c
2019-04-03 11:27:49 -07:00
Yann ColletandGitHub 816a3f47c7 Merge pull request #1568 from terrelln/examples3
Update streaming_memory_usage.c and fix ZSTD_estimateCStreamSize_usingCCtxParams()
2019-04-03 09:07:13 -07:00
Nick Terrell cdc8ae2e9b [examples] Update streaming_memory_usage.c
Update to use the new streaming API. Making progress on Issue #1548.

Tested that the checks don't fail.
Tested with window log 9-32. The lowest and highest fail as expected.
2019-04-02 19:20:57 -07:00
Nick Terrell 00679da22b [libzstd] Setting ZSTD_d_maxWindowLog to 0 means default 2019-04-02 19:20:52 -07:00
Nick TerrellandNick Terrell 95624b77e4 [libzstd] Speed up single segment zstd_fast by 5%
This PR is based on top of PR #1563.

The optimization is to process two input pointers per loop.
It is based on ideas from [igzip] level 1, and talking to @gbtucker.

| Platform                | Silesia     | Enwik8 |
|-------------------------|-------------|--------|
| OSX clang-10            | +5.3%       | +5.4%  |
| i9 5 GHz gcc-8          | +6.6%       | +6.6%  |
| i9 5 GHz clang-7        | +8.0%       | +8.0%  |
| Skylake 2.4 GHz gcc-4.8 | +6.3%       | +7.9%  |
| Skylake 2.4 GHz clang-7 | +6.2%       | +7.5%  |

Testing on all Silesia files on my Intel i9-9900k with gcc-8

| Silesia File | Ratio Change | Speed Change |
|--------------|--------------|--------------|
| silesia.tar  | +0.17%       | +6.6%        |
| dickens      | +0.25%       | +7.0%        |
| mozilla      | +0.02%       | +6.8%        |
| mr           | -0.30%       | +10.9%       |
| nci          | +1.28%       | +4.5%        |
| ooffice      | -0.35%       | +10.7%       |
| osdb         | +0.75%       | +9.8%        |
| reymont      | +0.65%       | +4.6%        |
| samba        | +0.70%       | +5.9%        |
| sao          | -0.01%       | +14.0%       |
| webster      | +0.30%       | +5.5%        |
| xml          | +0.92%       | +5.3%        |
| x-ray        | -0.00%       | +1.4%        |

Same tests on Calgary. For brevity, I've only included files
where compression ratio regressed or was much better.

| Calgary File | Ratio Change | Speed Change |
|--------------|--------------|--------------|
| calgary.tar  | +0.30%       | +7.1%        |
| geo          | -0.14%       | +25.0%       |
| obj1         | -0.46%       | +15.2%       |
| obj2         | -0.18%       | +6.0%        |
| pic          | +1.80%       | +9.3%        |
| trans        | -0.35%       | +5.5%        |

We gain 0.1% of compression ratio on Silesia.
We gain 0.3% of compression ratio on enwik8.
I also tested on the GitHub and hg-commands datasets without a dictionary,
and we gain a small amount of compression ratio on each, as well as speed.

I tested the negative compression levels on Silesia on my
Intel i9-9900k with gcc-8:

| Level | Ratio Change | Speed Change |
|-------|--------------|--------------|
| -1    | +0.13%       | +6.4%        |
| -2    | +4.6%        | -1.5%        |
| -3    | +7.5%        | -4.8%        |
| -4    | +8.5%        | -6.9%        |
| -5    | +9.1%        | -9.1%        |

Roughly, the negative levels now scale half as quickly. E.g. the new
level 16 is roughly equivalent to the old level 8, but a bit quicker
and smaller.  If you don't think this is the right trade off, we can
change it to multiply the step size by 2, instead of adding 1. I think
this makes sense, because it gives a bit slower ratio decay.

[igzip]: https://github.com/01org/isa-l/tree/master/igzip
2019-04-02 19:02:50 -07:00
Nick Terrell de58910b5a [examples] Update streaming_decompression.c
Update to use the new streaming API. Making progress on Issue #1548.

Tested that it can decompress files produced by `streaming_compression`.
Tested that it can decompress two frames concatenated together.
Tested that it fails on corrupted data.
2019-04-02 18:52:59 -07:00
Nick TerrellandGitHub 882ceb86bc Merge pull request #1566 from terrelln/examples
[examples] Update multiple_streaming_compression.c
2019-04-02 17:13:10 -07:00
Nick Terrell 56682a7709 Fix ZSTD_estimateCStreamSize_usingCCtxParams()
It wasn't using the ZSTD_CCtx_params correctly. It must actualize
the compression parameters by calling ZSTD_getCParamsFromCCtxParams()
to get the real window log.

Tested by updating the streaming memory usage example in the next
commit. The CHECK() failed before this patch, and passes after.

I also added a unit test to zstreamtest.c that failed before this
patch, and passes after.
2019-04-01 18:02:52 -07:00
Nick Terrell 04325cbc2f Fix indentation 2019-04-01 17:33:49 -07:00
Nick Terrell fb13d757af [examples] Update multiple_streaming_compression.c
Update to use the new streaming API. Making progress on Issue #1548.

Tested that multiple files could be compressed, and that the output
is the same as calling `streaming_compression` multiple times with
the same compression level, and that it can be decompressed.
2019-04-01 16:41:06 -07:00
Nick TerrellandGitHub 425ce5547c Merge pull request #1563 from terrelln/dms-sep
[libzstd] Split out zstd_fast dict match state function
2019-03-29 16:19:21 -06:00
Nick Terrell f00407b640 Split out zstd_fast dict match state function 2019-03-29 10:39:16 -06:00
Nick TerrellandGitHub 6625f3b390 Merge pull request #1561 from shakeelrao/fix-typo
Update comments in zstd.h and fileio.c
2019-03-28 23:42:16 -06:00
shakeelrao dca73db30c fix srcSize typo and add new UTIL func to comment 2019-03-28 17:50:34 -07:00
Nick TerrellandGitHub dcc6c7e9ae Merge pull request #1556 from terrelln/dictbuilder
[cover] Improvements for small or homogeneous data
2019-03-25 15:08:32 -07:00
Nick TerrellandGitHub 440f390cba Merge pull request #1557 from terrelln/examples
[examples] Update streaming_compression to the new API
2019-03-25 15:07:35 -07:00
Nick TerrellandGitHub 7186a50775 Merge pull request #1559 from shakeelrao/reject-dict
[CLI] ensure dictionary and input file are different
2019-03-25 15:06:58 -07:00
shakeelrao 44f77b5c71 Add whitespace to test case 2019-03-24 03:42:11 -07:00
shakeelrao b25d7eacf2 Rename test 2019-03-24 03:40:03 -07:00
shakeelrao 2b4491d81a Add CLI test to validate error 2019-03-24 00:47:13 -07:00
shakeelrao 5333e41ab3 Add NULL check for dict 2019-03-24 00:23:50 -07:00
shakeelrao 8ea219d8c6 Modify error msg 2019-03-23 21:59:30 -07:00
shakeelrao 1290933d19 Implement file check 2019-03-23 21:53:13 -07:00
shakeelrao e5811e5520 Extract file comparison into utility func 2019-03-23 19:04:56 -07:00
Nick TerrellandNick Terrell f5cbee988b [examples] Update streaming_compression to the new API 2019-03-23 15:59:26 -07:00
Nick TerrellandGitHub d97605ad85 Merge pull request #1558 from nehaljwani/fix-version-soversion-libzstd
[libzstd] Specify soversion and version corectly for CMake build
2019-03-23 13:32:39 -07:00
Nehal J Wani 7ac2052dbc [libzstd] Specify soversion and version correctly for CMake build
Fixes #1512
2019-03-23 17:37:37 +05:30
Nick Terrell d0f5ba36fb [cover] Improvements for small or homogeneous data
* The algorithm would bail as soon as it found one epoch that
  contained no new segments. Change it so it now has to fail
  >= 10 times in a row (10 for fastcover, 10-100 for cover).
* The algorithm uses the `maxDict` size to decide the epoch size.
  When this size is absurdly large, it causes tiny epochs. Lower
  bound the epoch size at 10x the segment size, and warn the user
  that their training set is too small.

Fixes #1554
2019-03-22 14:14:46 -07:00
Nick TerrellandGitHub 0c7668cd06 Merge pull request #1555 from terrelln/load-dict
[lib] Allow ZSTD_CCtx_loadDictionary() to be called before parameters are set
2019-03-21 17:52:57 -07:00
Nick Terrell 6b053b9f60 [lib] Allow ZSTD_CCtx_loadDictionary() to be called before parameters are set
* After loading a dictionary only create the cdict once we've started the
  compression job. This allows the user to pass the dictionary before they
  set other settings, and is in line with the rest of the API.
* Add tests that mix the 3 dictionary loading APIs.
* Add extra tests for `ZSTD_CCtx_loadDictionary()`.
* The first 2 tests added fail before this patch.
* Run the regression test suite.
2019-03-21 16:13:53 -07:00
Nick TerrellandGitHub 041bc0bdb7 Merge pull request #1551 from terrelln/stream-wrap
Refactor old stream API to completely wrap the advanced API
2019-03-21 16:10:00 -07:00
Nick Terrell 20f9ff7e53 Update documentation to tell how to replace the old streaming API with the new one. 2019-03-21 16:08:58 -07:00
Nick Terrell e55da9e963 Wrap the new advanced api completely 2019-03-21 10:54:40 -07:00
Nick Terrell 11e73576bb [regression] Add more streaming tests
* Test all of the `ZSTD_initCStream*()` variants.
* Fix a typo in the zstdcli method.
2019-03-21 10:54:18 -07:00
Nick TerrellandGitHub 0dd3588acc Merge pull request #1553 from shakeelrao/legacy-bound
Add legacy support to decompressBound
2019-03-19 10:53:12 -07:00
shakeelrao 186ded6d91 Fix typo in legacy documentation 2019-03-19 01:44:08 -07:00
shakeelrao 5740eb6769 Remove extraneous spacing in comments 2019-03-18 21:05:35 -07:00
shakeelrao 0a3fa6f909 Add legacy mode in documentation 2019-03-18 20:33:15 -07:00
shakeelrao 20aa1b455c Stylistic changes 2019-03-17 19:35:43 -07:00
shakeelrao 0033bb4785 Update documentation for ZSTD_frameSizeInfo 2019-03-17 17:41:27 -07:00
shakeelrao 19b75b6ecb Test new ZSTD_findFrameCompressedSize and update documentation 2019-03-15 18:04:19 -07:00
shakeelrao 8cd423a659 Reorder declaration in ZSTD_findFrameSizeInfoLegacy 2019-03-15 16:20:34 -07:00
shakeelrao 60796e76b0 Add legacy support to decompressBound 2019-03-15 16:10:37 -07:00
Nick TerrellandGitHub f52a7d8faa Merge pull request #1547 from shakeelrao/fix-error
Fix incorrect error code in ZSTD_errorFrameSizeInfo
2019-03-15 10:57:49 -07:00
shakeelrao 4c0540da1c Add static linking to legacy tests 2019-03-15 05:13:55 -07:00
shakeelrao 91ffc8d256 Add test to validate patch 2019-03-15 03:59:03 -07:00
Nick TerrellandGitHub 45139e9fd5 Merge pull request #1550 from terrelln/cparams-cdict
[libzstd] Allow compression parameters to be set with a cdict
2019-03-13 19:17:22 -07:00
Nick Terrell 18fbcddd0c [zstreamtest] Remove outdated test 2019-03-13 17:01:23 -07:00
Nick Terrell 787b76904a [libzstd] Allow compression parameters to be set with a cdict
The order you set parameters in the advanced API is not supposed to matter.
However, once you call `ZSTD_CCtx_refCDict()` the compression parameters
cannot be changed. Remove that restriction, and document what parameters
are used when using a CDict.

If the CCtx is in dictionary mode, then the CDict's parameters are used.
If the CCtx is not in dictionary mode, then its requested parameters are
used.
2019-03-13 16:10:05 -07:00
Nick TerrellandGitHub ea3b81f02c Merge pull request #1549 from terrelln/ref-cdict-free
[libzstd] Free local cdict when referencing cdict
2019-03-13 16:08:54 -07:00
Nick Terrell 0594e8135b [libzstd] Free local cdict when referencing cdict
We no longer care about the `cdictLocal` after calling
`ZSTD_CCtx_refCDict()`, so we should free it to save some
memory.
2019-03-13 14:54:31 -07:00
shakeelrao 18d3a97d43 Add unit test to validate the error case 2019-03-13 01:43:40 -07:00
shakeelrao 79827a179f Fix incorrectly assigned value in ZSTD_errorFrameSizeInfo
As documented in `zstd.h`, ZSTD_decompressBound returns `ZSTD_CONTENTSIZE_ERROR`
if an error occurs (not `ZSTD_CONTENTSIZE_UNKNOWN`). This is consistent with
the error checking made in ZSTD_decompressBound, particularly line 545.
2019-03-13 01:23:07 -07:00
Nick TerrellandGitHub 13cc7c610e Merge pull request #1543 from shakeelrao/dev
Provide a function to estimate decompressed size.
2019-03-04 08:00:47 -08:00
shakeelrao 9ad3f31d33 update documentation for decompressBound 2019-03-02 17:56:10 -08:00
shakeelrao 95dfd48143 update formatting 2019-03-01 23:11:15 -08:00
shakeelrao 3da3dc2f45 add missing size content test 2019-03-01 21:27:30 -08:00
shakeelrao 1e08c49f75 add stylistic changes 2019-03-01 18:29:35 -08:00
shakeelrao 2bb5eec711 update missing error case to CONTENTSIZE_ERROR 2019-03-01 00:12:16 -08:00
shakeelrao 44ae395b3e change nbBlocks to size_t for consistency 2019-03-01 00:05:59 -08:00
shakeelrao 03026c3b1d change compressedBound to ULL 2019-03-01 00:03:50 -08:00
shakeelrao 8930c3c79b implement API-level changes 2019-02-28 22:55:18 -08:00
Nick TerrellandGitHub 8b7fa49590 Merge pull request #1541 from terrelln/fuzz
[fuzz] Add --enable-fuzzer for clang fuzzing
2019-02-28 11:25:27 -08:00
shakeelrao dce9a09772 initialize local vars in decompressBound 2019-02-28 03:01:21 -08:00
shakeelrao 515c506b4c switch frameBound type to ULL 2019-02-28 02:10:17 -08:00
shakeelrao d0a3f25697 change return type to ULL 2019-02-28 01:52:01 -08:00
shakeelrao c9d674b60d Remove autogenerated test file 2019-02-28 01:29:04 -08:00
shakeelrao 97d3d28dab Fix decl-after-stmnt build error 2019-02-28 01:24:54 -08:00
shakeelrao 820af1e078 Provide an API function to estimate decompressed size.
Introduces a new utility function `ZSTD_findFrameCompressedSize_internal` which
is equivalent to `ZSTD_findFrameCompressSize`, but accepts an additional output
parameter `bound` that computes an upper-bound for the compressed data in the frame.

The new API function is named `ZSTD_decompressBound` to be consistent with
`zstd_compressBound` (the inverse operation). Clients will now be able to compute an upper-bound for
their compressed payloads instead of guessing a large size.

Implements https://github.com/facebook/zstd/issues/1536.
2019-02-28 00:42:49 -08:00
Nick Terrell 4b0024a97d [fuzz] Add --enable-fuzzer for clang fuzzing 2019-02-27 17:15:52 -08:00
Nick TerrellandGitHub be3bd70c57 Merge pull request #1532 from terrelln/cctx-params
[libzstd] Rename ZSTD_CCtxParam_* to ZSTD_CCtxParams_*
2019-02-20 10:46:46 -08:00
Nick Terrell 2e8c19f6a3 Update changelog 2019-02-20 10:46:14 -08:00
Nick TerrellandGitHub a36d9302ce Merge pull request #1531 from terrelln/appveyorTest
Fixes for Windows release
2019-02-19 19:42:07 -08:00
Nick Terrell 7ad7ba3178 [libzstd] Rename ZSTD_CCtxParam_* to ZSTD_CCtxParams_* 2019-02-19 17:44:52 -08:00
Nick Terrell 9f9630f455 [Windows] Don't use a .def file 2019-02-19 16:52:38 -08:00
Nick Terrell 0c86d23467 [Windows] Move public headers to include/ 2019-02-19 15:49:48 -08:00
Nick TerrellandGitHub eb3a7a3827 Merge pull request #1530 from terrelln/param-order
Clean up parameter code
2019-02-19 14:40:10 -08:00
Nick Terrell 6efce7c9ca [fuzzer] Add test cases 2019-02-19 13:22:44 -08:00
Nick Terrell f4abba02ba [libzstd] Clean up parameter code
* Move all ZSTDMT parameter setting code to ZSTD_CCtxParams_*Parameter().
  ZSTDMT now calls these functions, so we can keep all the logic in the
  same place.
* Clean up `ZSTD_CCtx_setParameter()` to only add extra checks where needed.
* Clean up `ZSTDMT_initJobCCtxParams()` by copying all parameters by default,
  and then zeroing the ones that need to be zeroed. We've missed adding several
  parameters here, and it makes more sense to only have to update it if you
  change something in ZSTDMT.
* Add `ZSTDMT_cParam_clampBounds()` to clamp a parameter into its valid
  range. Use this to keep backwards compatibility when setting ZSTDMT parameters,
  which clamp into the valid range.
2019-02-19 13:22:37 -08:00
Nick TerrellandGitHub 54e9412ddd Merge pull request #1525 from terrelln/enable-huf-flag
Fix optimal parser prices with uncompressed literals
2019-02-15 20:21:08 -05:00
Nick Terrell 19ca3fbc03 [zstdcli] Respect --[no-]compress-literals in benchmark mode 2019-02-15 16:27:39 -08:00
Nick Terrell 0c53c5ad4a [zstdcli] Add a flag to control literals compression 2019-02-15 15:00:45 -08:00
Nick Terrell 5261a288d1 Fix a bug in the compress cctx method 2019-02-15 14:58:19 -08:00
Nick Terrell 3d7377b874 [libzstd] Handle uncompressed literals 2019-02-15 14:58:11 -08:00
Nick Terrell a96e67af6c [regression] Test level 19 with uncompressed literals 2019-02-15 10:52:46 -08:00
Nick TerrellandGitHub 4c870b70fc Merge pull request #1522 from terrelln/enable-huf-flag
Add ZSTD_c_literalCompressionMode flag
2019-02-13 19:02:32 -05:00
Nick Terrell dbaa7042d9 [regression] Test ZSTD_c_literalCompressionMode
Test a positive compression level with uncompressed literals,
and a negative compression level with compressed literals.

I double checked the `results.csv` and made sure that the compressed
sizes make sense.
2019-02-13 15:00:32 -08:00
Nick Terrell f9513115e4 [libzstd] Add ZSTD_c_literalCompressionMode flag
It controls the literals compression. It is either
`auto`, `huffman`, or `uncompressed`. It defaults to
`auto`, which is the current behavior.
2019-02-13 14:59:22 -08:00
Nick TerrellandGitHub ae7380d2af Merge pull request #1519 from terrelln/play-bsd
[cirrus] Run playTests.sh
2019-02-13 16:21:14 -05:00
Nick Terrell e1a799e5de [util] Fix UTIL_isLink() for FreeBSD 2019-02-11 17:44:10 -08:00
Nick Terrell 9c071664ad [cirrus] Run playTests.sh
* Pass `-Werror` through `MOREFLAGS`
* Install `coreutils`
* Run `playTests.sh`
2019-02-11 17:44:00 -08:00
Nick TerrellandGitHub 32a98bafdc Merge pull request #1521 from bket/lstat
Detection of symbolic links on OpenBSD
2019-02-11 20:38:49 -05:00
Björn Ketelaars 77d9109c27 Add test
While here enable symlink test for OpenBSD.
2019-02-12 01:56:05 +01:00
Björn Ketelaars 482b84f07b Make detection of symbolic links more consistent
While fixing the detection of symbolic links on OpenBSD I noticed
inconsistent behaviour:

$ echo hello > hello
$ ln -s hello world
$ zstd hello world
Warning : world is a symbolic link, ignoring
hello                :316.67%   (     6 =>     19 bytes, hello.zst
$ ls *.zst
hello.zst
$ zstd world
world                :316.67%   (     6 =>     19 bytes, world.zst)
$ ls *.zst
hello.zst world.zst
2019-02-12 01:56:05 +01:00
Björn Ketelaars 1e4dc2e5f1 Detect symbolic links on OpenBSD
In #1520 it is described that FreeBSD doesn't detect symbolic links. The
same is true for OpenBSD. This diff fixes this issue for OpenBSD. I'm
guessing that something similar works for FreeBSD as well. However, I'm
unable to test this.
2019-02-12 01:56:05 +01:00
Nick TerrellandGitHub a17369c7dc Merge pull request #1518 from bket/non-portable
'head -c BYTES' is non portable
2019-02-11 15:43:03 -05:00
Björn Ketelaars b26c53b0d0 'head -c BYTES' is non-portable.
Pull request #1499 added a new test, which uses 'head -c'. The '-c'
option is non-portable (not in POSIX). Instead use 'dd'. Similar issue
has been resolved in the past (#1321).
2019-02-11 12:00:26 +01:00
Nick TerrellandGitHub 197a5737c8 Merge pull request #1516 from terrelln/dict-doc
[zdict] Improve documentation
2019-02-01 19:04:05 -05:00
Nick Terrell 21616d8a77 [zdict] Improve documentation 2019-02-01 15:19:32 -08:00
Nick TerrellandGitHub 5c1148a6a5 Merge pull request #1515 from thatsafunnyname/patch-1
-Wformat-security not needed with -Wformat=2
2019-02-01 13:41:27 -05:00
Peter (Stig) EdwardsandGitHub cdb3e7af2f -Wformat-security not needed with -Wformat=2 2019-02-01 09:38:49 +00:00
Peter (Stig) EdwardsandGitHub 1951c1b3a0 -Wformat-security not needed with -Wformat=2 2019-02-01 09:31:46 +00:00
Peter (Stig) EdwardsandGitHub 894bbda44c -Wformat-security not needed with -Wformat=2 2019-02-01 09:31:02 +00:00
Peter (Stig) EdwardsandGitHub 188c748208 -Wformat-security not needed with -Wformat=2 2019-02-01 09:30:31 +00:00
Peter (Stig) EdwardsandGitHub 723418f8d8 -Wformat-security not needed with -Wformat=2 2019-02-01 09:29:40 +00:00
Peter (Stig) EdwardsandGitHub 4a9e0502e6 -Wformat-security not needed with -Wformat=2 2019-02-01 09:29:08 +00:00
Peter (Stig) EdwardsandGitHub 2b7120ec71 -Wformat-security not needed with -Wformat=2 2019-02-01 09:28:41 +00:00
Peter (Stig) EdwardsandGitHub 2ff9249810 -Wformat-security not needed with -Wformat=2 2019-02-01 09:27:22 +00:00
Yann Collet fb756156f5 fixed static size of benchFnState
added a static assert to ensure condition is respected on target platform
2019-01-30 17:59:07 -08:00
Nick TerrellandGitHub fafa322456 Merge pull request #1511 from lwhsu/cirrus-ci
Change Cirrus CI's badge to dev branch
2019-01-30 16:53:13 -05:00
Li-Wen Hsu 1a6f2b4f7f Change Cirrus CI's badge to dev branch 2019-01-31 05:37:04 +08:00
Nick TerrellandGitHub 79463a65e9 Merge pull request #1501 from lwhsu/cirrus-ci
Add Cirrus-CI config and build status badge for testing on FreeBSD
2019-01-30 14:15:02 -05:00
Yann ColletandGitHub a940e78f16 Merge pull request #1509 from felixhandte/verbose-errors
Add Debug Information to Error Checks
2019-01-29 11:32:24 -08:00
W. Felix Handte 501eb25102 Rename FORWARD_ERROR -> FORWARD_IF_ERROR 2019-01-29 12:56:07 -05:00
W. Felix Handte 429987c9a6 Add Comment 2019-01-28 17:35:31 -05:00
W. Felix Handte 2179ce00e1 Remove CHECK_E Macro 2019-01-28 17:33:13 -05:00
W. Felix Handte 03e040a966 Replace Uses of CHECK_E with RETURN_ERROR_IF(*_isError(... 2019-01-28 17:33:01 -05:00
W. Felix Handte 7ebd897157 Remove CHECK_F Macro 2019-01-28 17:16:32 -05:00
W. Felix Handte 64bb6640f2 Replace CHECK_F Uses in zstdmt_compress.c and zstd_ddict.c 2019-01-28 17:15:57 -05:00
Yann ColletandGitHub 6cf253fb52 Merge pull request #1508 from facebook/fileio_lz4
fixed fileio.c compilation with LZ4 enabled
2019-01-28 14:12:27 -08:00
W. Felix Handte cafc3b1bcb Also Convert zstd_compress.c 2019-01-28 17:05:18 -05:00
W. Felix Handte 324e9654d3 Add grep-able String to Error Macros 2019-01-28 12:50:36 -05:00
W. Felix Handte 32fed9c7be Switch CHECK_F Calls to FORWARD_ERROR 2019-01-28 12:45:34 -05:00
W. Felix Handte 800c87fed0 Switch Unconditional RETURN_ERROR_IF Calls to RETURN_ERROR 2019-01-28 12:45:34 -05:00
W. Felix Handte a3538bbc6f Add RETURN_ERROR and FORWARD_ERROR Macros 2019-01-28 12:45:26 -05:00
W. Felix Handte c823237d7b Convert Checks in zstd_decompress.c to RETURN_ERROR_IF 2019-01-28 12:23:14 -05:00
W. Felix Handte ea031f4ea2 Convert Checks in zstd_decompress_block.c to RETURN_ERROR_IF 2019-01-28 11:56:39 -05:00
W. Felix Handte 54fa31f03b Add RETURN_ERROR_IF Macro That Logs Debug Information When Check Fails 2019-01-28 11:43:33 -05:00
Yann Collet cee31bbd25 updated fullbench and paramgrill
to use new benchfn
returning a double.
2019-01-25 15:38:08 -08:00
Yann Collet b8701102e0 fixed benchzstd to use new version of benchfn
returning a double type
2019-01-25 15:11:50 -08:00
Yann Collet 8c3ba44ada Merge branch 'fileio_lz4' into benchfn 2019-01-25 14:53:56 -08:00
Yann Collet 07e047873e fixed fileio.c compilation with LZ4 enabled
was broken by #1505.

I'm surprised it passed CI tests.
LZ4 tests are part of the "Extended" tests on Travis CI,
which are run on "master" and in "cron" jobs.

Since latest cron job did not failed,
especially this one : https://travis-ci.org/facebook/zstd/jobs/484365040
it suggests cron jobs are no longer using `dev` branch.

To be investigated
2019-01-25 14:42:44 -08:00
Yann Collet f75ad2edcf added ability to create timedFnState on stack 2019-01-25 14:22:25 -08:00
Yann Collet 6b2f26791e updated benchfn.h code comments 2019-01-25 12:18:33 -08:00
Yann ColletandGitHub 2888c62e85 Merge pull request #1505 from kostmo/remove-global-params
Remove global parameters, pass into public functions instead
2019-01-23 17:11:08 -08:00
Karl Ostmo 5e220bf4b5 Remove global parameters, pass into public functions instead 2019-01-23 16:06:27 -08:00
Yann ColletandGitHub 31ba3f7e64 Merge pull request #1504 from facebook/conversionWarnings
Conversion warnings
2019-01-22 10:04:59 -08:00
Yann Collet 54bd39abdf Revert "added clang test in travis"
This reverts commit 4909a341db.
2019-01-20 11:13:01 -08:00
Yann Collet 4909a341db added clang test in travis 2019-01-20 00:11:07 -08:00
Yann Collet 2a6aa6be5f updated clang tests
target clangbuild
2019-01-19 23:40:41 -08:00
Yann Collet a1394399b4 fixed minor conversion warnings in examples/ 2019-01-19 23:38:20 -08:00
Li-Wen Hsu 281c7970ac Add Cirrus-CI build status badge 2019-01-17 03:43:02 +08:00
Li-Wen Hsu 1828c2619c Add Cirrus-CI config for FreeBSD builds 2019-01-17 03:42:14 +08:00
Yann ColletandGitHub bd2740f347 Merge pull request #1499 from kostmo/detect-truncation
fix --list on truncated files
2019-01-16 08:56:22 -08:00
Yann ColletandGitHub ae087ec4bb Merge pull request #1500 from lwhsu/unistd
Include unistd.h on unix platforms for explicit function declaration
2019-01-16 06:21:58 -08:00
Karl Ostmo 4fa585aee3 fix --list on truncated files
fseek() doesn't indicate when it moves past the end of a file.
Consequently, if a file is truncated within its last block, the error would't be detected.

This PR adds a test scenario that induces this situation using a small compressed file of only one block in size.
This test is added to tests/playTests.sh

Check is implemented by ensuring that the filehandle position is equal to the filesize upon exit.
2019-01-15 19:03:29 -08:00
Li-Wen Hsu 6ff9d5e881 Include unistd.h on unix platforms for explicit function declaration 2019-01-16 04:55:43 +08:00
Yann ColletandGitHub f8745ae095 Merge pull request #1496 from hjmjohnson/cmake-improve-conditional-policies
ENH: Simplify conditional logic
2019-01-10 09:35:21 -08:00
Hans Johnson 62c0dd7aff ENH: Simplify conditional logic
Based on excellent comment in #1489, the logic
to set cmake policies was simplified.  This will
provide an easier mechanism for maintaining the
conditional logic across many versions of cmake.
2019-01-08 14:25:56 -06:00
Yann ColletandGitHub c5be47c8c1 Merge pull request #1494 from lzutao/fix-leak
Fix potential leak of 'outBuff' (reported by scan-build)
2019-01-06 17:17:02 -08:00
Yann ColletandGitHub 1cd61ea862 Merge pull request #1493 from lzutao/fix-#1428
Fix #1428 - zstdgrep returned 1 on both matched and unmatched file
2019-01-06 12:37:07 -08:00
Lzu Tao 260ff2f6b7 tests/legagy.c: More fixes 2019-01-06 23:42:24 +07:00
Lzu Tao de7e3be7fa Fix potential leak of 'outBuff' (reported by scan-build) 2019-01-06 23:28:38 +07:00
Lzu Tao 7b6a8840c5 Fix #1428 - zstdgrep returned 1 on match and unmatch
- Use ZCAT for testing zstdgrep in case of non-install yet
- tests: Add file test for zstdgrep
2019-01-06 23:22:55 +07:00
Yann ColletandGitHub f8c8796dfe Merge pull request #1491 from cemeyer/freebsd_num_cores
Fix #1425 - Use physical core count API on FreeBSD
2019-01-05 11:48:01 -08:00
Conrad Meyer fe82637069 Fix #1425 - Use physical core count API on FreeBSD
Similar to Apple, use the native physical core count sysctl, when available.

This is a little repetitive (it's basically the __APPLE__ method plus the
otherBSD method concatenated together) but seemed clearer than any way that
would totally eliminate repetition.

The __FreeBSD_version check only tests the version of the FreeBSD kernel
that zstd is compiled on; importantly, it may be run on a different version.
So the compile-time check is a little naive and needs to be able to fallback
to work on older versions of FreeBSD.  For a similar reason, it may make
sense to simply eliminate the __FreeBSD_version check entirely.  The
tradeoff is that a spurious sysctlbyname would be issued when -T0 is used on
older kernels.
2019-01-04 11:57:12 -08:00
Yann ColletandGitHub b174809fcc Merge pull request #1490 from erikwebb/dev
Check CMake minor version support for VERSION_LESS_EQUAL
2019-01-03 13:22:07 -08:00
Erik Webb 9448a3790d Check CMake minor version support for VERSION_LESS_EQUAL
VERSION_LESS_EQUAL is only available to CMake 3.7+. This adds additional
logic to check that CMAKE_MINOR_VERSION is at least 7.

Fixes #1489
2019-01-03 15:26:20 -05:00
Yann Collet f9e4f89252 improved comments for adjustCParams() and getCParams() 2019-01-02 12:18:40 -08:00
Yann ColletandGitHub a2f492f2b3 Merge pull request #1485 from ldv-alt/dev
contrib/pzstd/Makefile: fix build of tests
2019-01-02 10:46:41 -08:00
Yann ColletandGitHub 282000d88b Merge pull request #1475 from hjmjohnson/cmake-version-setting
Cmake version setting
2018-12-30 21:11:39 -08:00
Hans Johnson 97d1de3d22 Provide forward compatible cmake paradigms
Automatically extract version information
from the zstd.h file.  Use naming of variables
consisent with modern cmake and https://semver.org/
(Semantic Versioning 2.0.0, MAJOR, MINOR, PATCH)

Modern versions of cmake provide consistent
paradigms for configuring project external
interface values.

This set of changes provide a back port of
some of cmake 3+ paradigms back to cmake 2.8.9.
Set and allow use of the current cmake policies
for newer versions of cmake when available to
allow for modern compiler features to be
utilized when available.

NOTE: The intent is that future modifications to
cmake will enable (conditional on cmake version support)
the ability to support modern linkage, and target
export mechanisms.  Those future changes will
make incorporating zstd into other packages
much easier.

This patch also allows the more rigourous error
checking of commmon cmake errors to be preformed
by cmake (i.e. more stringent syntax checking and
create errors for common hard to find misuses of
cmake variables).

This patch also provides support for modern
compiler support options by cmake (like
enabling interprocedural optimization
if link time optimizations are known to be supported
by the compiler envirionment.  IPO can be supported
by setting the CMAKE_INTERPROCEDURAL_OPTIMIZATION variable
for newer versions of cmake.
2018-12-28 13:47:35 -06:00
Dmitry V. Levin 8b2210411a contrib/pzstd/Makefile: fix build of tests
Apparently, Options.o cannot be linked in without $(PROGDIR)/util.o
2018-12-28 19:02:22 +00:00
Yann ColletandGitHub 23c73fe3e2 Merge pull request #1474 from hjmjohnson/cmake-set-default-build-type
Cmake set default build type
2018-12-28 11:02:22 -08:00
Yann ColletandGitHub 6746de8dd6 Merge pull request #1478 from hjmjohnson/remove-duplicates-validation
BUG: list sub-command REMOVE_DUPLICATES requires list to be present
2018-12-28 10:50:03 -08:00
Yann ColletandGitHub c1a862385f Merge pull request #1482 from lzutao/travisTest
travis: Use ninja from official github release
2018-12-28 10:49:01 -08:00
Yann ColletandGitHub bad7ed161a Merge pull request #1483 from lzutao/meson-readme
meson: Update build guide
2018-12-28 09:46:13 -08:00
Yann ColletandGitHub 663c55eba0 Merge pull request #1484 from lzutao/meson-pkgconf
meson: Correct generating pkgconf after Meson v0.49.0
2018-12-27 22:39:07 -08:00
Lzu Tao 142076ceae travis: Remove deprecated sudo field 2018-12-28 11:55:26 +07:00
Lzu Tao 787a72cdfe meson: Correct generating pkgconf after Meson v0.49.0 2018-12-28 11:20:33 +07:00
Lzu Tao 226cdffd69 meson: Update build guide [skip ci] 2018-12-28 11:17:11 +07:00
Lzu Tao 889a492784 travis: Use ninja from github 2018-12-28 10:25:13 +07:00
Yann ColletandGitHub acbd6c0341 Merge pull request #1480 from facebook/dev
v1.3.8
2018-12-27 10:38:31 -08:00
Hans Johnson 1a279ae85a BUG: list sub-command REMOVE_DUPLICATES requires list to be present
When compiling without c++ enabled, some variables are not present.
This is a check enforced in recent Cmake versions.

CMake Error at CMakeModules/AddZstdCompilationFlags.cmake:54 (list):
  list sub-command REMOVE_DUPLICATES requires list to be present.
Call Stack (most recent call first):
  CMakeLists.txt:53 (ADD_ZSTD_COMPILATION_FLAGS)
2018-12-26 13:26:59 -06:00
Hans Johnson 77ef7847f7 Improve setting the default build type
The CMAKE_BUILD_TYPE variable is a CACHE variable
and should be set in a way that persists and is
documented in the CACHE.  Also set the default
values for the gui to ease selection of types.

These changes provide better support for GUI
configurators that support cmake.
2018-12-26 13:23:21 -06:00
150 changed files with 6256 additions and 3524 deletions
+16
View File
@@ -0,0 +1,16 @@
env:
CIRRUS_CLONE_DEPTH: 1
ARCH: amd64
task:
freebsd_instance:
matrix:
image: freebsd-12-0-release-amd64
image: freebsd-11-2-release-amd64
install_script:
- sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf
- pkg upgrade -y
- pkg install -y gmake coreutils
script: |
MOREFLAGS="-Werror" gmake -j all
gmake shortest
+8 -6
View File
@@ -2,7 +2,6 @@
language: c language: c
dist: trusty dist: trusty
sudo: required
git: git:
depth: 1 depth: 1
@@ -179,14 +178,17 @@ matrix:
# meson dedicated test # meson dedicated test
- name: Xenial (Meson + clang) - name: Xenial (Meson + clang)
# env: ALLOW_FAILURES=true
dist: xenial dist: xenial
language: cpp language: cpp
compiler: clang compiler: clang
before_install: install:
- sudo apt-get install -qq liblz4-dev valgrind tree - sudo apt-get install -qq liblz4-dev valgrind tree
- curl -o ~/get-pip.py 'https://bootstrap.pypa.io/get-pip.py' - travis_retry curl -o ~/ninja.zip -L 'https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip'
- python3 ~/get-pip.py --user && unzip ~/ninja.zip -d ~/.local/bin
- pip3 install --user meson ninja - travis_retry curl -o ~/get-pip.py -L 'https://bootstrap.pypa.io/get-pip.py'
&& python3 ~/get-pip.py --user
&& pip3 install --user meson
script: script:
- meson --buildtype=debug - meson --buildtype=debug
-Db_lundef=false -Db_lundef=false
@@ -198,4 +200,4 @@ matrix:
- DESTDIR=./staging ninja install - DESTDIR=./staging ninja install
- tree ./staging - tree ./staging
allow_failures: allow_failures:
- name: Xenial (Meson + clang) - env: ALLOW_FAILURES=true
+38 -1
View File
@@ -1,3 +1,40 @@
v1.4.0
perf: Improve level 1 compression speed in most scenarios by 6% by @gbtucker and @terrelln
api: Move the advanced API, including all functions in the staging section, to the stable section
api: Make ZSTD_e_flush and ZSTD_e_end block for maximum forward progress
api: Rename ZSTD_CCtxParam_getParameter to ZSTD_CCtxParams_getParameter
api: Rename ZSTD_CCtxParam_setParameter to ZSTD_CCtxParams_setParameter
api: Don't export ZSTDMT functions from the shared library by default
api: Require ZSTD_MULTITHREAD to be defined to use ZSTDMT
api: Add ZSTD_decompressBound() to provide an upper bound on decompressed size by @shakeelrao
api: Fix ZSTD_decompressDCtx() corner cases with a dictionary
api: Move ZSTD_getDictID_*() functions to the stable section
api: Add ZSTD_c_literalCompressionMode flag to enable or disable literal compression by @terrelln
api: Allow compression parameters to be set when a dictionary is used
api: Allow setting parameters before or after ZSTD_CCtx_loadDictionary() is called
api: Fix ZSTD_estimateCStreamSize_usingCCtxParams()
api: Setting ZSTD_d_maxWindowLog to 0 means use the default
cli: Ensure that a dictionary is not used to compress itself by @shakeelrao
cli: Add --[no-]compress-literals flag to enable or disable literal compression
doc: Update the examples to use the advanced API
doc: Explain how to transition from old streaming functions to the advanced API in the header
build: Improve the Windows release packages
build: Improve CMake build by @hjmjohnson
build: Build fixes for FreeBSD by @lwhsu
build: Remove redundant warnings by @thatsafunnyname
build: Fix tests on OpenBSD by @bket
build: Extend fuzzer build system to work with the new clang engine
build: CMake now creates the libzstd.so.1 symlink
build: Improve Menson build by @lzutao
misc: Fix symbolic link detection on FreeBSD
misc: Use physical core count for -T0 on FreeBSD by @cemeyer
misc: Fix zstd --list on truncated files by @kostmo
misc: Improve logging in debug mode by @felixhandte
misc: Add CirrusCI tests by @lwhsu
misc: Optimize dictionary memory usage in corner cases
misc: Improve the dictionary builder on small or homogeneous data
misc: Fix spelling across the repo by @jsoref
v1.3.8 v1.3.8
perf: better decompression speed on large files (+7%) and cold dictionaries (+15%) perf: better decompression speed on large files (+7%) and cold dictionaries (+15%)
perf: slightly better compression ratio at high compression modes perf: slightly better compression ratio at high compression modes
@@ -239,7 +276,7 @@ v1.0.0
Change Licensing, all project is now BSD, Copyright Facebook Change Licensing, all project is now BSD, Copyright Facebook
Small decompression speed improvement Small decompression speed improvement
API : Streaming API supports legacy format API : Streaming API supports legacy format
API : ZDICT_getDictID(), ZSTD_sizeof_{CCtx, DCtx, CStream, DStream}(), ZSTD_setDStreamParamter() API : ZDICT_getDictID(), ZSTD_sizeof_{CCtx, DCtx, CStream, DStream}(), ZSTD_setDStreamParameter()
CLI supports legacy formats v0.4+ CLI supports legacy formats v0.4+
Fixed : compression fails on certain huge files, reported by Jesse McGrew Fixed : compression fails on certain huge files, reported by Jesse McGrew
Enhanced documentation, by Przemyslaw Skibinski Enhanced documentation, by Przemyslaw Skibinski
+2 -6
View File
@@ -156,7 +156,7 @@ list:
done \ done \
} | column -t -s $$'\t' } | column -t -s $$'\t'
.PHONY: install clangtest armtest usan asan uasan .PHONY: install armtest usan asan uasan
install: install:
@$(MAKE) -C $(ZSTDDIR) $@ @$(MAKE) -C $(ZSTDDIR) $@
@$(MAKE) -C $(PRGDIR) $@ @$(MAKE) -C $(PRGDIR) $@
@@ -188,7 +188,7 @@ gcc7build: clean
.PHONY: clangbuild .PHONY: clangbuild
clangbuild: clean clangbuild: clean
clang -v clang -v
CXX=clang++ CC=clang $(MAKE) all MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation" CXX=clang++ CC=clang CFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation" $(MAKE) all
m32build: clean m32build: clean
gcc -v gcc -v
@@ -232,10 +232,6 @@ gcc6test: clean
gcc-6 -v gcc-6 -v
$(MAKE) all CC=gcc-6 MOREFLAGS="-Werror" $(MAKE) all CC=gcc-6 MOREFLAGS="-Werror"
clangtest: clean
clang -v
$(MAKE) all CXX=clang++ CC=clang MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation"
armtest: clean armtest: clean
$(MAKE) -C $(TESTDIR) datagen # use native, faster $(MAKE) -C $(TESTDIR) datagen # use native, faster
$(MAKE) -C $(TESTDIR) test CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS="-Werror -static" FUZZER_FLAGS=--no-big-tests $(MAKE) -C $(TESTDIR) test CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS="-Werror -static" FUZZER_FLAGS=--no-big-tests
+14 -11
View File
@@ -14,6 +14,7 @@ a list of known ports and bindings is provided on [Zstandard homepage](http://ww
[![Build Status][travisDevBadge]][travisLink] [![Build Status][travisDevBadge]][travisLink]
[![Build status][AppveyorDevBadge]][AppveyorLink] [![Build status][AppveyorDevBadge]][AppveyorLink]
[![Build status][CircleDevBadge]][CircleLink] [![Build status][CircleDevBadge]][CircleLink]
[![Build status][CirrusDevBadge]][CirrusLink]
[travisDevBadge]: https://travis-ci.org/facebook/zstd.svg?branch=dev "Continuous Integration test suite" [travisDevBadge]: https://travis-ci.org/facebook/zstd.svg?branch=dev "Continuous Integration test suite"
[travisLink]: https://travis-ci.org/facebook/zstd [travisLink]: https://travis-ci.org/facebook/zstd
@@ -21,14 +22,16 @@ a list of known ports and bindings is provided on [Zstandard homepage](http://ww
[AppveyorLink]: https://ci.appveyor.com/project/YannCollet/zstd-p0yf0 [AppveyorLink]: https://ci.appveyor.com/project/YannCollet/zstd-p0yf0
[CircleDevBadge]: https://circleci.com/gh/facebook/zstd/tree/dev.svg?style=shield "Short test suite" [CircleDevBadge]: https://circleci.com/gh/facebook/zstd/tree/dev.svg?style=shield "Short test suite"
[CircleLink]: https://circleci.com/gh/facebook/zstd [CircleLink]: https://circleci.com/gh/facebook/zstd
[CirrusDevBadge]: https://api.cirrus-ci.com/github/facebook/zstd.svg?branch=dev
[CirrusLink]: https://cirrus-ci.com/github/facebook/zstd
## Benchmarks ## Benchmarks
For reference, several fast compression algorithms were tested and compared For reference, several fast compression algorithms were tested and compared
on a server running Linux Debian (`Linux version 4.14.0-3-amd64`), on a server running Arch Linux (`Linux version 5.0.5-arch1-1`),
with a Core i7-6700K CPU @ 4.0GHz, with a Core i9-9900K CPU @ 5.0GHz,
using [lzbench], an open-source in-memory benchmark by @inikep using [lzbench], an open-source in-memory benchmark by @inikep
compiled with [gcc] 7.3.0, compiled with [gcc] 8.2.1,
on the [Silesia compression corpus]. on the [Silesia compression corpus].
[lzbench]: https://github.com/inikep/lzbench [lzbench]: https://github.com/inikep/lzbench
@@ -37,14 +40,14 @@ on the [Silesia compression corpus].
| Compressor name | Ratio | Compression| Decompress.| | Compressor name | Ratio | Compression| Decompress.|
| --------------- | ------| -----------| ---------- | | --------------- | ------| -----------| ---------- |
| **zstd 1.3.4 -1** | 2.877 | 470 MB/s | 1380 MB/s | | **zstd 1.4.0 -1** | 2.884 | 530 MB/s | 1360 MB/s |
| zlib 1.2.11 -1 | 2.743 | 110 MB/s | 400 MB/s | | zlib 1.2.11 -1 | 2.743 | 110 MB/s | 440 MB/s |
| brotli 1.0.2 -0 | 2.701 | 410 MB/s | 430 MB/s | | brotli 1.0.7 -0 | 2.701 | 430 MB/s | 470 MB/s |
| quicklz 1.5.0 -1 | 2.238 | 550 MB/s | 710 MB/s | | quicklz 1.5.0 -1 | 2.238 | 600 MB/s | 800 MB/s |
| lzo1x 2.09 -1 | 2.108 | 650 MB/s | 830 MB/s | | lzo1x 2.09 -1 | 2.106 | 680 MB/s | 950 MB/s |
| lz4 1.8.1 | 2.101 | 750 MB/s | 3700 MB/s | | lz4 1.8.3 | 2.101 | 800 MB/s | 4220 MB/s |
| snappy 1.1.4 | 2.091 | 530 MB/s | 1800 MB/s | | snappy 1.1.4 | 2.073 | 580 MB/s | 2020 MB/s |
| lzf 3.6 -1 | 2.077 | 400 MB/s | 860 MB/s | | lzf 3.6 -1 | 2.077 | 440 MB/s | 930 MB/s |
[zlib]: http://www.zlib.net/ [zlib]: http://www.zlib.net/
[LZ4]: http://www.lz4.org/ [LZ4]: http://www.lz4.org/
+4
View File
@@ -408,6 +408,10 @@
RelativePath="..\..\..\programs\util.c" RelativePath="..\..\..\programs\util.c"
> >
</File> </File>
<File
RelativePath="..\..\..\programs\timefn.c"
>
</File>
<File <File
RelativePath="..\..\..\lib\compress\zstd_fast.c" RelativePath="..\..\..\lib\compress\zstd_fast.c"
> >
+8 -4
View File
@@ -45,7 +45,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs" AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="3" RuntimeLibrary="3"
@@ -121,7 +121,7 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
OmitFramePointers="true" OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs" AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0" RuntimeLibrary="0"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
@@ -195,7 +195,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs" AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\programs"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="3" RuntimeLibrary="3"
@@ -272,7 +272,7 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
OmitFramePointers="true" OmitFramePointers="true"
AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\programs" AdditionalIncludeDirectories="$(SolutionDir)..\..\lib;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\compress;$(SolutionDir)..\..\programs"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" PreprocessorDefinitions="ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0" RuntimeLibrary="0"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
@@ -332,6 +332,10 @@
RelativePath="..\..\..\programs\util.c" RelativePath="..\..\..\programs\util.c"
> >
</File> </File>
<File
RelativePath="..\..\..\programs\timefn.c"
>
</File>
<File <File
RelativePath="..\..\..\programs\datagen.c" RelativePath="..\..\..\programs\datagen.c"
> >
+4
View File
@@ -336,6 +336,10 @@
RelativePath="..\..\..\programs\util.c" RelativePath="..\..\..\programs\util.c"
> >
</File> </File>
<File
RelativePath="..\..\..\programs\timefn.c"
>
</File>
<File <File
RelativePath="..\..\..\programs\benchfn.c" RelativePath="..\..\..\programs\benchfn.c"
> >
@@ -167,6 +167,7 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\..\lib\common\xxhash.c" /> <ClCompile Include="..\..\..\lib\common\xxhash.c" />
<ClCompile Include="..\..\..\programs\util.c" /> <ClCompile Include="..\..\..\programs\util.c" />
<ClCompile Include="..\..\..\programs\timefn.c" />
<ClCompile Include="..\..\..\programs\datagen.c" /> <ClCompile Include="..\..\..\programs\datagen.c" />
<ClCompile Include="..\..\..\programs\benchfn.c" /> <ClCompile Include="..\..\..\programs\benchfn.c" />
<ClCompile Include="..\..\..\tests\fullbench.c" /> <ClCompile Include="..\..\..\tests\fullbench.c" />
+2 -1
View File
@@ -156,7 +156,6 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\..\lib\common\entropy_common.c" /> <ClCompile Include="..\..\..\lib\common\entropy_common.c" />
<ClCompile Include="..\..\..\programs\util.c" />
<ClCompile Include="..\..\..\lib\common\debug.c" /> <ClCompile Include="..\..\..\lib\common\debug.c" />
<ClCompile Include="..\..\..\lib\common\fse_decompress.c" /> <ClCompile Include="..\..\..\lib\common\fse_decompress.c" />
<ClCompile Include="..\..\..\lib\common\zstd_common.c" /> <ClCompile Include="..\..\..\lib\common\zstd_common.c" />
@@ -178,6 +177,8 @@
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" /> <ClCompile Include="..\..\..\lib\decompress\zstd_decompress.c" />
<ClCompile Include="..\..\..\lib\decompress\zstd_decompress_block.c" /> <ClCompile Include="..\..\..\lib\decompress\zstd_decompress_block.c" />
<ClCompile Include="..\..\..\lib\decompress\zstd_ddict.c" /> <ClCompile Include="..\..\..\lib\decompress\zstd_ddict.c" />
<ClCompile Include="..\..\..\programs\util.c" />
<ClCompile Include="..\..\..\programs\timefn.c" />
<ClCompile Include="..\..\..\programs\datagen.c" /> <ClCompile Include="..\..\..\programs\datagen.c" />
<ClCompile Include="..\..\..\programs\benchfn.c" /> <ClCompile Include="..\..\..\programs\benchfn.c" />
<ClCompile Include="..\..\..\tests\fullbench.c" /> <ClCompile Include="..\..\..\tests\fullbench.c" />
+5 -4
View File
@@ -90,7 +90,7 @@
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<EnablePREfast>false</EnablePREfast> <EnablePREfast>false</EnablePREfast>
</ClCompile> </ClCompile>
@@ -105,7 +105,7 @@
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<EnablePREfast>false</EnablePREfast> <EnablePREfast>false</EnablePREfast>
</ClCompile> </ClCompile>
@@ -122,7 +122,7 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<EnablePREfast>false</EnablePREfast> <EnablePREfast>false</EnablePREfast>
<TreatWarningAsError>false</TreatWarningAsError> <TreatWarningAsError>false</TreatWarningAsError>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -142,7 +142,7 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>ZSTD_MULTITHREAD=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>false</TreatWarningAsError> <TreatWarningAsError>false</TreatWarningAsError>
<EnablePREfast>false</EnablePREfast> <EnablePREfast>false</EnablePREfast>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -182,6 +182,7 @@
<ClCompile Include="..\..\..\lib\dictBuilder\divsufsort.c" /> <ClCompile Include="..\..\..\lib\dictBuilder\divsufsort.c" />
<ClCompile Include="..\..\..\lib\dictBuilder\zdict.c" /> <ClCompile Include="..\..\..\lib\dictBuilder\zdict.c" />
<ClCompile Include="..\..\..\programs\util.c" /> <ClCompile Include="..\..\..\programs\util.c" />
<ClCompile Include="..\..\..\programs\timefn.c" />
<ClCompile Include="..\..\..\programs\datagen.c" /> <ClCompile Include="..\..\..\programs\datagen.c" />
<ClCompile Include="..\..\..\tests\fuzzer.c" /> <ClCompile Include="..\..\..\tests\fuzzer.c" />
</ItemGroup> </ItemGroup>
+1
View File
@@ -53,6 +53,7 @@
<ClCompile Include="..\..\..\lib\legacy\zstd_v06.c" /> <ClCompile Include="..\..\..\lib\legacy\zstd_v06.c" />
<ClCompile Include="..\..\..\lib\legacy\zstd_v07.c" /> <ClCompile Include="..\..\..\lib\legacy\zstd_v07.c" />
<ClCompile Include="..\..\..\programs\util.c" /> <ClCompile Include="..\..\..\programs\util.c" />
<ClCompile Include="..\..\..\programs\timefn.c" />
<ClCompile Include="..\..\..\programs\benchfn.c" /> <ClCompile Include="..\..\..\programs\benchfn.c" />
<ClCompile Include="..\..\..\programs\benchzstd.c" /> <ClCompile Include="..\..\..\programs\benchzstd.c" />
<ClCompile Include="..\..\..\programs\datagen.c" /> <ClCompile Include="..\..\..\programs\datagen.c" />
+48 -8
View File
@@ -7,17 +7,57 @@
# in the COPYING file in the root directory of this source tree). # in the COPYING file in the root directory of this source tree).
# ################################################################ # ################################################################
cmake_minimum_required(VERSION 2.8.9) cmake_minimum_required(VERSION 2.8.9 FATAL_ERROR)
project(zstd) # As of 2018-12-26 ZSTD has been validated to build with cmake version 3.13.2 new policies.
set(ZSTD_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..") # Set and use the newest cmake policies that are validated to work
set(ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION "3")
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION "13") #Policies never changed at PATCH level
message(STATUS "No build type selected, defaulting to Release") if("${CMAKE_MAJOR_VERSION}" LESS 3)
set(CMAKE_BUILD_TYPE "Release") set(ZSTD_CMAKE_POLICY_VERSION "${CMAKE_VERSION}")
elseif( "${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}" EQUAL "${CMAKE_MAJOR_VERSION}" AND
"${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}" GREATER "${CMAKE_MINOR_VERSION}")
set(ZSTD_CMAKE_POLICY_VERSION "${CMAKE_VERSION}")
else()
set(ZSTD_CMAKE_POLICY_VERSION "${ZSTD_MAX_VALIDATED_CMAKE_MAJOR_VERSION}.${ZSTD_MAX_VALIDATED_CMAKE_MINOR_VERSION}.0")
endif() endif()
cmake_policy(VERSION ${ZSTD_CMAKE_POLICY_VERSION})
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
set(ZSTD_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..")
set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib)
# Parse version
include(GetZstdLibraryVersion)
GetZstdLibraryVersion(${LIBRARY_DIR}/zstd.h zstd_VERSION_MAJOR zstd_VERSION_MINOR zstd_VERSION_PATCH)
if( CMAKE_MAJOR_VERSION LESS 3 )
## Provide cmake 3+ behavior for older versions of cmake
project(zstd)
set(PROJECT_VERSION_MAJOR ${zstd_VERSION_MAJOR})
set(PROJECT_VERSION_MINOR ${zstd_VERSION_MINOR})
set(PROJECT_VERSION_PATCH ${zstd_VERSION_PATCH})
set(PROJECT_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}")
enable_language(C) # Main library is in C
enable_language(CXX) # Testing contributed code also utilizes CXX
else()
project(zstd
VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}"
LANGUAGES C # Main library is in C
CXX # Testing contributed code also utilizes CXX
)
endif()
message(STATUS "ZSTD VERSION: ${zstd_VERSION}")
set(zstd_HOMEPAGE_URL "http://www.zstd.net")
set(zstd_DESCRIPTION "Zstandard is a real-time compression algorithm, providing high compression ratios.")
# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
include(GNUInstallDirs) include(GNUInstallDirs)
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@@ -50,9 +50,11 @@ macro(ADD_ZSTD_COMPILATION_FLAGS)
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
separate_arguments(${flag_var}) if( ${flag_var} )
list(REMOVE_DUPLICATES ${flag_var}) separate_arguments(${flag_var})
string(REPLACE ";" " " ${flag_var} "${${flag_var}}") list(REMOVE_DUPLICATES ${flag_var})
string(REPLACE ";" " " ${flag_var} "${${flag_var}}")
endif()
endforeach () endforeach ()
if (MSVC AND ZSTD_USE_STATIC_RUNTIME) if (MSVC AND ZSTD_USE_STATIC_RUNTIME)
@@ -60,7 +62,9 @@ macro(ADD_ZSTD_COMPILATION_FLAGS)
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") if ( ${flag_var} )
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif()
endforeach () endforeach ()
endif () endif ()
@@ -1,9 +1,10 @@
function(GetZstdLibraryVersion _header _major _minor _release) function(GetZstdLibraryVersion _header _major _minor _patch)
# Read file content # Read file content
file(READ ${_header} CONTENT) file(READ ${_header} CONTENT)
string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" VERSION_REGEX "${CONTENT}") string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" VERSION_REGEX "${CONTENT}")
set(${_major} ${CMAKE_MATCH_1} PARENT_SCOPE) set(${_major} ${CMAKE_MATCH_1} PARENT_SCOPE)
set(${_minor} ${CMAKE_MATCH_2} PARENT_SCOPE) set(${_minor} ${CMAKE_MATCH_2} PARENT_SCOPE)
set(${_release} ${CMAKE_MATCH_3} PARENT_SCOPE) set(${_patch} ${CMAKE_MATCH_3} PARENT_SCOPE)
endfunction() endfunction()
+1 -1
View File
@@ -3,7 +3,7 @@
Contributions to the cmake build configurations are welcome. Please Contributions to the cmake build configurations are welcome. Please
use case sensitivity that matches modern (ie. cmake version 2.6 and above) use case sensitivity that matches modern (ie. cmake version 2.6 and above)
conventions of using lower-case for commands, and upper-case for conventions of using lower-case for commands, and upper-case for
varibles. variables.
# CMake Style Recommendations # CMake Style Recommendations
+3 -8
View File
@@ -18,14 +18,8 @@ if(NOT ZSTD_BUILD_SHARED AND NOT ZSTD_BUILD_STATIC)
endif() endif()
# Define library directory, where sources and header files are located # Define library directory, where sources and header files are located
set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib)
include_directories(${LIBRARY_DIR} ${LIBRARY_DIR}/common) include_directories(${LIBRARY_DIR} ${LIBRARY_DIR}/common)
# Parse version
include(GetZstdLibraryVersion)
GetZstdLibraryVersion(${LIBRARY_DIR}/zstd.h LIBVER_MAJOR LIBVER_MINOR LIBVER_RELEASE)
message(STATUS "ZSTD VERSION ${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}")
set(Sources set(Sources
${LIBRARY_DIR}/common/entropy_common.c ${LIBRARY_DIR}/common/entropy_common.c
${LIBRARY_DIR}/common/fse_decompress.c ${LIBRARY_DIR}/common/fse_decompress.c
@@ -155,7 +149,8 @@ if (ZSTD_BUILD_SHARED)
libzstd_shared libzstd_shared
PROPERTIES PROPERTIES
OUTPUT_NAME zstd OUTPUT_NAME zstd
SOVERSION ${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}) VERSION ${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}
SOVERSION ${zstd_VERSION_MAJOR})
endif () endif ()
if (ZSTD_BUILD_STATIC) if (ZSTD_BUILD_STATIC)
@@ -170,7 +165,7 @@ if (UNIX)
set(PREFIX "${CMAKE_INSTALL_PREFIX}") set(PREFIX "${CMAKE_INSTALL_PREFIX}")
set(LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") set(LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
set(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include") set(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
set(VERSION "${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}") set(VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}")
add_custom_target(libzstd.pc ALL add_custom_target(libzstd.pc ALL
${CMAKE_COMMAND} -DIN="${LIBRARY_DIR}/libzstd.pc.in" -DOUT="libzstd.pc" ${CMAKE_COMMAND} -DIN="${LIBRARY_DIR}/libzstd.pc.in" -DOUT="libzstd.pc"
-DPREFIX="${PREFIX}" -DLIBDIR="${LIBDIR}" -DINCLUDEDIR="${INCLUDEDIR}" -DVERSION="${VERSION}" -DPREFIX="${PREFIX}" -DLIBDIR="${LIBDIR}" -DINCLUDEDIR="${INCLUDEDIR}" -DVERSION="${VERSION}"
+2 -2
View File
@@ -26,7 +26,7 @@ if (MSVC)
set(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstd.rc) set(PlatformDependResources ${MSVC_RESOURCE_DIR}/zstd.rc)
endif () endif ()
add_executable(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${PlatformDependResources}) add_executable(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${PlatformDependResources})
target_link_libraries(zstd libzstd_static) target_link_libraries(zstd libzstd_static)
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
target_link_libraries(zstd rt) target_link_libraries(zstd rt)
@@ -63,7 +63,7 @@ if (UNIX)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdgrep.1 DESTINATION "${MAN_INSTALL_DIR}") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdgrep.1 DESTINATION "${MAN_INSTALL_DIR}")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdless.1 DESTINATION "${MAN_INSTALL_DIR}") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdless.1 DESTINATION "${MAN_INSTALL_DIR}")
add_executable(zstd-frugal ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/fileio.c) add_executable(zstd-frugal ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/fileio.c)
target_link_libraries(zstd-frugal libzstd_static) target_link_libraries(zstd-frugal libzstd_static)
set_property(TARGET zstd-frugal APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_NOBENCH;ZSTD_NODICT") set_property(TARGET zstd-frugal APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_NOBENCH;ZSTD_NODICT")
endif () endif ()
+3 -3
View File
@@ -43,13 +43,13 @@ include_directories(${TESTS_DIR} ${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/c
add_executable(datagen ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/datagencli.c) add_executable(datagen ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/datagencli.c)
target_link_libraries(datagen libzstd_static) target_link_libraries(datagen libzstd_static)
add_executable(fullbench ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${TESTS_DIR}/fullbench.c) add_executable(fullbench ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${TESTS_DIR}/fullbench.c)
target_link_libraries(fullbench libzstd_static) target_link_libraries(fullbench libzstd_static)
add_executable(fuzzer ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${TESTS_DIR}/fuzzer.c) add_executable(fuzzer ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/fuzzer.c)
target_link_libraries(fuzzer libzstd_static) target_link_libraries(fuzzer libzstd_static)
if (UNIX) if (UNIX)
add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${TESTS_DIR}/paramgrill.c) add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/paramgrill.c)
target_link_libraries(paramgrill libzstd_static m) #m is math library target_link_libraries(paramgrill libzstd_static m) #m is math library
endif () endif ()
+2 -2
View File
@@ -7,7 +7,7 @@ modern software development tools and practices, such as unit tests,
coverage reports, Valgrind, CCache and the like. coverage reports, Valgrind, CCache and the like.
This Meson build system is provided with no guarantee and maintained This Meson build system is provided with no guarantee and maintained
by Dima Krasner <dima@dimakrasner.com>. by Dima Krasner \<dima@dimakrasner.com\>.
It outputs one `libzstd`, either shared or static, depending on It outputs one `libzstd`, either shared or static, depending on
`default_library` option. `default_library` option.
@@ -17,7 +17,7 @@ It outputs one `libzstd`, either shared or static, depending on
`cd` to this meson directory (`build/meson`) `cd` to this meson directory (`build/meson`)
```sh ```sh
meson --buildtype=release -D with-contrib=true -D with-tests=true -D with-contrib=true builddir meson --buildtype=release -Dbuild_{programs,contrib}=true builddir
cd builddir cd builddir
ninja # to build ninja # to build
ninja install # to install ninja install # to install
+3 -3
View File
@@ -98,7 +98,7 @@ if use_debug
if cc_id == compiler_gcc or cc_id == compiler_clang if cc_id == compiler_gcc or cc_id == compiler_clang
libzstd_debug_cflags = ['-Wstrict-aliasing=1', '-Wswitch-enum', libzstd_debug_cflags = ['-Wstrict-aliasing=1', '-Wswitch-enum',
'-Wdeclaration-after-statement', '-Wstrict-prototypes', '-Wdeclaration-after-statement', '-Wstrict-prototypes',
'-Wundef', '-Wpointer-arith', '-Wformat-security', '-Wvla', '-Wundef', '-Wpointer-arith', '-Wvla',
'-Wformat=2', '-Winit-self', '-Wfloat-equal', '-Wwrite-strings', '-Wformat=2', '-Winit-self', '-Wfloat-equal', '-Wwrite-strings',
'-Wredundant-decls', '-Wmissing-prototypes', '-Wc++-compat'] '-Wredundant-decls', '-Wmissing-prototypes', '-Wc++-compat']
endif endif
@@ -116,9 +116,9 @@ libzstd = library('zstd',
libzstd_dep = declare_dependency(link_with: libzstd, libzstd_dep = declare_dependency(link_with: libzstd,
include_directories: libzstd_includes) include_directories: libzstd_includes)
pkgconfig.generate(name: 'libzstd', pkgconfig.generate(libzstd,
name: 'libzstd',
filebase: 'libzstd', filebase: 'libzstd',
libraries: [libzstd],
description: 'fast lossless compression algorithm library', description: 'fast lossless compression algorithm library',
version: zstd_libversion, version: zstd_libversion,
url: 'http://www.zstd.net/') url: 'http://www.zstd.net/')
+4 -2
View File
@@ -11,9 +11,11 @@
project('zstd', project('zstd',
['c', 'cpp'], ['c', 'cpp'],
license: ['BSD', 'GPLv2'], license: ['BSD', 'GPLv2'],
default_options : ['c_std=c99', default_options : [
'c_std=c99',
'cpp_std=c++11', 'cpp_std=c++11',
'buildtype=release'], 'buildtype=release'
],
version: '1.3.8', version: '1.3.8',
meson_version: '>=0.47.0') meson_version: '>=0.47.0')
+2
View File
@@ -12,6 +12,7 @@ zstd_rootdir = '../../..'
zstd_programs_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'), zstd_programs_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'),
join_paths(zstd_rootdir, 'programs/util.c'), join_paths(zstd_rootdir, 'programs/util.c'),
join_paths(zstd_rootdir, 'programs/timefn.c'),
join_paths(zstd_rootdir, 'programs/fileio.c'), join_paths(zstd_rootdir, 'programs/fileio.c'),
join_paths(zstd_rootdir, 'programs/benchfn.c'), join_paths(zstd_rootdir, 'programs/benchfn.c'),
join_paths(zstd_rootdir, 'programs/benchzstd.c'), join_paths(zstd_rootdir, 'programs/benchzstd.c'),
@@ -63,6 +64,7 @@ zstd = executable('zstd',
install: true) install: true)
zstd_frugal_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'), zstd_frugal_sources = [join_paths(zstd_rootdir, 'programs/zstdcli.c'),
join_paths(zstd_rootdir, 'programs/timefn.c'),
join_paths(zstd_rootdir, 'programs/util.c'), join_paths(zstd_rootdir, 'programs/util.c'),
join_paths(zstd_rootdir, 'programs/fileio.c')] join_paths(zstd_rootdir, 'programs/fileio.c')]
+7
View File
@@ -40,6 +40,7 @@ datagen = executable('datagen',
fullbench_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'), fullbench_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
join_paths(zstd_rootdir, 'programs/util.c'), join_paths(zstd_rootdir, 'programs/util.c'),
join_paths(zstd_rootdir, 'programs/timefn.c'),
join_paths(zstd_rootdir, 'programs/benchfn.c'), join_paths(zstd_rootdir, 'programs/benchfn.c'),
join_paths(zstd_rootdir, 'programs/benchzstd.c'), join_paths(zstd_rootdir, 'programs/benchzstd.c'),
join_paths(zstd_rootdir, 'tests/fullbench.c')] join_paths(zstd_rootdir, 'tests/fullbench.c')]
@@ -51,6 +52,7 @@ fullbench = executable('fullbench',
fuzzer_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'), fuzzer_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
join_paths(zstd_rootdir, 'programs/util.c'), join_paths(zstd_rootdir, 'programs/util.c'),
join_paths(zstd_rootdir, 'programs/timefn.c'),
join_paths(zstd_rootdir, 'tests/fuzzer.c')] join_paths(zstd_rootdir, 'tests/fuzzer.c')]
fuzzer = executable('fuzzer', fuzzer = executable('fuzzer',
fuzzer_sources, fuzzer_sources,
@@ -60,6 +62,7 @@ fuzzer = executable('fuzzer',
zbufftest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'), zbufftest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
join_paths(zstd_rootdir, 'programs/util.c'), join_paths(zstd_rootdir, 'programs/util.c'),
join_paths(zstd_rootdir, 'programs/timefn.c'),
join_paths(zstd_rootdir, 'tests/zbufftest.c')] join_paths(zstd_rootdir, 'tests/zbufftest.c')]
zbufftest = executable('zbufftest', zbufftest = executable('zbufftest',
zbufftest_sources, zbufftest_sources,
@@ -70,6 +73,7 @@ zbufftest = executable('zbufftest',
zstreamtest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'), zstreamtest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
join_paths(zstd_rootdir, 'programs/util.c'), join_paths(zstd_rootdir, 'programs/util.c'),
join_paths(zstd_rootdir, 'programs/timefn.c'),
join_paths(zstd_rootdir, 'tests/seqgen.c'), join_paths(zstd_rootdir, 'tests/seqgen.c'),
join_paths(zstd_rootdir, 'tests/zstreamtest.c')] join_paths(zstd_rootdir, 'tests/zstreamtest.c')]
zstreamtest = executable('zstreamtest', zstreamtest = executable('zstreamtest',
@@ -79,6 +83,7 @@ zstreamtest = executable('zstreamtest',
install: false) install: false)
paramgrill_sources = [join_paths(zstd_rootdir, 'programs/benchfn.c'), paramgrill_sources = [join_paths(zstd_rootdir, 'programs/benchfn.c'),
join_paths(zstd_rootdir, 'programs/timefn.c'),
join_paths(zstd_rootdir, 'programs/benchzstd.c'), join_paths(zstd_rootdir, 'programs/benchzstd.c'),
join_paths(zstd_rootdir, 'programs/datagen.c'), join_paths(zstd_rootdir, 'programs/datagen.c'),
join_paths(zstd_rootdir, 'programs/util.c'), join_paths(zstd_rootdir, 'programs/util.c'),
@@ -116,6 +121,7 @@ legacy = executable('legacy',
install: false) install: false)
decodecorpus_sources = [join_paths(zstd_rootdir, 'programs/util.c'), decodecorpus_sources = [join_paths(zstd_rootdir, 'programs/util.c'),
join_paths(zstd_rootdir, 'programs/timefn.c'),
join_paths(zstd_rootdir, 'tests/decodecorpus.c')] join_paths(zstd_rootdir, 'tests/decodecorpus.c')]
decodecorpus = executable('decodecorpus', decodecorpus = executable('decodecorpus',
decodecorpus_sources, decodecorpus_sources,
@@ -132,6 +138,7 @@ symbols = executable('symbols',
install: false) install: false)
poolTests_sources = [join_paths(zstd_rootdir, 'programs/util.c'), poolTests_sources = [join_paths(zstd_rootdir, 'programs/util.c'),
join_paths(zstd_rootdir, 'programs/timefn.c'),
join_paths(zstd_rootdir, 'tests/poolTests.c'), join_paths(zstd_rootdir, 'tests/poolTests.c'),
join_paths(zstd_rootdir, 'lib/common/pool.c'), join_paths(zstd_rootdir, 'lib/common/pool.c'),
join_paths(zstd_rootdir, 'lib/common/threading.c'), join_paths(zstd_rootdir, 'lib/common/threading.c'),
+3 -3
View File
@@ -13,7 +13,7 @@ CPPFLAGS += -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
CFLAGS ?= -O3 CFLAGS ?= -O3
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
-Wstrict-prototypes -Wundef -Wformat-security \ -Wstrict-prototypes -Wundef \
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
-Wredundant-decls -Wredundant-decls
CFLAGS += $(DEBUGFLAGS) CFLAGS += $(DEBUGFLAGS)
@@ -22,10 +22,10 @@ FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(MULTITHREAD_LDFLAGS)
all: adapt datagen all: adapt datagen
adapt: $(ZSTD_FILES) $(PRGDIR)/util.c adapt.c adapt: $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c adapt.c
$(CC) $(FLAGS) $^ -o $@ $(CC) $(FLAGS) $^ -o $@
adapt-debug: $(ZSTD_FILES) $(PRGDIR)/util.c adapt.c adapt-debug: $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c adapt.c
$(CC) $(FLAGS) -DDEBUG_MODE=2 $^ -o adapt $(CC) $(FLAGS) -DDEBUG_MODE=2 $^ -o adapt
datagen : $(PRGDIR)/datagen.c datagencli.c datagen : $(PRGDIR)/datagen.c datagencli.c
+1
View File
@@ -13,6 +13,7 @@
#include <string.h> /* memset */ #include <string.h> /* memset */
#include "zstd_internal.h" #include "zstd_internal.h"
#include "util.h" #include "util.h"
#include "timefn.h" /* UTIL_time_t, UTIL_getTime, UTIL_getSpanTimeMicro */
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
#define PRINT(...) fprintf(stdout, __VA_ARGS__) #define PRINT(...) fprintf(stdout, __VA_ARGS__)
+1 -1
View File
@@ -5,7 +5,7 @@ The `Dockerfile` script requires a version of `docker` >= 17.05
## Installing docker ## Installing docker
The officiel docker install docs use a ppa with a modern version available: The official docker install docs use a ppa with a modern version available:
https://docs.docker.com/install/linux/docker-ce/ubuntu/ https://docs.docker.com/install/linux/docker-ce/ubuntu/
## How to run ## How to run
@@ -127,7 +127,7 @@ dictInfo* createDictFromFiles(sampleInfo *info, unsigned maxDictSize,
/** compressWithDict() : /** compressWithDict() :
* Compress samples from sample buffer given dicionary stored on dictionary buffer and compression level * Compress samples from sample buffer given dictionary stored on dictionary buffer and compression level
* @return compression ratio * @return compression ratio
*/ */
double compressWithDict(sampleInfo *srcInfo, dictInfo* dInfo, int compressionLevel, int displayLevel) { double compressWithDict(sampleInfo *srcInfo, dictInfo* dInfo, int compressionLevel, int displayLevel) {
@@ -194,7 +194,7 @@ double compressWithDict(sampleInfo *srcInfo, dictInfo* dInfo, int compressionLev
totalCompressedSize += compressedSize; totalCompressedSize += compressedSize;
} }
/* Sum orignal sizes */ /* Sum original sizes */
for (i = 0; i<srcInfo->nbSamples; i++) { for (i = 0; i<srcInfo->nbSamples; i++) {
totalOriginalSize += srcInfo->samplesSizes[i]; totalOriginalSize += srcInfo->samplesSizes[i];
} }
@@ -125,7 +125,7 @@ typedef struct {
* *
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1}) * Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
* *
* Once the dmer with hash value d is in the dictionay we set F(d) = F(d)/2. * Once the dmer with hash value d is in the dictionary we set F(d) = F(d)/2.
*/ */
static FASTCOVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx, static FASTCOVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
U32 *freqs, U32 begin,U32 end, U32 *freqs, U32 begin,U32 end,
@@ -149,7 +149,7 @@ static FASTCOVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
while (activeSegment.end < end) { while (activeSegment.end < end) {
/* Get hash value of current dmer */ /* Get hash value of current dmer */
const size_t index = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, parameters.f, ctx->d); const size_t index = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, parameters.f, ctx->d);
/* Add frequency of this index to score if this is the first occurence of index in active segment */ /* Add frequency of this index to score if this is the first occurrence of index in active segment */
if (ctx->segmentFreqs[index] == 0) { if (ctx->segmentFreqs[index] == 0) {
activeSegment.score += freqs[index]; activeSegment.score += freqs[index];
} }
+7 -3
View File
@@ -18,7 +18,7 @@ CFLAGS ?= -O3
CFLAGS += -std=gnu99 CFLAGS += -std=gnu99
DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
-Wstrict-aliasing=1 -Wswitch-enum \ -Wstrict-aliasing=1 -Wswitch-enum \
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \ -Wstrict-prototypes -Wundef -Wpointer-arith \
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
-Wredundant-decls -Wredundant-decls
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
@@ -28,14 +28,17 @@ default: largeNbDicts
all : largeNbDicts all : largeNbDicts
largeNbDicts: util.o benchfn.o datagen.o xxhash.o largeNbDicts.c $(LIBZSTD) largeNbDicts: util.o timefn.o benchfn.o datagen.o xxhash.o largeNbDicts.c $(LIBZSTD)
$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@
.PHONY: $(LIBZSTD) .PHONY: $(LIBZSTD)
$(LIBZSTD): $(LIBZSTD):
$(MAKE) -C $(LIBDIR) libzstd.a CFLAGS="$(CFLAGS)" $(MAKE) -C $(LIBDIR) libzstd.a CFLAGS="$(CFLAGS)"
benchfn.o : $(PROGDIR)/benchfn.c benchfn.o: $(PROGDIR)/benchfn.c
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
timefn.o: $(PROGDIR)/timefn.c
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c $(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
datagen.o: $(PROGDIR)/datagen.c datagen.o: $(PROGDIR)/datagen.c
@@ -48,6 +51,7 @@ util.o: $(PROGDIR)/util.c
xxhash.o : $(LIBDIR)/common/xxhash.c xxhash.o : $(LIBDIR)/common/xxhash.c
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c $(CC) $(CPPFLAGS) $(CFLAGS) $^ -c
clean: clean:
$(RM) *.o $(RM) *.o
$(MAKE) -C $(LIBDIR) clean > /dev/null $(MAKE) -C $(LIBDIR) clean > /dev/null
+1 -1
View File
@@ -424,7 +424,7 @@ static ddict_collection_t createDDictCollection(const void* dictBuffer, size_t d
} }
/* mess with adresses, so that linear scanning dictionaries != linear address scanning */ /* mess with addresses, so that linear scanning dictionaries != linear address scanning */
void shuffleDictionaries(ddict_collection_t dicts) void shuffleDictionaries(ddict_collection_t dicts)
{ {
size_t const nbDicts = dicts.nbDDict; size_t const nbDicts = dicts.nbDDict;
@@ -4,7 +4,7 @@ Date: Mon, 17 Jul 2017 17:08:19 -0700
Subject: [PATCH v5 2/5] lib: Add zstd modules Subject: [PATCH v5 2/5] lib: Add zstd modules
Add zstd compression and decompression kernel modules. Add zstd compression and decompression kernel modules.
zstd offers a wide varity of compression speed and quality trade-offs. zstd offers a wide variety of compression speed and quality trade-offs.
It can compress at speeds approaching lz4, and quality approaching lzma. It can compress at speeds approaching lz4, and quality approaching lzma.
zstd decompressions at speeds more than twice as fast as zlib, and zstd decompressions at speeds more than twice as fast as zlib, and
decompression speed remains roughly the same across all compression levels. decompression speed remains roughly the same across all compression levels.
@@ -21,7 +21,7 @@ will be easier to keep the kernel zstd up to date.
I benchmarked zstd compression as a special character device. I ran zstd I benchmarked zstd compression as a special character device. I ran zstd
and zlib compression at several levels, as well as performing no and zlib compression at several levels, as well as performing no
compression, which measure the time spent copying the data to kernel space. compression, which measure the time spent copying the data to kernel space.
Data is passed to the compresser 4096 B at a time. The benchmark file is Data is passed to the compressor 4096 B at a time. The benchmark file is
located in the upstream zstd source repository under located in the upstream zstd source repository under
`contrib/linux-kernel/zstd_compress_test.c` [2]. `contrib/linux-kernel/zstd_compress_test.c` [2].
@@ -86,7 +86,7 @@ Tested in userland using the test-suite in the zstd repo under
`contrib/linux-kernel/test/UserlandTest.cpp` [5] by mocking the kernel `contrib/linux-kernel/test/UserlandTest.cpp` [5] by mocking the kernel
functions. Fuzz tested using libfuzzer [6] with the fuzz harnesses under functions. Fuzz tested using libfuzzer [6] with the fuzz harnesses under
`contrib/linux-kernel/test/{RoundTripCrash.c,DecompressCrash.c}` [7] [8] `contrib/linux-kernel/test/{RoundTripCrash.c,DecompressCrash.c}` [7] [8]
with ASAN, UBSAN, and MSAN. Additionaly, it was tested while testing the with ASAN, UBSAN, and MSAN. Additionally, it was tested while testing the
BtrFS and SquashFS patches coming next. BtrFS and SquashFS patches coming next.
[1] https://clang.llvm.org/docs/ClangFormat.html [1] https://clang.llvm.org/docs/ClangFormat.html
@@ -4200,14 +4200,14 @@ index 0000000..ff18ae6
+ BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); + BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
+ U32 const fcsCode = + U32 const fcsCode =
+ params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */ + params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */
+ BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6)); + BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
+ size_t pos; + size_t pos;
+ +
+ if (dstCapacity < ZSTD_frameHeaderSize_max) + if (dstCapacity < ZSTD_frameHeaderSize_max)
+ return ERROR(dstSize_tooSmall); + return ERROR(dstSize_tooSmall);
+ +
+ ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER); + ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER);
+ op[4] = frameHeaderDecriptionByte; + op[4] = frameHeaderDescriptionByte;
+ pos = 5; + pos = 5;
+ if (!singleSegment) + if (!singleSegment)
+ op[pos++] = windowLogByte; + op[pos++] = windowLogByte;
@@ -8812,8 +8812,8 @@ index 0000000..ef3d174
+ U32 position = 0; + U32 position = 0;
+ U32 symbol; + U32 symbol;
+ for (symbol = 0; symbol <= maxSymbolValue; symbol++) { + for (symbol = 0; symbol <= maxSymbolValue; symbol++) {
+ int nbOccurences; + int nbOccurrences;
+ for (nbOccurences = 0; nbOccurences < normalizedCounter[symbol]; nbOccurences++) { + for (nbOccurrences = 0; nbOccurrences < normalizedCounter[symbol]; nbOccurrences++) {
+ tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol; + tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
+ position = (position + step) & tableMask; + position = (position + step) & tableMask;
+ while (position > highThreshold) + while (position > highThreshold)
@@ -9944,7 +9944,7 @@ index 0000000..2143da2
+ HUF_repeat_none, /**< Cannot use the previous table */ + HUF_repeat_none, /**< Cannot use the previous table */
+ HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, + HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
+ 4}X_repeat */ + 4}X_repeat */
+ HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */ + HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */
+} HUF_repeat; +} HUF_repeat;
+/** HUF_compress4X_repeat() : +/** HUF_compress4X_repeat() :
+* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. +* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
@@ -11,7 +11,7 @@ Signed-off-by: Nick Terrell <terrelln@fb.com>
--- ---
v4 -> v5: v4 -> v5:
- Fix patch documentation to reflect that Sean Purcell is the author - Fix patch documentation to reflect that Sean Purcell is the author
- Don't strip trailing whitespace of unreleated code - Don't strip trailing whitespace of unrelated code
- Make zstd_display_options() static - Make zstd_display_options() static
v5 -> v6: v5 -> v6:
@@ -224,7 +224,7 @@ index 0000000..dcab75a
+ * set the default options, this is to ensure any user supplied + * set the default options, this is to ensure any user supplied
+ * -X options on the appending mksquashfs command line are over-ridden. + * -X options on the appending mksquashfs command line are over-ridden.
+ * + *
+ * This function returns 0 on sucessful extraction of options, and -1 on error. + * This function returns 0 on successful extraction of options, and -1 on error.
+ */ + */
+static int zstd_extract_options(int block_size, void *buffer, int size) +static int zstd_extract_options(int block_size, void *buffer, int size)
+{ +{
+2 -2
View File
@@ -2436,14 +2436,14 @@ static size_t ZSTD_writeFrameHeader(void *dst, size_t dstCapacity, ZSTD_paramete
BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
U32 const fcsCode = U32 const fcsCode =
params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */ params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */
BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6)); BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6));
size_t pos; size_t pos;
if (dstCapacity < ZSTD_frameHeaderSize_max) if (dstCapacity < ZSTD_frameHeaderSize_max)
return ERROR(dstSize_tooSmall); return ERROR(dstSize_tooSmall);
ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER); ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER);
op[4] = frameHeaderDecriptionByte; op[4] = frameHeaderDescriptionByte;
pos = 5; pos = 5;
if (!singleSegment) if (!singleSegment)
op[pos++] = windowLogByte; op[pos++] = windowLogByte;
+2 -2
View File
@@ -141,8 +141,8 @@ size_t FSE_buildCTable_wksp(FSE_CTable *ct, const short *normalizedCounter, unsi
U32 position = 0; U32 position = 0;
U32 symbol; U32 symbol;
for (symbol = 0; symbol <= maxSymbolValue; symbol++) { for (symbol = 0; symbol <= maxSymbolValue; symbol++) {
int nbOccurences; int nbOccurrences;
for (nbOccurences = 0; nbOccurences < normalizedCounter[symbol]; nbOccurences++) { for (nbOccurrences = 0; nbOccurrences < normalizedCounter[symbol]; nbOccurrences++) {
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol; tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
position = (position + step) & tableMask; position = (position + step) & tableMask;
while (position > highThreshold) while (position > highThreshold)
+1 -1
View File
@@ -134,7 +134,7 @@ typedef enum {
HUF_repeat_none, /**< Cannot use the previous table */ HUF_repeat_none, /**< Cannot use the previous table */
HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
4}X_repeat */ 4}X_repeat */
HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */ HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */
} HUF_repeat; } HUF_repeat;
/** HUF_compress4X_repeat() : /** HUF_compress4X_repeat() :
* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. * Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
@@ -1,5 +1,5 @@
#ifndef LINUX_COMIPLER_H_ #ifndef LINUX_COMPILER_H_
#define LINUX_COMIPLER_H_ #define LINUX_COMPILER_H_
#ifndef __always_inline #ifndef __always_inline
# define __always_inline inline # define __always_inline inline
@@ -9,4 +9,4 @@
# define noinline __attribute__((__noinline__)) # define noinline __attribute__((__noinline__))
#endif #endif
#endif // LINUX_COMIPLER_H_ #endif // LINUX_COMPILER_H_
+4 -2
View File
@@ -190,13 +190,15 @@ $(ZSTDDIR)/libzstd.a: $(ZSTD_FILES)
CFLAGS="$(ALL_CFLAGS)" LDFLAGS="$(ALL_LDFLAGS)" $(MAKE) -C $(ZSTDDIR) libzstd.a CFLAGS="$(ALL_CFLAGS)" LDFLAGS="$(ALL_LDFLAGS)" $(MAKE) -C $(ZSTDDIR) libzstd.a
# Rules to build the tests # Rules to build the tests
test/RoundTripTest$(EXT): test/RoundTripTest.o $(PROGDIR)/datagen.o Options.o \ test/RoundTripTest$(EXT): test/RoundTripTest.o $(PROGDIR)/datagen.o \
$(PROGDIR)/util.o Options.o \
Pzstd.o SkippableFrame.o $(ZSTDDIR)/libzstd.a Pzstd.o SkippableFrame.o $(ZSTDDIR)/libzstd.a
$(LD_COMMAND) $(LD_COMMAND)
test/%Test$(EXT): PZSTD_LDFLAGS += $(GTEST_LIB) test/%Test$(EXT): PZSTD_LDFLAGS += $(GTEST_LIB)
test/%Test$(EXT): LIBS += -lgtest -lgtest_main test/%Test$(EXT): LIBS += -lgtest -lgtest_main
test/%Test$(EXT): test/%Test.o $(PROGDIR)/datagen.o Options.o Pzstd.o \ test/%Test$(EXT): test/%Test.o $(PROGDIR)/datagen.o \
$(PROGDIR)/util.o Options.o Pzstd.o \
SkippableFrame.o $(ZSTDDIR)/libzstd.a SkippableFrame.o $(ZSTDDIR)/libzstd.a
$(LD_COMMAND) $(LD_COMMAND)
+1 -1
View File
@@ -55,7 +55,7 @@ static std::uint64_t handleOneInput(const Options &options,
SharedState& state) { SharedState& state) {
auto inputSize = fileSizeOrZero(inputFile); auto inputSize = fileSizeOrZero(inputFile);
// WorkQueue outlives ThreadPool so in the case of error we are certain // WorkQueue outlives ThreadPool so in the case of error we are certain
// we don't accidently try to call push() on it after it is destroyed // we don't accidentally try to call push() on it after it is destroyed
WorkQueue<std::shared_ptr<BufferWorkQueue>> outs{options.numThreads + 1}; WorkQueue<std::shared_ptr<BufferWorkQueue>> outs{options.numThreads + 1};
std::uint64_t bytesRead; std::uint64_t bytesRead;
std::uint64_t bytesWritten; std::uint64_t bytesWritten;
+1 -1
View File
@@ -9,7 +9,7 @@
/** /**
* A subset of `folly/Range.h`. * A subset of `folly/Range.h`.
* All code copied verbatiam modulo formatting * All code copied verbatim modulo formatting
*/ */
#pragma once #pragma once
+1 -1
View File
@@ -54,7 +54,7 @@ class ResourcePool {
/** /**
* @returns A unique pointer to a resource. The resource is null iff * @returns A unique pointer to a resource. The resource is null iff
* there are no avaiable resources and `factory()` returns null. * there are no available resources and `factory()` returns null.
*/ */
UniquePtr get() { UniquePtr get() {
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
+2 -2
View File
@@ -12,8 +12,8 @@ __`zstd_compression_format.md`__ : This document defines the Zstandard compressi
Compliant decoders must adhere to this document, Compliant decoders must adhere to this document,
and compliant encoders must generate data that follows it. and compliant encoders must generate data that follows it.
Should you look for ressources to develop your own port of Zstandard algorithm, Should you look for resources to develop your own port of Zstandard algorithm,
you may find the following ressources useful : you may find the following resources useful :
__`educational_decoder`__ : This directory contains an implementation of a Zstandard decoder, __`educational_decoder`__ : This directory contains an implementation of a Zstandard decoder,
compliant with the Zstandard compression format. compliant with the Zstandard compression format.
+1 -1
View File
@@ -7,7 +7,7 @@ CPPFLAGS += -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
CFLAGS ?= -O3 CFLAGS ?= -O3
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
-Wstrict-prototypes -Wundef -Wformat-security \ -Wstrict-prototypes -Wundef \
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
-Wredundant-decls -Wredundant-decls
CFLAGS += $(DEBUGFLAGS) CFLAGS += $(DEBUGFLAGS)
+1 -1
View File
@@ -358,7 +358,7 @@ static u32 copy_literals(const size_t seq, istream_t *litstream,
ostream_t *const out); ostream_t *const out);
// Given an offset code from a sequence command (either an actual offset value // Given an offset code from a sequence command (either an actual offset value
// or an index for previous offset), computes the correct offset and udpates // or an index for previous offset), computes the correct offset and updates
// the offset history // the offset history
static size_t compute_offset(sequence_command_t seq, u64 *const offset_hist); static size_t compute_offset(sequence_command_t seq, u64 *const offset_hist);
+533 -402
View File
@@ -1,37 +1,46 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>zstd 1.3.8 Manual</title> <title>zstd 1.4.0 Manual</title>
</head> </head>
<body> <body>
<h1>zstd 1.3.8 Manual</h1> <h1>zstd 1.4.0 Manual</h1>
<hr> <hr>
<a name="Contents"></a><h2>Contents</h2> <a name="Contents"></a><h2>Contents</h2>
<ol> <ol>
<li><a href="#Chapter1">Introduction</a></li> <li><a href="#Chapter1">Introduction</a></li>
<li><a href="#Chapter2">Version</a></li> <li><a href="#Chapter2">Version</a></li>
<li><a href="#Chapter3">Default constant</a></li> <li><a href="#Chapter3">Default constant</a></li>
<li><a href="#Chapter4">Simple API</a></li> <li><a href="#Chapter4">Constants</a></li>
<li><a href="#Chapter5">Explicit context</a></li> <li><a href="#Chapter5">Simple API</a></li>
<li><a href="#Chapter6">Simple dictionary API</a></li> <li><a href="#Chapter6">Explicit context</a></li>
<li><a href="#Chapter7">Bulk processing dictionary API</a></li> <li><a href="#Chapter7">Advanced compression API</a></li>
<li><a href="#Chapter8">Streaming</a></li> <li><a href="#Chapter8">Advanced decompression API</a></li>
<li><a href="#Chapter9">Streaming compression - HowTo</a></li> <li><a href="#Chapter9">Streaming</a></li>
<li><a href="#Chapter10">Streaming decompression - HowTo</a></li> <li><a href="#Chapter10">Streaming compression - HowTo</a></li>
<li><a href="#Chapter11">ADVANCED AND EXPERIMENTAL FUNCTIONS</a></li> <li><a href="#Chapter11">This is a legacy streaming API, and can be replaced by ZSTD_CCtx_reset() and</a></li>
<li><a href="#Chapter12">Candidate API for promotion to stable status</a></li> <li><a href="#Chapter12">Equivalent to:</a></li>
<li><a href="#Chapter13">Advanced compression API</a></li> <li><a href="#Chapter13">Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).</a></li>
<li><a href="#Chapter14">experimental API (static linking only)</a></li> <li><a href="#Chapter14">Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush).</a></li>
<li><a href="#Chapter15">Frame size functions</a></li> <li><a href="#Chapter15">Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end).</a></li>
<li><a href="#Chapter16">Memory management</a></li> <li><a href="#Chapter16">Streaming decompression - HowTo</a></li>
<li><a href="#Chapter17">Advanced compression functions</a></li> <li><a href="#Chapter17">Simple dictionary API</a></li>
<li><a href="#Chapter18">Advanced decompression functions</a></li> <li><a href="#Chapter18">Bulk processing dictionary API</a></li>
<li><a href="#Chapter19">Advanced streaming functions</a></li> <li><a href="#Chapter19">Dictionary helper functions</a></li>
<li><a href="#Chapter20">Buffer-less and synchronous inner streaming functions</a></li> <li><a href="#Chapter20">Advanced dictionary and prefix API</a></li>
<li><a href="#Chapter21">Buffer-less streaming compression (synchronous mode)</a></li> <li><a href="#Chapter21">ADVANCED AND EXPERIMENTAL FUNCTIONS</a></li>
<li><a href="#Chapter22">Buffer-less streaming decompression (synchronous mode)</a></li> <li><a href="#Chapter22">experimental API (static linking only)</a></li>
<li><a href="#Chapter23">ZSTD_getFrameHeader() :</a></li> <li><a href="#Chapter23">Frame size functions</a></li>
<li><a href="#Chapter24">Block level API</a></li> <li><a href="#Chapter24">ZSTD_decompressBound() :</a></li>
<li><a href="#Chapter25">Memory management</a></li>
<li><a href="#Chapter26">Advanced compression functions</a></li>
<li><a href="#Chapter27">Advanced decompression functions</a></li>
<li><a href="#Chapter28">Advanced streaming functions</a></li>
<li><a href="#Chapter29">Buffer-less and synchronous inner streaming functions</a></li>
<li><a href="#Chapter30">Buffer-less streaming compression (synchronous mode)</a></li>
<li><a href="#Chapter31">Buffer-less streaming decompression (synchronous mode)</a></li>
<li><a href="#Chapter32">ZSTD_getFrameHeader() :</a></li>
<li><a href="#Chapter33">Block level API</a></li>
</ol> </ol>
<hr> <hr>
<a name="Chapter1"></a><h2>Introduction</h2><pre> <a name="Chapter1"></a><h2>Introduction</h2><pre>
@@ -71,7 +80,9 @@
</b></pre><BR> </b></pre><BR>
<a name="Chapter3"></a><h2>Default constant</h2><pre></pre> <a name="Chapter3"></a><h2>Default constant</h2><pre></pre>
<a name="Chapter4"></a><h2>Simple API</h2><pre></pre> <a name="Chapter4"></a><h2>Constants</h2><pre></pre>
<a name="Chapter5"></a><h2>Simple API</h2><pre></pre>
<pre><b>size_t ZSTD_compress( void* dst, size_t dstCapacity, <pre><b>size_t ZSTD_compress( void* dst, size_t dstCapacity,
const void* src, size_t srcSize, const void* src, size_t srcSize,
@@ -126,13 +137,22 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
@return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise.
</p></pre><BR> </p></pre><BR>
<pre><b>size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
</b><p> `src` should point to the start of a ZSTD frame or skippable frame.
`srcSize` must be >= first frame size
@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
</p></pre><BR>
<h3>Helper functions</h3><pre></pre><b><pre>#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) </b>/* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */<b> <h3>Helper functions</h3><pre></pre><b><pre>#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) </b>/* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */<b>
size_t ZSTD_compressBound(size_t srcSize); </b>/*!< maximum compressed size in worst case single-pass scenario */<b> size_t ZSTD_compressBound(size_t srcSize); </b>/*!< maximum compressed size in worst case single-pass scenario */<b>
unsigned ZSTD_isError(size_t code); </b>/*!< tells if a `size_t` function result is an error code */<b> unsigned ZSTD_isError(size_t code); </b>/*!< tells if a `size_t` function result is an error code */<b>
const char* ZSTD_getErrorName(size_t code); </b>/*!< provides readable string from an error code */<b> const char* ZSTD_getErrorName(size_t code); </b>/*!< provides readable string from an error code */<b>
int ZSTD_minCLevel(void); </b>/*!< minimum negative compression level allowed */<b>
int ZSTD_maxCLevel(void); </b>/*!< maximum compression level available */<b> int ZSTD_maxCLevel(void); </b>/*!< maximum compression level available */<b>
</pre></b><BR> </pre></b><BR>
<a name="Chapter5"></a><h2>Explicit context</h2><pre></pre> <a name="Chapter6"></a><h2>Explicit context</h2><pre></pre>
<h3>Compression context</h3><pre> When compressing many times, <h3>Compression context</h3><pre> When compressing many times,
it is recommended to allocate a context just once, and re-use it for each successive compression operation. it is recommended to allocate a context just once, and re-use it for each successive compression operation.
@@ -169,228 +189,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
</p></pre><BR> </p></pre><BR>
<a name="Chapter6"></a><h2>Simple dictionary API</h2><pre></pre> <a name="Chapter7"></a><h2>Advanced compression API</h2><pre></pre>
<pre><b>size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize,
int compressionLevel);
</b><p> Compression at an explicit compression level using a Dictionary.
A dictionary can be any arbitrary data segment (also called a prefix),
or a buffer with specified information (see dictBuilder/zdict.h).
Note : This function loads the dictionary, resulting in significant startup delay.
It's intended for a dictionary used only once.
Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used.
</p></pre><BR>
<pre><b>size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize);
</b><p> Decompression using a known Dictionary.
Dictionary must be identical to the one used during compression.
Note : This function loads the dictionary, resulting in significant startup delay.
It's intended for a dictionary used only once.
Note : When `dict == NULL || dictSize < 8` no dictionary is used.
</p></pre><BR>
<a name="Chapter7"></a><h2>Bulk processing dictionary API</h2><pre></pre>
<pre><b>ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
int compressionLevel);
</b><p> When compressing multiple messages / blocks using the same dictionary, it's recommended to load it only once.
ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup cost.
ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
`dictBuffer` can be released after ZSTD_CDict creation, because its content is copied within CDict.
Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate `dictBuffer` content.
Note : A ZSTD_CDict can be created from an empty dictBuffer, but it is inefficient when used to compress small data.
</p></pre><BR>
<pre><b>size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
</b><p> Function frees memory allocated by ZSTD_createCDict().
</p></pre><BR>
<pre><b>size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict);
</b><p> Compression using a digested Dictionary.
Recommended when same dictionary is used multiple times.
Note : compression level is _decided at dictionary creation time_,
and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no)
</p></pre><BR>
<pre><b>ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
</b><p> Create a digested dictionary, ready to start decompression operation without startup delay.
dictBuffer can be released after DDict creation, as its content is copied inside DDict.
</p></pre><BR>
<pre><b>size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
</b><p> Function frees memory allocated with ZSTD_createDDict()
</p></pre><BR>
<pre><b>size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_DDict* ddict);
</b><p> Decompression using a digested Dictionary.
Recommended when same dictionary is used multiple times.
</p></pre><BR>
<a name="Chapter8"></a><h2>Streaming</h2><pre></pre>
<pre><b>typedef struct ZSTD_inBuffer_s {
const void* src; </b>/**< start of input buffer */<b>
size_t size; </b>/**< size of input buffer */<b>
size_t pos; </b>/**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */<b>
} ZSTD_inBuffer;
</b></pre><BR>
<pre><b>typedef struct ZSTD_outBuffer_s {
void* dst; </b>/**< start of output buffer */<b>
size_t size; </b>/**< size of output buffer */<b>
size_t pos; </b>/**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */<b>
} ZSTD_outBuffer;
</b></pre><BR>
<a name="Chapter9"></a><h2>Streaming compression - HowTo</h2><pre>
A ZSTD_CStream object is required to track streaming operation.
Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
For parallel execution, use one separate ZSTD_CStream per thread.
note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
Parameters are sticky : when starting a new compression on the same context,
it will re-use the same sticky parameters as previous compression session.
When in doubt, it's recommended to fully initialize the context before usage.
Use ZSTD_initCStream() to set the parameter to a selected compression level.
Use advanced API (ZSTD_CCtx_setParameter(), etc.) to set more specific parameters.
Use ZSTD_compressStream() as many times as necessary to consume input stream.
The function will automatically update both `pos` fields within `input` and `output`.
Note that the function may not consume the entire input,
for example, because the output buffer is already full,
in which case `input.pos < input.size`.
The caller must check if input has been entirely consumed.
If not, the caller must make some room to receive more compressed data,
and then present again remaining input data.
@return : a size hint, preferred nb of bytes to use as input for next function call
or an error code, which can be tested using ZSTD_isError().
Note 1 : it's just a hint, to help latency a little, any value will work fine.
Note 2 : size hint is guaranteed to be <= ZSTD_CStreamInSize()
At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
using ZSTD_flushStream(). `output->pos` will be updated.
Note that, if `output->size` is too small, a single invocation of ZSTD_flushStream() might not be enough (return code > 0).
In which case, make some room to receive more compressed data, and call again ZSTD_flushStream().
@return : 0 if internal buffers are entirely flushed,
>0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
or an error code, which can be tested using ZSTD_isError().
ZSTD_endStream() instructs to finish a frame.
It will perform a flush and write frame epilogue.
The epilogue is required for decoders to consider a frame completed.
flush() operation is the same, and follows same rules as ZSTD_flushStream().
@return : 0 if frame fully completed and fully flushed,
>0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
or an error code, which can be tested using ZSTD_isError().
<BR></pre>
<pre><b>typedef ZSTD_CCtx ZSTD_CStream; </b>/**< CCtx and CStream are now effectively same object (>= v1.3.0) */<b>
</b></pre><BR>
<h3>ZSTD_CStream management functions</h3><pre></pre><b><pre>ZSTD_CStream* ZSTD_createCStream(void);
size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
</pre></b><BR>
<h3>Streaming compression functions</h3><pre></pre><b><pre>size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
</pre></b><BR>
<pre><b>size_t ZSTD_CStreamInSize(void); </b>/**< recommended size for input buffer */<b>
</b></pre><BR>
<pre><b>size_t ZSTD_CStreamOutSize(void); </b>/**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */<b>
</b></pre><BR>
<a name="Chapter10"></a><h2>Streaming decompression - HowTo</h2><pre>
A ZSTD_DStream object is required to track streaming operations.
Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
ZSTD_DStream objects can be re-used multiple times.
Use ZSTD_initDStream() to start a new decompression operation.
@return : recommended first input size
Alternatively, use advanced API to set specific properties.
Use ZSTD_decompressStream() repetitively to consume your input.
The function will update both `pos` fields.
If `input.pos < input.size`, some input has not been consumed.
It's up to the caller to present again remaining data.
The function tries to flush all data decoded immediately, respecting output buffer size.
If `output.pos < output.size`, decoder has flushed everything it could.
But if `output.pos == output.size`, there might be some data left within internal buffers.,
In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
@return : 0 when a frame is completely decoded and fully flushed,
or an error code, which can be tested using ZSTD_isError(),
or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
the return value is a suggested next input size (just a hint for better latency)
that will never request more than the remaining frame size.
<BR></pre>
<pre><b>typedef ZSTD_DCtx ZSTD_DStream; </b>/**< DCtx and DStream are now effectively same object (>= v1.3.0) */<b>
</b></pre><BR>
<h3>ZSTD_DStream management functions</h3><pre></pre><b><pre>ZSTD_DStream* ZSTD_createDStream(void);
size_t ZSTD_freeDStream(ZSTD_DStream* zds);
</pre></b><BR>
<h3>Streaming decompression functions</h3><pre></pre><b><pre>size_t ZSTD_initDStream(ZSTD_DStream* zds);
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
</pre></b><BR>
<pre><b>size_t ZSTD_DStreamInSize(void); </b>/*!< recommended size for input buffer */<b>
</b></pre><BR>
<pre><b>size_t ZSTD_DStreamOutSize(void); </b>/*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */<b>
</b></pre><BR>
<a name="Chapter11"></a><h2>ADVANCED AND EXPERIMENTAL FUNCTIONS</h2><pre>
The definitions in the following section are considered experimental.
They are provided for advanced scenarios.
They should never be used with a dynamic library, as prototypes may change in the future.
Use them only in association with static linking.
<BR></pre>
<a name="Chapter12"></a><h2>Candidate API for promotion to stable status</h2><pre>
The following symbols and constants form the "staging area" :
they are considered to join "stable API" by v1.4.0.
The proposal is written so that it can be made stable "as is",
though it's still possible to suggest improvements.
Staging is in fact last chance for changes,
the API is locked once reaching "stable" status.
<BR></pre>
<pre><b>int ZSTD_minCLevel(void); </b>/*!< minimum negative compression level allowed */<b>
</b></pre><BR>
<pre><b>size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
</b><p> `src` should point to the start of a ZSTD frame or skippable frame.
`srcSize` must be >= first frame size
@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
</p></pre><BR>
<pre><b>size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
</b><p> These functions give the _current_ memory usage of selected object.
Note that object memory usage can evolve (increase or decrease) over time.
</p></pre><BR>
<a name="Chapter13"></a><h2>Advanced compression API</h2><pre></pre>
<pre><b>typedef enum { ZSTD_fast=1, <pre><b>typedef enum { ZSTD_fast=1,
ZSTD_dfast=2, ZSTD_dfast=2,
@@ -407,7 +206,10 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
</b></pre><BR> </b></pre><BR>
<pre><b>typedef enum { <pre><b>typedef enum {
</b>/* compression parameters */<b> </b>/* compression parameters<b>
* Note: When compressing with a ZSTD_CDict these parameters are superseded
* by the parameters used to construct the ZSTD_CDict. See ZSTD_CCtx_refCDict()
* for more info (superseded-by-cdict). */
ZSTD_c_compressionLevel=100, </b>/* Update all compression parameters according to pre-defined cLevel table<b> ZSTD_c_compressionLevel=100, </b>/* Update all compression parameters according to pre-defined cLevel table<b>
* Default level is ZSTD_CLEVEL_DEFAULT==3. * Default level is ZSTD_CLEVEL_DEFAULT==3.
* Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.
@@ -529,6 +331,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
* ZSTD_c_format * ZSTD_c_format
* ZSTD_c_forceMaxWindow * ZSTD_c_forceMaxWindow
* ZSTD_c_forceAttachDict * ZSTD_c_forceAttachDict
* ZSTD_c_literalCompressionMode
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly; * note : never ever use experimentalParam? names directly;
* also, the enums values themselves are unstable and can still change. * also, the enums values themselves are unstable and can still change.
@@ -536,7 +339,8 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
ZSTD_c_experimentalParam1=500, ZSTD_c_experimentalParam1=500,
ZSTD_c_experimentalParam2=10, ZSTD_c_experimentalParam2=10,
ZSTD_c_experimentalParam3=1000, ZSTD_c_experimentalParam3=1000,
ZSTD_c_experimentalParam4=1001 ZSTD_c_experimentalParam4=1001,
ZSTD_c_experimentalParam5=1002,
} ZSTD_cParameter; } ZSTD_cParameter;
</b></pre><BR> </b></pre><BR>
<pre><b>typedef struct { <pre><b>typedef struct {
@@ -580,62 +384,10 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
Note 3 : Whenever all input data is provided and consumed in a single round, Note 3 : Whenever all input data is provided and consumed in a single round,
for example with ZSTD_compress2(), for example with ZSTD_compress2(),
or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end), or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),
this value is automatically overriden by srcSize instead. this value is automatically overridden by srcSize instead.
</p></pre><BR> </p></pre><BR>
<pre><b>size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
</b><p> Create an internal CDict from `dict` buffer.
Decompression will have to use same dictionary.
@result : 0, or an error code (which can be tested with ZSTD_isError()).
Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,
meaning "return to no-dictionary mode".
Note 1 : Dictionary is sticky, it will be used for all future compressed frames.
To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters).
Note 2 : Loading a dictionary involves building tables.
It's also a CPU consuming operation, with non-negligible impact on latency.
Tables are dependent on compression parameters, and for this reason,
compression parameters can no longer be changed after loading a dictionary.
Note 3 :`dict` content will be copied internally.
Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.
In such a case, dictionary buffer must outlive its users.
Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()
to precisely select how dictionary content must be interpreted.
</p></pre><BR>
<pre><b>size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
</b><p> Reference a prepared dictionary, to be used for all next compressed frames.
Note that compression parameters are enforced from within CDict,
and supercede any compression parameter previously set within CCtx.
The dictionary will remain valid for future compressed frames using same CCtx.
@result : 0, or an error code (which can be tested with ZSTD_isError()).
Special : Referencing a NULL CDict means "return to no-dictionary mode".
Note 1 : Currently, only one dictionary can be managed.
Referencing a new dictionary effectively "discards" any previous one.
Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx.
</p></pre><BR>
<pre><b>size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
const void* prefix, size_t prefixSize);
</b><p> Reference a prefix (single-usage dictionary) for next compressed frame.
A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
Decompression will need same prefix to properly regenerate data.
Compressing with a prefix is similar in outcome as performing a diff and compressing it,
but performs much faster, especially during decompression (compression speed is tunable with compression level).
@result : 0, or an error code (which can be tested with ZSTD_isError()).
Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary
Note 1 : Prefix buffer is referenced. It **must** outlive compression.
Its content must remain unmodified during compression.
Note 2 : If the intention is to diff some large src data blob with some prior version of itself,
ensure that the window size is large enough to contain the entire source.
See ZSTD_c_windowLog.
Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.
It's a CPU consuming operation, with non-negligible impact on latency.
If there is a need to use the same prefix multiple times, consider loadDictionary instead.
Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dm_rawContent).
Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation.
</p></pre><BR>
<pre><b>typedef enum { <pre><b>typedef enum {
ZSTD_reset_session_only = 1, ZSTD_reset_session_only = 1,
ZSTD_reset_parameters = 2, ZSTD_reset_parameters = 2,
@@ -672,42 +424,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
</p></pre><BR> </p></pre><BR>
<pre><b>typedef enum { <a name="Chapter8"></a><h2>Advanced decompression API</h2><pre></pre>
ZSTD_e_continue=0, </b>/* collect more data, encoder decides when to output compressed result, for optimal compression ratio */<b>
ZSTD_e_flush=1, </b>/* flush any data provided so far,<b>
* it creates (at least) one new block, that can be decoded immediately on reception;
* frame will continue: any future data can still reference previously compressed data, improving compression. */
ZSTD_e_end=2 </b>/* flush any remaining data _and_ close current frame.<b>
* note that frame is only closed after compressed data is fully flushed (return value == 0).
* After that point, any additional data starts a new frame.
* note : each frame is independent (does not reference any content from previous frame). */
} ZSTD_EndDirective;
</b></pre><BR>
<pre><b>size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
ZSTD_outBuffer* output,
ZSTD_inBuffer* input,
ZSTD_EndDirective endOp);
</b><p> Behaves about the same as ZSTD_compressStream, with additional control on end directive.
- Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
- Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
- outpot->pos must be <= dstCapacity, input->pos must be <= srcSize
- outpot->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
- When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
- When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
and then immediately returns, just indicating that there is some data remaining to be flushed.
The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
- Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
- @return provides a minimum amount of data remaining to be flushed from internal buffers
or an error code, which can be tested using ZSTD_isError().
if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
- after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
only ZSTD_e_end or ZSTD_e_flush operations are allowed.
Before starting a new compression job, or changing compression parameters,
it is required to fully flush internal buffers.
</p></pre><BR>
<pre><b>typedef enum { <pre><b>typedef enum {
@@ -715,7 +432,8 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
* the streaming API will refuse to allocate memory buffer * the streaming API will refuse to allocate memory buffer
* in order to protect the host from unreasonable memory requirements. * in order to protect the host from unreasonable memory requirements.
* This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
* By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) */ * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).
* Special: value 0 means "use default maximum windowLog". */
</b>/* note : additional experimental parameters are also available<b> </b>/* note : additional experimental parameters are also available<b>
* within the experimental section of the API. * within the experimental section of the API.
@@ -746,6 +464,352 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
</p></pre><BR> </p></pre><BR>
<pre><b>size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
</b><p> Return a DCtx to clean state.
Session and parameters can be reset jointly or separately.
Parameters can only be reset when no active frame is being decompressed.
@return : 0, or an error code, which can be tested with ZSTD_isError()
</p></pre><BR>
<a name="Chapter9"></a><h2>Streaming</h2><pre></pre>
<pre><b>typedef struct ZSTD_inBuffer_s {
const void* src; </b>/**< start of input buffer */<b>
size_t size; </b>/**< size of input buffer */<b>
size_t pos; </b>/**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */<b>
} ZSTD_inBuffer;
</b></pre><BR>
<pre><b>typedef struct ZSTD_outBuffer_s {
void* dst; </b>/**< start of output buffer */<b>
size_t size; </b>/**< size of output buffer */<b>
size_t pos; </b>/**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */<b>
} ZSTD_outBuffer;
</b></pre><BR>
<a name="Chapter10"></a><h2>Streaming compression - HowTo</h2><pre>
A ZSTD_CStream object is required to track streaming operation.
Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
For parallel execution, use one separate ZSTD_CStream per thread.
note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
Parameters are sticky : when starting a new compression on the same context,
it will re-use the same sticky parameters as previous compression session.
When in doubt, it's recommended to fully initialize the context before usage.
Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),
ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to
set more specific parameters, the pledged source size, or load a dictionary.
Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to
consume input stream. The function will automatically update both `pos`
fields within `input` and `output`.
Note that the function may not consume the entire input, for example, because
the output buffer is already full, in which case `input.pos < input.size`.
The caller must check if input has been entirely consumed.
If not, the caller must make some room to receive more compressed data,
and then present again remaining input data.
note: ZSTD_e_continue is guaranteed to make some forward progress when called,
but doesn't guarantee maximal forward progress. This is especially relevant
when compressing with multiple threads. The call won't block if it can
consume some input, but if it can't it will wait for some, but not all,
output to be flushed.
@return : provides a minimum amount of data remaining to be flushed from internal buffers
or an error code, which can be tested using ZSTD_isError().
At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.
Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).
In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.
You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the
operation.
note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will
block until the flush is complete or the output buffer is full.
@return : 0 if internal buffers are entirely flushed,
>0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
or an error code, which can be tested using ZSTD_isError().
Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.
It will perform a flush and write frame epilogue.
The epilogue is required for decoders to consider a frame completed.
flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.
You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to
start a new frame.
note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will
block until the flush is complete or the output buffer is full.
@return : 0 if frame fully completed and fully flushed,
>0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
or an error code, which can be tested using ZSTD_isError().
<BR></pre>
<pre><b>typedef ZSTD_CCtx ZSTD_CStream; </b>/**< CCtx and CStream are now effectively same object (>= v1.3.0) */<b>
</b></pre><BR>
<h3>ZSTD_CStream management functions</h3><pre></pre><b><pre>ZSTD_CStream* ZSTD_createCStream(void);
size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
</pre></b><BR>
<h3>Streaming compression functions</h3><pre></pre><b><pre>typedef enum {
ZSTD_e_continue=0, </b>/* collect more data, encoder decides when to output compressed result, for optimal compression ratio */<b>
ZSTD_e_flush=1, </b>/* flush any data provided so far,<b>
* it creates (at least) one new block, that can be decoded immediately on reception;
* frame will continue: any future data can still reference previously compressed data, improving compression.
* note : multithreaded compression will block to flush as much output as possible. */
ZSTD_e_end=2 </b>/* flush any remaining data _and_ close current frame.<b>
* note that frame is only closed after compressed data is fully flushed (return value == 0).
* After that point, any additional data starts a new frame.
* note : each frame is independent (does not reference any content from previous frame).
: note : multithreaded compression will block to flush as much output as possible. */
} ZSTD_EndDirective;
</pre></b><BR>
<pre><b>size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
ZSTD_outBuffer* output,
ZSTD_inBuffer* input,
ZSTD_EndDirective endOp);
</b><p> Behaves about the same as ZSTD_compressStream, with additional control on end directive.
- Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
- Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
- output->pos must be <= dstCapacity, input->pos must be <= srcSize
- output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
- When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
- When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
and then immediately returns, just indicating that there is some data remaining to be flushed.
The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
- Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
- @return provides a minimum amount of data remaining to be flushed from internal buffers
or an error code, which can be tested using ZSTD_isError().
if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
- after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
only ZSTD_e_end or ZSTD_e_flush operations are allowed.
Before starting a new compression job, or changing compression parameters,
it is required to fully flush internal buffers.
</p></pre><BR>
<pre><b>size_t ZSTD_CStreamInSize(void); </b>/**< recommended size for input buffer */<b>
</b></pre><BR>
<pre><b>size_t ZSTD_CStreamOutSize(void); </b>/**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */<b>
</b></pre><BR>
<a name="Chapter11"></a><h2>This is a legacy streaming API, and can be replaced by ZSTD_CCtx_reset() and</h2><pre> ZSTD_compressStream2(). It is redundent, but is still fully supported.
Advanced parameters and dictionary compression can only be used through the
new API.
<BR></pre>
<a name="Chapter12"></a><h2>Equivalent to:</h2><pre>
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
<BR></pre>
<a name="Chapter13"></a><h2>Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).</h2><pre> NOTE: The return value is different. ZSTD_compressStream() returns a hint for
the next read size (if non-zero and not an error). ZSTD_compressStream2()
returns the number of bytes left to flush (if non-zero and not an error).
<BR></pre>
<a name="Chapter14"></a><h2>Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush).</h2><pre></pre>
<a name="Chapter15"></a><h2>Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end).</h2><pre></pre>
<a name="Chapter16"></a><h2>Streaming decompression - HowTo</h2><pre>
A ZSTD_DStream object is required to track streaming operations.
Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
ZSTD_DStream objects can be re-used multiple times.
Use ZSTD_initDStream() to start a new decompression operation.
@return : recommended first input size
Alternatively, use advanced API to set specific properties.
Use ZSTD_decompressStream() repetitively to consume your input.
The function will update both `pos` fields.
If `input.pos < input.size`, some input has not been consumed.
It's up to the caller to present again remaining data.
The function tries to flush all data decoded immediately, respecting output buffer size.
If `output.pos < output.size`, decoder has flushed everything it could.
But if `output.pos == output.size`, there might be some data left within internal buffers.,
In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
@return : 0 when a frame is completely decoded and fully flushed,
or an error code, which can be tested using ZSTD_isError(),
or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
the return value is a suggested next input size (just a hint for better latency)
that will never request more than the remaining frame size.
<BR></pre>
<pre><b>typedef ZSTD_DCtx ZSTD_DStream; </b>/**< DCtx and DStream are now effectively same object (>= v1.3.0) */<b>
</b></pre><BR>
<h3>ZSTD_DStream management functions</h3><pre></pre><b><pre>ZSTD_DStream* ZSTD_createDStream(void);
size_t ZSTD_freeDStream(ZSTD_DStream* zds);
</pre></b><BR>
<h3>Streaming decompression functions</h3><pre></pre><b><pre>size_t ZSTD_initDStream(ZSTD_DStream* zds);
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
</pre></b><BR>
<pre><b>size_t ZSTD_DStreamInSize(void); </b>/*!< recommended size for input buffer */<b>
</b></pre><BR>
<pre><b>size_t ZSTD_DStreamOutSize(void); </b>/*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */<b>
</b></pre><BR>
<a name="Chapter17"></a><h2>Simple dictionary API</h2><pre></pre>
<pre><b>size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize,
int compressionLevel);
</b><p> Compression at an explicit compression level using a Dictionary.
A dictionary can be any arbitrary data segment (also called a prefix),
or a buffer with specified information (see dictBuilder/zdict.h).
Note : This function loads the dictionary, resulting in significant startup delay.
It's intended for a dictionary used only once.
Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used.
</p></pre><BR>
<pre><b>size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize);
</b><p> Decompression using a known Dictionary.
Dictionary must be identical to the one used during compression.
Note : This function loads the dictionary, resulting in significant startup delay.
It's intended for a dictionary used only once.
Note : When `dict == NULL || dictSize < 8` no dictionary is used.
</p></pre><BR>
<a name="Chapter18"></a><h2>Bulk processing dictionary API</h2><pre></pre>
<pre><b>ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
int compressionLevel);
</b><p> When compressing multiple messages / blocks using the same dictionary, it's recommended to load it only once.
ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup cost.
ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
`dictBuffer` can be released after ZSTD_CDict creation, because its content is copied within CDict.
Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate `dictBuffer` content.
Note : A ZSTD_CDict can be created from an empty dictBuffer, but it is inefficient when used to compress small data.
</p></pre><BR>
<pre><b>size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
</b><p> Function frees memory allocated by ZSTD_createCDict().
</p></pre><BR>
<pre><b>size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict);
</b><p> Compression using a digested Dictionary.
Recommended when same dictionary is used multiple times.
Note : compression level is _decided at dictionary creation time_,
and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no)
</p></pre><BR>
<pre><b>ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
</b><p> Create a digested dictionary, ready to start decompression operation without startup delay.
dictBuffer can be released after DDict creation, as its content is copied inside DDict.
</p></pre><BR>
<pre><b>size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
</b><p> Function frees memory allocated with ZSTD_createDDict()
</p></pre><BR>
<pre><b>size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_DDict* ddict);
</b><p> Decompression using a digested Dictionary.
Recommended when same dictionary is used multiple times.
</p></pre><BR>
<a name="Chapter19"></a><h2>Dictionary helper functions</h2><pre></pre>
<pre><b>unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
</b><p> Provides the dictID stored within dictionary.
if @return == 0, the dictionary is not conformant with Zstandard specification.
It can still be loaded, but as a content-only dictionary.
</p></pre><BR>
<pre><b>unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
</b><p> Provides the dictID of the dictionary loaded into `ddict`.
If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
Non-conformant dictionaries can still be loaded, but as content-only dictionaries.
</p></pre><BR>
<pre><b>unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
</b><p> Provides the dictID required to decompressed the frame stored within `src`.
If @return == 0, the dictID could not be decoded.
This could for one of the following reasons :
- The frame does not require a dictionary to be decoded (most common case).
- The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
Note : this use case also happens when using a non-conformant dictionary.
- `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
- This is not a Zstandard frame.
When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code.
</p></pre><BR>
<a name="Chapter20"></a><h2>Advanced dictionary and prefix API</h2><pre>
This API allows dictionaries to be used with ZSTD_compress2(),
ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
only reset with the context is reset with ZSTD_reset_parameters or
ZSTD_reset_session_and_parameters. Prefixes are single-use.
<BR></pre>
<pre><b>size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
</b><p> Create an internal CDict from `dict` buffer.
Decompression will have to use same dictionary.
@result : 0, or an error code (which can be tested with ZSTD_isError()).
Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,
meaning "return to no-dictionary mode".
Note 1 : Dictionary is sticky, it will be used for all future compressed frames.
To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters).
Note 2 : Loading a dictionary involves building tables.
It's also a CPU consuming operation, with non-negligible impact on latency.
Tables are dependent on compression parameters, and for this reason,
compression parameters can no longer be changed after loading a dictionary.
Note 3 :`dict` content will be copied internally.
Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.
In such a case, dictionary buffer must outlive its users.
Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()
to precisely select how dictionary content must be interpreted.
</p></pre><BR>
<pre><b>size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
</b><p> Reference a prepared dictionary, to be used for all next compressed frames.
Note that compression parameters are enforced from within CDict,
and supersede any compression parameter previously set within CCtx.
The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
The dictionary will remain valid for future compressed frames using same CCtx.
@result : 0, or an error code (which can be tested with ZSTD_isError()).
Special : Referencing a NULL CDict means "return to no-dictionary mode".
Note 1 : Currently, only one dictionary can be managed.
Referencing a new dictionary effectively "discards" any previous one.
Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx.
</p></pre><BR>
<pre><b>size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
const void* prefix, size_t prefixSize);
</b><p> Reference a prefix (single-usage dictionary) for next compressed frame.
A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
Decompression will need same prefix to properly regenerate data.
Compressing with a prefix is similar in outcome as performing a diff and compressing it,
but performs much faster, especially during decompression (compression speed is tunable with compression level).
@result : 0, or an error code (which can be tested with ZSTD_isError()).
Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary
Note 1 : Prefix buffer is referenced. It **must** outlive compression.
Its content must remain unmodified during compression.
Note 2 : If the intention is to diff some large src data blob with some prior version of itself,
ensure that the window size is large enough to contain the entire source.
See ZSTD_c_windowLog.
Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.
It's a CPU consuming operation, with non-negligible impact on latency.
If there is a need to use the same prefix multiple times, consider loadDictionary instead.
Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dm_rawContent).
Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation.
</p></pre><BR>
<pre><b>size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); <pre><b>size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
</b><p> Create an internal DDict from dict buffer, </b><p> Create an internal DDict from dict buffer,
to be used to decompress next frames. to be used to decompress next frames.
@@ -793,15 +857,25 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
</p></pre><BR> </p></pre><BR>
<pre><b>size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset); <pre><b>size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
</b><p> Return a DCtx to clean state. size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
Session and parameters can be reset jointly or separately. size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
Parameters can only be reset when no active frame is being decompressed. size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
@return : 0, or an error code, which can be tested with ZSTD_isError() size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
</b><p> These functions give the _current_ memory usage of selected object.
Note that object memory usage can evolve (increase or decrease) over time.
</p></pre><BR> </p></pre><BR>
<a name="Chapter14"></a><h2>experimental API (static linking only)</h2><pre> <a name="Chapter21"></a><h2>ADVANCED AND EXPERIMENTAL FUNCTIONS</h2><pre>
The definitions in the following section are considered experimental.
They are provided for advanced scenarios.
They should never be used with a dynamic library, as prototypes may change in the future.
Use them only in association with static linking.
<BR></pre>
<a name="Chapter22"></a><h2>experimental API (static linking only)</h2><pre>
The following symbols and constants The following symbols and constants
are not planned to join "stable API" status in the near future. are not planned to join "stable API" status in the near future.
They can still change in future versions. They can still change in future versions.
@@ -890,12 +964,21 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
ZSTD_dictForceCopy = 2, </b>/* Always copy the dictionary. */<b> ZSTD_dictForceCopy = 2, </b>/* Always copy the dictionary. */<b>
} ZSTD_dictAttachPref_e; } ZSTD_dictAttachPref_e;
</b></pre><BR> </b></pre><BR>
<a name="Chapter15"></a><h2>Frame size functions</h2><pre></pre> <pre><b>typedef enum {
ZSTD_lcm_auto = 0, </b>/**< Automatically determine the compression mode based on the compression level.<b>
* Negative compression levels will be uncompressed, and positive compression
* levels will be compressed. */
ZSTD_lcm_huffman = 1, </b>/**< Always attempt Huffman compression. Uncompressed literals will still be<b>
* emitted if Huffman compression is not profitable. */
ZSTD_lcm_uncompressed = 2, </b>/**< Always emit uncompressed literals. */<b>
} ZSTD_literalCompressionMode_e;
</b></pre><BR>
<a name="Chapter23"></a><h2>Frame size functions</h2><pre></pre>
<pre><b>unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); <pre><b>unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
</b><p> `src` should point the start of a series of ZSTD encoded and/or skippable frames </b><p> `src` should point to the start of a series of ZSTD encoded and/or skippable frames
`srcSize` must be the _exact_ size of this series `srcSize` must be the _exact_ size of this series
(i.e. there should be a frame boundary exactly at `srcSize` bytes after `src`) (i.e. there should be a frame boundary at `src + srcSize`)
@return : - decompressed size of all data in all successive frames @return : - decompressed size of all data in all successive frames
- if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN
- if an error occurred: ZSTD_CONTENTSIZE_ERROR - if an error occurred: ZSTD_CONTENTSIZE_ERROR
@@ -915,13 +998,27 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
however it does mean that all frame data must be present and valid. however it does mean that all frame data must be present and valid.
</p></pre><BR> </p></pre><BR>
<a name="Chapter24"></a><h2>ZSTD_decompressBound() :</h2><pre> `src` should point to the start of a series of ZSTD encoded and/or skippable frames
`srcSize` must be the _exact_ size of this series
(i.e. there should be a frame boundary at `src + srcSize`)
@return : - upper-bound for the decompressed size of all data in all successive frames
- if an error occured: ZSTD_CONTENTSIZE_ERROR
note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame.
note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.
note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:
upper-bound = # blocks * min(128 KB, Window_Size)
<BR></pre>
<pre><b>size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); <pre><b>size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
</b><p> srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. </b><p> srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
@return : size of the Frame Header, @return : size of the Frame Header,
or an error code (if srcSize is too small) or an error code (if srcSize is too small)
</p></pre><BR> </p></pre><BR>
<a name="Chapter16"></a><h2>Memory management</h2><pre></pre> <a name="Chapter25"></a><h2>Memory management</h2><pre></pre>
<pre><b>size_t ZSTD_estimateCCtxSize(int compressionLevel); <pre><b>size_t ZSTD_estimateCCtxSize(int compressionLevel);
size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
@@ -933,7 +1030,7 @@ size_t ZSTD_estimateDCtxSize(void);
It will also consider src size to be arbitrarily "large", which is worst case. It will also consider src size to be arbitrarily "large", which is worst case.
If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation. If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation.
ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1. ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
Note : CCtx size estimation is only correct for single-threaded compression. Note : CCtx size estimation is only correct for single-threaded compression.
</p></pre><BR> </p></pre><BR>
@@ -946,7 +1043,7 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
It will also consider src size to be arbitrarily "large", which is worst case. It will also consider src size to be arbitrarily "large", which is worst case.
If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation. If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1. ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
Note : CStream size estimation is only correct for single-threaded compression. Note : CStream size estimation is only correct for single-threaded compression.
ZSTD_DStream memory budget depends on window Size. ZSTD_DStream memory budget depends on window Size.
This information can be passed manually, using ZSTD_estimateDStreamSize, This information can be passed manually, using ZSTD_estimateDStreamSize,
@@ -1001,7 +1098,7 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; </b>/**< t
</p></pre><BR> </p></pre><BR>
<a name="Chapter17"></a><h2>Advanced compression functions</h2><pre></pre> <a name="Chapter26"></a><h2>Advanced compression functions</h2><pre></pre>
<pre><b>ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); <pre><b>ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
</b><p> Create a digested dictionary for compression </b><p> Create a digested dictionary for compression
@@ -1011,22 +1108,26 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; </b>/**< t
</p></pre><BR> </p></pre><BR>
<pre><b>ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); <pre><b>ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
</b><p> @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. </b><p> @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
`estimatedSrcSize` value is optional, select 0 if not known `estimatedSrcSize` value is optional, select 0 if not known
</p></pre><BR> </p></pre><BR>
<pre><b>ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); <pre><b>ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
</b><p> same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`. </b><p> same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0
</p></pre><BR> </p></pre><BR>
<pre><b>size_t ZSTD_checkCParams(ZSTD_compressionParameters params); <pre><b>size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
</b><p> Ensure param values remain within authorized range </b><p> Ensure param values remain within authorized range.
@return 0 on success, or an error code (can be checked with ZSTD_isError())
</p></pre><BR> </p></pre><BR>
<pre><b>ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize); <pre><b>ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
</b><p> optimize params for a given `srcSize` and `dictSize`. </b><p> optimize params for a given `srcSize` and `dictSize`.
both values are optional, select `0` if unknown. `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.
`dictSize` must be `0` when there is no dictionary.
cPar can be invalid : all parameters will be clamped within valid range in the @return struct.
This function never fails (wide contract)
</p></pre><BR> </p></pre><BR>
<pre><b>size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, <pre><b>size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
@@ -1072,10 +1173,10 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; </b>/**< t
size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
</b><p> Quick howto : </b><p> Quick howto :
- ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
- ZSTD_CCtxParam_setParameter() : Push parameters one by one into - ZSTD_CCtxParams_setParameter() : Push parameters one by one into
an existing ZSTD_CCtx_params structure. an existing ZSTD_CCtx_params structure.
This is similar to This is similar to
ZSTD_CCtx_setParameter(). ZSTD_CCtx_setParameter().
- ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to
an existing CCtx. an existing CCtx.
These parameters will be applied to These parameters will be applied to
@@ -1105,7 +1206,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
</p></pre><BR> </p></pre><BR>
<pre><b>size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value); <pre><b>size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
</b><p> Similar to ZSTD_CCtx_setParameter. </b><p> Similar to ZSTD_CCtx_setParameter.
Set one compression parameter, selected by enum ZSTD_cParameter. Set one compression parameter, selected by enum ZSTD_cParameter.
Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams(). Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
@@ -1113,7 +1214,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
</p></pre><BR> </p></pre><BR>
<pre><b>size_t ZSTD_CCtxParam_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value); <pre><b>size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
</b><p> Similar to ZSTD_CCtx_getParameter. </b><p> Similar to ZSTD_CCtx_getParameter.
Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
@result : 0, or an error code (which can be tested with ZSTD_isError()). @result : 0, or an error code (which can be tested with ZSTD_isError()).
@@ -1142,7 +1243,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
</p></pre><BR> </p></pre><BR>
<a name="Chapter18"></a><h2>Advanced decompression functions</h2><pre></pre> <a name="Chapter27"></a><h2>Advanced decompression functions</h2><pre></pre>
<pre><b>unsigned ZSTD_isFrame(const void* buffer, size_t size); <pre><b>unsigned ZSTD_isFrame(const void* buffer, size_t size);
</b><p> Tells if the content of `buffer` starts with a valid Frame Identifier. </b><p> Tells if the content of `buffer` starts with a valid Frame Identifier.
@@ -1158,30 +1259,6 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
it must remain read accessible throughout the lifetime of DDict it must remain read accessible throughout the lifetime of DDict
</p></pre><BR> </p></pre><BR>
<pre><b>unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
</b><p> Provides the dictID stored within dictionary.
if @return == 0, the dictionary is not conformant with Zstandard specification.
It can still be loaded, but as a content-only dictionary.
</p></pre><BR>
<pre><b>unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
</b><p> Provides the dictID of the dictionary loaded into `ddict`.
If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
Non-conformant dictionaries can still be loaded, but as content-only dictionaries.
</p></pre><BR>
<pre><b>unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
</b><p> Provides the dictID required to decompressed the frame stored within `src`.
If @return == 0, the dictID could not be decoded.
This could for one of the following reasons :
- The frame does not require a dictionary to be decoded (most common case).
- The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
Note : this use case also happens when using a non-conformant dictionary.
- `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
- This is not a Zstandard frame.
When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code.
</p></pre><BR>
<pre><b>size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); <pre><b>size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
</b><p> Same as ZSTD_DCtx_loadDictionary(), </b><p> Same as ZSTD_DCtx_loadDictionary(),
but references `dict` content instead of copying it into `dctx`. but references `dict` content instead of copying it into `dctx`.
@@ -1228,20 +1305,74 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
</p></pre><BR> </p></pre><BR>
<a name="Chapter19"></a><h2>Advanced streaming functions</h2><pre> Warning : most of these functions are now redundant with the Advanced API. <a name="Chapter28"></a><h2>Advanced streaming functions</h2><pre> Warning : most of these functions are now redundant with the Advanced API.
Once Advanced API reaches "stable" status, Once Advanced API reaches "stable" status,
redundant functions will be deprecated, and then at some point removed. redundant functions will be deprecated, and then at some point removed.
<BR></pre> <BR></pre>
<h3>Advanced Streaming compression functions</h3><pre></pre><b><pre>size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); </b>/**< pledgedSrcSize must be correct. If it is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, "0" also disables frame content size field. It may be enabled in the future. */<b> <h3>Advanced Streaming compression functions</h3><pre></pre><b><pre></b>/**! ZSTD_initCStream_srcSize() :<b>
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); </b>/**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.*/<b> * This function is deprecated, and equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
*
* pledgedSrcSize must be correct. If it is not known at init time, use
* ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
* "0" also disables frame content size field. It may be enabled in the future.
*/
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize);
</b>/**! ZSTD_initCStream_usingDict() :<b>
* This function is deprecated, and is equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
*
* Creates of an internal CDict (incompatible with static CCtx), except if
* dict == NULL or dictSize < 8, in which case no dict is used.
* Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if
* it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
*/
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel);
</b>/**! ZSTD_initCStream_advanced() :<b>
* This function is deprecated, and is approximately equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_setZstdParams(zcs, params); // Set the zstd params and leave the rest as-is
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
*
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
* value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy.
*/
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
ZSTD_parameters params, unsigned long long pledgedSrcSize); </b>/**< pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy. */<b> ZSTD_parameters params, unsigned long long pledgedSrcSize);
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); </b>/**< note : cdict will just be referenced, and must outlive compression session */<b> </b>/**! ZSTD_initCStream_usingCDict() :<b>
size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize); </b>/**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters. pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. */<b> * This function is deprecated, and equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_refCDict(zcs, cdict);
*
* note : cdict will just be referenced, and must outlive compression session
*/
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
</b>/**! ZSTD_initCStream_usingCDict_advanced() :<b>
* This function is deprecated, and is approximately equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_setZstdFrameParams(zcs, fParams); // Set the zstd frame params and leave the rest as-is
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
* ZSTD_CCtx_refCDict(zcs, cdict);
*
* same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
* value ZSTD_CONTENTSIZE_UNKNOWN.
*/
size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize);
</pre></b><BR> </pre></b><BR>
<pre><b>size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); <pre><b>size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
</b><p> start a new frame, using same parameters from previous frame. </b><p> This function is deprecated, and is equivalent to:
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
start a new frame, using same parameters from previous frame.
This is typically useful to skip dictionary loading stage, since it will re-use it in-place. This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
Note that zcs must be init at least once before using ZSTD_resetCStream(). Note that zcs must be init at least once before using ZSTD_resetCStream().
If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN. If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN.
@@ -1280,14 +1411,14 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict*
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); </b>/**< note : ddict is referenced, it must outlive decompression session */<b> size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); </b>/**< note : ddict is referenced, it must outlive decompression session */<b>
size_t ZSTD_resetDStream(ZSTD_DStream* zds); </b>/**< re-use decompression parameters from previous init; saves dictionary loading */<b> size_t ZSTD_resetDStream(ZSTD_DStream* zds); </b>/**< re-use decompression parameters from previous init; saves dictionary loading */<b>
</pre></b><BR> </pre></b><BR>
<a name="Chapter20"></a><h2>Buffer-less and synchronous inner streaming functions</h2><pre> <a name="Chapter29"></a><h2>Buffer-less and synchronous inner streaming functions</h2><pre>
This is an advanced API, giving full control over buffer management, for users which need direct control over memory. This is an advanced API, giving full control over buffer management, for users which need direct control over memory.
But it's also a complex one, with several restrictions, documented below. But it's also a complex one, with several restrictions, documented below.
Prefer normal streaming API for an easier experience. Prefer normal streaming API for an easier experience.
<BR></pre> <BR></pre>
<a name="Chapter21"></a><h2>Buffer-less streaming compression (synchronous mode)</h2><pre> <a name="Chapter30"></a><h2>Buffer-less streaming compression (synchronous mode)</h2><pre>
A ZSTD_CCtx object is required to track streaming operations. A ZSTD_CCtx object is required to track streaming operations.
Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource. Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.
ZSTD_CCtx object can be re-used multiple times within successive compression operations. ZSTD_CCtx object can be re-used multiple times within successive compression operations.
@@ -1323,7 +1454,7 @@ size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); </b>/* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */<b> size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); </b>/* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */<b>
size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); </b>/**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */<b> size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); </b>/**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */<b>
</pre></b><BR> </pre></b><BR>
<a name="Chapter22"></a><h2>Buffer-less streaming decompression (synchronous mode)</h2><pre> <a name="Chapter31"></a><h2>Buffer-less streaming decompression (synchronous mode)</h2><pre>
A ZSTD_DCtx object is required to track streaming operations. A ZSTD_DCtx object is required to track streaming operations.
Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
A ZSTD_DCtx object can be re-used multiple times. A ZSTD_DCtx object can be re-used multiple times.
@@ -1405,7 +1536,7 @@ typedef struct {
unsigned checksumFlag; unsigned checksumFlag;
} ZSTD_frameHeader; } ZSTD_frameHeader;
</pre></b><BR> </pre></b><BR>
<a name="Chapter23"></a><h2>ZSTD_getFrameHeader() :</h2><pre> decode Frame Header, or requires larger `srcSize`. <a name="Chapter32"></a><h2>ZSTD_getFrameHeader() :</h2><pre> decode Frame Header, or requires larger `srcSize`.
@return : 0, `zfhPtr` is correctly filled, @return : 0, `zfhPtr` is correctly filled,
>0, `srcSize` is too small, value is wanted `srcSize` amount, >0, `srcSize` is too small, value is wanted `srcSize` amount,
or an error code, which can be tested using ZSTD_isError() or an error code, which can be tested using ZSTD_isError()
@@ -1421,7 +1552,7 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
<pre><b>typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; <pre><b>typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
</b></pre><BR> </b></pre><BR>
<a name="Chapter24"></a><h2>Block level API</h2><pre></pre> <a name="Chapter33"></a><h2>Block level API</h2><pre></pre>
<pre><b></b><p> Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes). <pre><b></b><p> Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes).
User will have to take in charge required information to regenerate data, such as compressed and content sizes. User will have to take in charge required information to regenerate data, such as compressed and content sizes.
+8 -8
View File
@@ -25,28 +25,28 @@ all: simple_compression simple_decompression \
$(LIB) : $(LIB) :
$(MAKE) -C ../lib libzstd.a $(MAKE) -C ../lib libzstd.a
simple_compression : simple_compression.c utils.h $(LIB) simple_compression : simple_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
simple_decompression : simple_decompression.c utils.h $(LIB) simple_decompression : simple_decompression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
multiple_simple_compression : multiple_simple_compression.c utils.h $(LIB) multiple_simple_compression : multiple_simple_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
dictionary_compression : dictionary_compression.c utils.h $(LIB) dictionary_compression : dictionary_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
dictionary_decompression : dictionary_decompression.c utils.h $(LIB) dictionary_decompression : dictionary_decompression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
streaming_compression : streaming_compression.c utils.h $(LIB) streaming_compression : streaming_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
multiple_streaming_compression : multiple_streaming_compression.c utils.h $(LIB) multiple_streaming_compression : multiple_streaming_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
streaming_decompression : streaming_decompression.c utils.h $(LIB) streaming_decompression : streaming_decompression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
streaming_memory_usage : streaming_memory_usage.c $(LIB) streaming_memory_usage : streaming_memory_usage.c $(LIB)
+35 -8
View File
@@ -11,15 +11,15 @@
/* /*
* This header file has common utility functions used in examples. * This header file has common utility functions used in examples.
*/ */
#ifndef UTILS_H #ifndef COMMON_H
#define UTILS_H #define COMMON_H
#include <stdlib.h> // malloc, free, exit #include <stdlib.h> // malloc, free, exit
#include <stdio.h> // fprintf, perror, fopen, etc. #include <stdio.h> // fprintf, perror, fopen, etc.
#include <string.h> // strlen, strcat, memset, strerror #include <string.h> // strerror
#include <errno.h> // errno #include <errno.h> // errno
#include <assert.h> // assert
#include <sys/stat.h> // stat #include <sys/stat.h> // stat
#include <zstd.h>
/* /*
* Define the returned error code from utility functions. * Define the returned error code from utility functions.
@@ -34,7 +34,34 @@ typedef enum {
ERROR_saveFile = 7, ERROR_saveFile = 7,
ERROR_malloc = 8, ERROR_malloc = 8,
ERROR_largeFile = 9, ERROR_largeFile = 9,
} UTILS_ErrorCode; } COMMON_ErrorCode;
/*! CHECK
* Check that the condition holds. If it doesn't print a message and die.
*/
#define CHECK(cond, ...) \
do { \
if (!(cond)) { \
fprintf(stderr, \
"%s:%d CHECK(%s) failed: ", \
__FILE__, \
__LINE__, \
#cond); \
fprintf(stderr, "" __VA_ARGS__); \
fprintf(stderr, "\n"); \
exit(1); \
} \
} while (0)
/*! CHECK_ZSTD
* Check the zstd error code and die if an error occurred after printing a
* message.
*/
#define CHECK_ZSTD(fn, ...) \
do { \
size_t const err = (fn); \
CHECK(!ZSTD_isError(err), "%s", ZSTD_getErrorName(err)); \
} while (0)
/*! fsize_orDie() : /*! fsize_orDie() :
* Get the size of a given file path. * Get the size of a given file path.
@@ -56,7 +83,7 @@ static size_t fsize_orDie(const char *filename)
* 2. if off_t -> size_t type conversion results in discrepancy, * 2. if off_t -> size_t type conversion results in discrepancy,
* the file size is too large for type size_t. * the file size is too large for type size_t.
*/ */
if ((fileSize < 0) || (fileSize != (off_t)size)) { if ((fileSize < 0) || (fileSize != (off_t)size)) {
fprintf(stderr, "%s : filesize too large \n", filename); fprintf(stderr, "%s : filesize too large \n", filename);
exit(ERROR_largeFile); exit(ERROR_largeFile);
} }
@@ -150,10 +177,10 @@ static void* malloc_orDie(size_t size)
* @return If successful this function will load file into buffer and * @return If successful this function will load file into buffer and
* return file size, otherwise it will printout an error to stderr and exit. * return file size, otherwise it will printout an error to stderr and exit.
*/ */
static size_t loadFile_orDie(const char* fileName, void* buffer, int bufferSize) static size_t loadFile_orDie(const char* fileName, void* buffer, size_t bufferSize)
{ {
size_t const fileSize = fsize_orDie(fileName); size_t const fileSize = fsize_orDie(fileName);
assert(fileSize <= bufferSize); CHECK(fileSize <= bufferSize, "File too large!");
FILE* const inFile = fopen_orDie(fileName, "rb"); FILE* const inFile = fopen_orDie(fileName, "rb");
size_t const readSize = fread(buffer, 1, fileSize, inFile); size_t const readSize = fread(buffer, 1, fileSize, inFile);
+12 -14
View File
@@ -7,13 +7,11 @@
* in the COPYING file in the root directory of this source tree). * in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses. * You may select, at your option, one of the above-listed licenses.
*/ */
#include <stdlib.h> // malloc, exit
#include <stdio.h> // printf #include <stdio.h> // printf
#include <string.h> // strerror #include <stdlib.h> // free
#include <errno.h> // errno #include <string.h> // memset, strcat
#include <sys/stat.h> // stat
#include <zstd.h> // presumes zstd library is installed #include <zstd.h> // presumes zstd library is installed
#include "utils.h" #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
/* createDict() : /* createDict() :
`dictFileName` is supposed to have been created using `zstd --train` */ `dictFileName` is supposed to have been created using `zstd --train` */
@@ -23,10 +21,7 @@ static ZSTD_CDict* createCDict_orDie(const char* dictFileName, int cLevel)
printf("loading dictionary %s \n", dictFileName); printf("loading dictionary %s \n", dictFileName);
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize); void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel); ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel);
if (!cdict) { CHECK(cdict != NULL, "ZSTD_createCDict() failed!");
fprintf(stderr, "ZSTD_createCDict error \n");
exit(7);
}
free(dictBuffer); free(dictBuffer);
return cdict; return cdict;
} }
@@ -39,13 +34,16 @@ static void compress(const char* fname, const char* oname, const ZSTD_CDict* cdi
size_t const cBuffSize = ZSTD_compressBound(fSize); size_t const cBuffSize = ZSTD_compressBound(fSize);
void* const cBuff = malloc_orDie(cBuffSize); void* const cBuff = malloc_orDie(cBuffSize);
/* Compress using the dictionary.
* This function writes the dictionary id, and content size into the header.
* But, it doesn't use a checksum. You can control these options using the
* advanced API: ZSTD_CCtx_setParameter(), ZSTD_CCtx_refCDict(),
* and ZSTD_compress2().
*/
ZSTD_CCtx* const cctx = ZSTD_createCCtx(); ZSTD_CCtx* const cctx = ZSTD_createCCtx();
if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); } CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict); size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict);
if (ZSTD_isError(cSize)) { CHECK_ZSTD(cSize);
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
exit(7);
}
saveFile_orDie(oname, cBuff, cSize); saveFile_orDie(oname, cBuff, cSize);
+33 -22
View File
@@ -9,15 +9,10 @@
*/ */
#include <stdlib.h> // malloc, exit
#include <stdio.h> // printf #include <stdio.h> // printf
#include <string.h> // strerror #include <stdlib.h> // free
#include <errno.h> // errno
#include <sys/stat.h> // stat
#define ZSTD_STATIC_LINKING_ONLY // ZSTD_findDecompressedSize
#include <zstd.h> // presumes zstd library is installed #include <zstd.h> // presumes zstd library is installed
#include "utils.h" #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
/* createDict() : /* createDict() :
`dictFileName` is supposed to have been created using `zstd --train` */ `dictFileName` is supposed to have been created using `zstd --train` */
@@ -27,7 +22,7 @@ static ZSTD_DDict* createDict_orDie(const char* dictFileName)
printf("loading dictionary %s \n", dictFileName); printf("loading dictionary %s \n", dictFileName);
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize); void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize); ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize);
if (ddict==NULL) { fprintf(stderr, "ZSTD_createDDict error \n"); exit(5); } CHECK(ddict != NULL, "ZSTD_createDDict() failed!");
free(dictBuffer); free(dictBuffer);
return ddict; return ddict;
} }
@@ -36,24 +31,40 @@ static void decompress(const char* fname, const ZSTD_DDict* ddict)
{ {
size_t cSize; size_t cSize;
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize); void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize); /* Read the content size from the frame header. For simplicity we require
if (rSize==ZSTD_CONTENTSIZE_ERROR) { * that it is always present. By default, zstd will write the content size
fprintf(stderr, "%s : it was not compressed by zstd.\n", fname); * in the header when it is known. If you can't guarantee that the frame
exit(5); * content size is always written into the header, either use streaming
} else if (rSize==ZSTD_CONTENTSIZE_UNKNOWN) { * decompression, or ZSTD_decompressBound().
fprintf(stderr, "%s : original size unknown \n", fname); */
exit(6); unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
} CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, "%s: not compressed by zstd!", fname);
CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, "%s: original size unknown!", fname);
void* const rBuff = malloc_orDie((size_t)rSize); void* const rBuff = malloc_orDie((size_t)rSize);
/* Check that the dictionary ID matches.
* If a non-zstd dictionary is used, then both will be zero.
* By default zstd always writes the dictionary ID into the frame.
* Zstd will check if there is a dictionary ID mismatch as well.
*/
unsigned const expectedDictID = ZSTD_getDictID_fromDDict(ddict);
unsigned const actualDictID = ZSTD_getDictID_fromFrame(cBuff, cSize);
CHECK(actualDictID == expectedDictID,
"DictID mismatch: expected %u got %u",
expectedDictID,
actualDictID);
/* Decompress using the dictionary.
* If you need to control the decompression parameters, then use the
* advanced API: ZSTD_DCtx_setParameter(), ZSTD_DCtx_refDDict(), and
* ZSTD_decompressDCtx().
*/
ZSTD_DCtx* const dctx = ZSTD_createDCtx(); ZSTD_DCtx* const dctx = ZSTD_createDCtx();
if (dctx==NULL) { fprintf(stderr, "ZSTD_createDCtx() error \n"); exit(10); } CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
size_t const dSize = ZSTD_decompress_usingDDict(dctx, rBuff, rSize, cBuff, cSize, ddict); size_t const dSize = ZSTD_decompress_usingDDict(dctx, rBuff, rSize, cBuff, cSize, ddict);
if (dSize != rSize) { CHECK_ZSTD(dSize);
fprintf(stderr, "error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize)); /* When zstd knows the content size, it will error if it doesn't match. */
exit(7); CHECK(dSize == rSize, "Impossible because zstd will check this condition!");
}
/* success */ /* success */
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize); printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
+17 -18
View File
@@ -8,13 +8,11 @@
* You may select, at your option, one of the above-listed licenses. * You may select, at your option, one of the above-listed licenses.
*/ */
#include <stdlib.h> // malloc, free, exit #include <stdio.h> // printf
#include <stdio.h> // fprintf, perror, fopen, etc. #include <stdlib.h> // free
#include <string.h> // strlen, strcat, memset, strerror #include <string.h> // memcpy, strlen
#include <errno.h> // errno
#include <sys/stat.h> // stat
#include <zstd.h> // presumes zstd library is installed #include <zstd.h> // presumes zstd library is installed
#include "utils.h" #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
typedef struct { typedef struct {
void* fBuffer; void* fBuffer;
@@ -28,7 +26,7 @@ typedef struct {
* allocate memory for buffers big enough to compress all files * allocate memory for buffers big enough to compress all files
* as well as memory for output file name (ofn) * as well as memory for output file name (ofn)
*/ */
static resources createResources_orDie(int argc, const char** argv, char **ofn, int* ofnBufferLen) static resources createResources_orDie(int argc, const char** argv, char **ofn, size_t* ofnBufferLen)
{ {
size_t maxFilenameLength=0; size_t maxFilenameLength=0;
size_t maxFileSize = 0; size_t maxFileSize = 0;
@@ -52,7 +50,7 @@ static resources createResources_orDie(int argc, const char** argv, char **ofn,
ress.fBuffer = malloc_orDie(ress.fBufferSize); ress.fBuffer = malloc_orDie(ress.fBufferSize);
ress.cBuffer = malloc_orDie(ress.cBufferSize); ress.cBuffer = malloc_orDie(ress.cBufferSize);
ress.cctx = ZSTD_createCCtx(); ress.cctx = ZSTD_createCCtx();
if (ress.cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); } CHECK(ress.cctx != NULL, "ZSTD_createCCtx() failed!");
return ress; return ress;
} }
@@ -69,16 +67,17 @@ static void compressFile_orDie(resources ress, const char* fname, const char* on
{ {
size_t fSize = loadFile_orDie(fname, ress.fBuffer, ress.fBufferSize); size_t fSize = loadFile_orDie(fname, ress.fBuffer, ress.fBufferSize);
/* Compress using the context.
* If you need more control over parameters, use the advanced API:
* ZSTD_CCtx_setParameter(), and ZSTD_compress2().
*/
size_t const cSize = ZSTD_compressCCtx(ress.cctx, ress.cBuffer, ress.cBufferSize, ress.fBuffer, fSize, 1); size_t const cSize = ZSTD_compressCCtx(ress.cctx, ress.cBuffer, ress.cBufferSize, ress.fBuffer, fSize, 1);
if (ZSTD_isError(cSize)) { CHECK_ZSTD(cSize);
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
exit(8);
}
saveFile_orDie(oname, ress.cBuffer, cSize); saveFile_orDie(oname, ress.cBuffer, cSize);
/* success */ /* success */
// printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname); printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname);
} }
int main(int argc, const char** argv) int main(int argc, const char** argv)
@@ -94,21 +93,21 @@ int main(int argc, const char** argv)
/* memory allocation for outFilename and resources */ /* memory allocation for outFilename and resources */
char* outFilename; char* outFilename;
int outFilenameBufferLen; size_t outFilenameBufferLen;
resources const ress = createResources_orDie(argc, argv, &outFilename, &outFilenameBufferLen); resources const ress = createResources_orDie(argc, argv, &outFilename, &outFilenameBufferLen);
/* compress files with shared context, input and output buffers */ /* compress files with shared context, input and output buffers */
int argNb; int argNb;
for (argNb = 1; argNb < argc; argNb++) { for (argNb = 1; argNb < argc; argNb++) {
const char* const inFilename = argv[argNb]; const char* const inFilename = argv[argNb];
int inFilenameLen = strlen(inFilename); size_t const inFilenameLen = strlen(inFilename);
assert(inFilenameLen + 5 <= outFilenameBufferLen); CHECK(inFilenameLen + 5 <= outFilenameBufferLen, "File name too long!");
memcpy(outFilename, inFilename, inFilenameLen); memcpy(outFilename, inFilename, inFilenameLen);
memcpy(outFilename+inFilenameLen, ".zst", 5); memcpy(outFilename+inFilenameLen, ".zst", 5);
compressFile_orDie(ress, inFilename, outFilename); compressFile_orDie(ress, inFilename, outFilename);
} }
/* free momery */ /* free memory */
freeResources(ress,outFilename); freeResources(ress,outFilename);
printf("compressed %i files \n", argc-1); printf("compressed %i files \n", argc-1);
+44 -29
View File
@@ -14,66 +14,80 @@
* All structures and buffers will be created only once, * All structures and buffers will be created only once,
* and shared across all compression operations */ * and shared across all compression operations */
#include <stdlib.h> // malloc, exit #include <stdio.h> // printf
#include <stdio.h> // fprintf, perror, feof #include <stdlib.h> // free
#include <string.h> // strerror #include <string.h> // memset, strcat
#include <errno.h> // errno
#define ZSTD_STATIC_LINKING_ONLY // streaming API defined as "experimental" for the time being
#include <zstd.h> // presumes zstd library is installed #include <zstd.h> // presumes zstd library is installed
#include "utils.h" #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
typedef struct { typedef struct {
void* buffIn; void* buffIn;
void* buffOut; void* buffOut;
size_t buffInSize; size_t buffInSize;
size_t buffOutSize; size_t buffOutSize;
ZSTD_CStream* cstream; ZSTD_CCtx* cctx;
} resources ; } resources;
static resources createResources_orDie() static resources createResources_orDie(int cLevel)
{ {
resources ress; resources ress;
ress.buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */ ress.buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */
ress.buffOutSize= ZSTD_CStreamOutSize(); /* can always flush a full block */ ress.buffOutSize= ZSTD_CStreamOutSize(); /* can always flush a full block */
ress.buffIn = malloc_orDie(ress.buffInSize); ress.buffIn = malloc_orDie(ress.buffInSize);
ress.buffOut= malloc_orDie(ress.buffOutSize); ress.buffOut= malloc_orDie(ress.buffOutSize);
ress.cstream = ZSTD_createCStream(); ress.cctx = ZSTD_createCCtx();
if (ress.cstream==NULL) { fprintf(stderr, "ZSTD_createCStream() error \n"); exit(10); } CHECK(ress.cctx != NULL, "ZSTD_createCCtx() failed!");
/* Set any compression parameters you want here.
* They will persist for every compression operation.
* Here we set the compression level, and enable the checksum.
*/
CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) );
CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, 1) );
return ress; return ress;
} }
static void freeResources(resources ress) static void freeResources(resources ress)
{ {
ZSTD_freeCStream(ress.cstream); ZSTD_freeCCtx(ress.cctx);
free(ress.buffIn); free(ress.buffIn);
free(ress.buffOut); free(ress.buffOut);
} }
static void compressFile_orDie(resources ress, const char* fname, const char* outName, int cLevel) static void compressFile_orDie(resources ress, const char* fname, const char* outName)
{ {
// Open the input and output files.
FILE* const fin = fopen_orDie(fname, "rb"); FILE* const fin = fopen_orDie(fname, "rb");
FILE* const fout = fopen_orDie(outName, "wb"); FILE* const fout = fopen_orDie(outName, "wb");
size_t const initResult = ZSTD_initCStream(ress.cstream, cLevel); /* Reset the context to a clean state to start a new compression operation.
if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initCStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); } * The parameters are sticky, so we keep the compression level and extra
* parameters that we set in createResources_orDie().
*/
CHECK_ZSTD( ZSTD_CCtx_reset(ress.cctx, ZSTD_reset_session_only) );
size_t const toRead = ress.buffInSize;
size_t read;
while ( (read = fread_orDie(ress.buffIn, toRead, fin)) ) {
/* This loop is the same as streaming_compression.c.
* See that file for detailed comments.
*/
int const lastChunk = (read < toRead);
ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;
size_t read, toRead = ress.buffInSize;
while( (read = fread_orDie(ress.buffIn, toRead, fin)) ) {
ZSTD_inBuffer input = { ress.buffIn, read, 0 }; ZSTD_inBuffer input = { ress.buffIn, read, 0 };
while (input.pos < input.size) { int finished;
do {
ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 }; ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 };
toRead = ZSTD_compressStream(ress.cstream, &output , &input); /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */ size_t const remaining = ZSTD_compressStream2(ress.cctx, &output, &input, mode);
if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_compressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); } CHECK_ZSTD(remaining);
if (toRead > ress.buffInSize) toRead = ress.buffInSize; /* Safely handle when `buffInSize` is manually changed to a smaller value */
fwrite_orDie(ress.buffOut, output.pos, fout); fwrite_orDie(ress.buffOut, output.pos, fout);
} finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
} while (!finished);
CHECK(input.pos == input.size,
"Impossible: zstd only returns 0 when the input is completely consumed!");
} }
ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 };
size_t const remainingToFlush = ZSTD_endStream(ress.cstream, &output); /* close frame */
if (remainingToFlush) { fprintf(stderr, "not fully flushed"); exit(13); }
fwrite_orDie(ress.buffOut, output.pos, fout);
fclose_orDie(fout); fclose_orDie(fout);
fclose_orDie(fin); fclose_orDie(fin);
} }
@@ -89,7 +103,8 @@ int main(int argc, const char** argv)
return 1; return 1;
} }
resources const ress = createResources_orDie(); int const cLevel = 7;
resources const ress = createResources_orDie(cLevel);
void* ofnBuffer = NULL; void* ofnBuffer = NULL;
size_t ofnbSize = 0; size_t ofnbSize = 0;
@@ -106,7 +121,7 @@ int main(int argc, const char** argv)
memset(ofnBuffer, 0, ofnSize); memset(ofnBuffer, 0, ofnSize);
strcat(ofnBuffer, ifn); strcat(ofnBuffer, ifn);
strcat(ofnBuffer, ".zst"); strcat(ofnBuffer, ".zst");
compressFile_orDie(ress, ifn, ofnBuffer, 7); compressFile_orDie(ress, ifn, ofnBuffer);
} }
freeResources(ress); freeResources(ress);
+9 -10
View File
@@ -8,13 +8,11 @@
* You may select, at your option, one of the above-listed licenses. * You may select, at your option, one of the above-listed licenses.
*/ */
#include <stdlib.h> // malloc, free, exit #include <stdio.h> // printf
#include <stdio.h> // fprintf, perror, fopen, etc. #include <stdlib.h> // free
#include <string.h> // strlen, strcat, memset, strerror #include <string.h> // strlen, strcat, memset
#include <errno.h> // errno
#include <sys/stat.h> // stat
#include <zstd.h> // presumes zstd library is installed #include <zstd.h> // presumes zstd library is installed
#include "utils.h" #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
static void compress_orDie(const char* fname, const char* oname) static void compress_orDie(const char* fname, const char* oname)
{ {
@@ -23,11 +21,12 @@ static void compress_orDie(const char* fname, const char* oname)
size_t const cBuffSize = ZSTD_compressBound(fSize); size_t const cBuffSize = ZSTD_compressBound(fSize);
void* const cBuff = malloc_orDie(cBuffSize); void* const cBuff = malloc_orDie(cBuffSize);
/* Compress.
* If you are doing many compressions, you may want to reuse the context.
* See the multiple_simple_compression.c example.
*/
size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1); size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1);
if (ZSTD_isError(cSize)) { CHECK_ZSTD(cSize);
fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
exit(8);
}
saveFile_orDie(oname, cBuff, cSize); saveFile_orDie(oname, cBuff, cSize);
+19 -20
View File
@@ -8,37 +8,36 @@
* You may select, at your option, one of the above-listed licenses. * You may select, at your option, one of the above-listed licenses.
*/ */
#include <stdlib.h> // malloc, exit
#include <stdio.h> // printf #include <stdio.h> // printf
#include <string.h> // strerror #include <stdlib.h> // free
#include <errno.h> // errno
#include <sys/stat.h> // stat
#define ZSTD_STATIC_LINKING_ONLY // ZSTD_findDecompressedSize
#include <zstd.h> // presumes zstd library is installed #include <zstd.h> // presumes zstd library is installed
#include "utils.h" #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
static void decompress(const char* fname) static void decompress(const char* fname)
{ {
size_t cSize; size_t cSize;
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize); void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize); /* Read the content size from the frame header. For simplicity we require
if (rSize==ZSTD_CONTENTSIZE_ERROR) { * that it is always present. By default, zstd will write the content size
fprintf(stderr, "%s : it was not compressed by zstd.\n", fname); * in the header when it is known. If you can't guarantee that the frame
exit(5); * content size is always written into the header, either use streaming
} else if (rSize==ZSTD_CONTENTSIZE_UNKNOWN) { * decompression, or ZSTD_decompressBound().
fprintf(stderr, */
"%s : original size unknown. Use streaming decompression instead.\n", fname); unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
exit(6); CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, "%s: not compressed by zstd!", fname);
} CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, "%s: original size unknown!", fname);
void* const rBuff = malloc_orDie((size_t)rSize); void* const rBuff = malloc_orDie((size_t)rSize);
/* Decompress.
* If you are doing many decompressions, you may want to reuse the context
* and use ZSTD_decompressDCtx(). If you want to set advanced parameters,
* use ZSTD_DCtx_setParameter().
*/
size_t const dSize = ZSTD_decompress(rBuff, rSize, cBuff, cSize); size_t const dSize = ZSTD_decompress(rBuff, rSize, cBuff, cSize);
CHECK_ZSTD(dSize);
if (dSize != rSize) { /* When zstd knows the content size, it will error if it doesn't match. */
fprintf(stderr, "error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize)); CHECK(dSize == rSize, "Impossible because zstd will check this condition!");
exit(7);
}
/* success */ /* success */
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize); printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
+57 -32
View File
@@ -9,54 +9,79 @@
*/ */
#include <stdlib.h> // malloc, free, exit #include <stdio.h> // printf
#include <stdio.h> // fprintf, perror, feof, fopen, etc. #include <stdlib.h> // free
#include <string.h> // strlen, memset, strcat #include <string.h> // memset, strcat, strlen
#include <zstd.h> // presumes zstd library is installed #include <zstd.h> // presumes zstd library is installed
#include "utils.h" #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
static void compressFile_orDie(const char* fname, const char* outName, int cLevel) static void compressFile_orDie(const char* fname, const char* outName, int cLevel)
{ {
/* Open the input and output files. */
FILE* const fin = fopen_orDie(fname, "rb"); FILE* const fin = fopen_orDie(fname, "rb");
FILE* const fout = fopen_orDie(outName, "wb"); FILE* const fout = fopen_orDie(outName, "wb");
size_t const buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */ /* Create the input and output buffers.
* They may be any size, but we recommend using these functions to size them.
* Performance will only suffer significantly for very tiny buffers.
*/
size_t const buffInSize = ZSTD_CStreamInSize();
void* const buffIn = malloc_orDie(buffInSize); void* const buffIn = malloc_orDie(buffInSize);
size_t const buffOutSize = ZSTD_CStreamOutSize(); /* can always flush a full block */ size_t const buffOutSize = ZSTD_CStreamOutSize();
void* const buffOut = malloc_orDie(buffOutSize); void* const buffOut = malloc_orDie(buffOutSize);
ZSTD_CStream* const cstream = ZSTD_createCStream(); /* Create the context. */
if (cstream==NULL) { fprintf(stderr, "ZSTD_createCStream() error \n"); exit(10); } ZSTD_CCtx* const cctx = ZSTD_createCCtx();
size_t const initResult = ZSTD_initCStream(cstream, cLevel); CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
if (ZSTD_isError(initResult)) {
fprintf(stderr, "ZSTD_initCStream() error : %s \n",
ZSTD_getErrorName(initResult));
exit(11);
}
size_t read, toRead = buffInSize; /* Set any parameters you want.
while( (read = fread_orDie(buffIn, toRead, fin)) ) { * Here we set the compression level, and enable the checksum.
*/
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel) );
CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) );
/* This loop read from the input file, compresses that entire chunk,
* and writes all output produced to the output file.
*/
size_t const toRead = buffInSize;
size_t read;
while ((read = fread_orDie(buffIn, toRead, fin))) {
/* Select the flush mode.
* If the read may not be finished (read == toRead) we use
* ZSTD_e_continue. If this is the last chunk, we use ZSTD_e_end.
* Zstd optimizes the case where the first flush mode is ZSTD_e_end,
* since it knows it is compressing the entire source in one pass.
*/
int const lastChunk = (read < toRead);
ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;
/* Set the input buffer to what we just read.
* We compress until the input buffer is empty, each time flushing the
* output.
*/
ZSTD_inBuffer input = { buffIn, read, 0 }; ZSTD_inBuffer input = { buffIn, read, 0 };
while (input.pos < input.size) { int finished;
do {
/* Compress into the output buffer and write all of the output to
* the file so we can reuse the buffer next iteration.
*/
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 }; ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
toRead = ZSTD_compressStream(cstream, &output , &input); /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */ size_t const remaining = ZSTD_compressStream2(cctx, &output , &input, mode);
if (ZSTD_isError(toRead)) { CHECK_ZSTD(remaining);
fprintf(stderr, "ZSTD_compressStream() error : %s \n",
ZSTD_getErrorName(toRead));
exit(12);
}
if (toRead > buffInSize) toRead = buffInSize; /* Safely handle case when `buffInSize` is manually changed to a value < ZSTD_CStreamInSize()*/
fwrite_orDie(buffOut, output.pos, fout); fwrite_orDie(buffOut, output.pos, fout);
} /* If we're on the last chunk we're finished when zstd returns 0,
* which means its consumed all the input AND finished the frame.
* Otherwise, we're finished when we've consumed all the input.
*/
finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
} while (!finished);
CHECK(input.pos == input.size,
"Impossible: zstd only returns 0 when the input is completely consumed!");
} }
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 }; ZSTD_freeCCtx(cctx);
size_t const remainingToFlush = ZSTD_endStream(cstream, &output); /* close frame */
if (remainingToFlush) { fprintf(stderr, "not fully flushed"); exit(13); }
fwrite_orDie(buffOut, output.pos, fout);
ZSTD_freeCStream(cstream);
fclose_orDie(fout); fclose_orDie(fout);
fclose_orDie(fin); free(buffIn); fclose_orDie(fin);
free(buffIn);
free(buffOut); free(buffOut);
} }
+28 -16
View File
@@ -9,12 +9,10 @@
*/ */
#include <stdlib.h> // malloc, exit #include <stdio.h> // fprintf
#include <stdio.h> // fprintf, perror, feof #include <stdlib.h> // free
#include <string.h> // strerror
#include <errno.h> // errno
#include <zstd.h> // presumes zstd library is installed #include <zstd.h> // presumes zstd library is installed
#include "utils.h" #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
static void decompressFile_orDie(const char* fname) static void decompressFile_orDie(const char* fname)
{ {
@@ -25,26 +23,40 @@ static void decompressFile_orDie(const char* fname)
size_t const buffOutSize = ZSTD_DStreamOutSize(); /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */ size_t const buffOutSize = ZSTD_DStreamOutSize(); /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */
void* const buffOut = malloc_orDie(buffOutSize); void* const buffOut = malloc_orDie(buffOutSize);
ZSTD_DStream* const dstream = ZSTD_createDStream(); ZSTD_DCtx* const dctx = ZSTD_createDCtx();
if (dstream==NULL) { fprintf(stderr, "ZSTD_createDStream() error \n"); exit(10); } CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
/* In more complex scenarios, a file may consist of multiple appended frames (ex : pzstd). /* This loop assumes that the input file is one or more concatenated zstd
* The following example decompresses only the first frame. * streams. This example won't work if there is trailing non-zstd data at
* It is compatible with other provided streaming examples */ * the end, but streaming decompression in general handles this case.
size_t const initResult = ZSTD_initDStream(dstream); * ZSTD_decompressStream() returns 0 exactly when the frame is completed,
if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initDStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); } * and doesn't consume input after the frame.
size_t read, toRead = initResult; */
size_t const toRead = buffInSize;
size_t read;
while ( (read = fread_orDie(buffIn, toRead, fin)) ) { while ( (read = fread_orDie(buffIn, toRead, fin)) ) {
ZSTD_inBuffer input = { buffIn, read, 0 }; ZSTD_inBuffer input = { buffIn, read, 0 };
/* Given a valid frame, zstd won't consume the last byte of the frame
* until it has flushed all of the decompressed data of the frame.
* Therefore, instead of checking if the return code is 0, we can
* decompress just check if input.pos < input.size.
*/
while (input.pos < input.size) { while (input.pos < input.size) {
ZSTD_outBuffer output = { buffOut, buffOutSize, 0 }; ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
toRead = ZSTD_decompressStream(dstream, &output , &input); /* toRead : size of next compressed block */ /* The return code is zero if the frame is complete, but there may
if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_decompressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); } * be multiple frames concatenated together. Zstd will automatically
* reset the context when a frame is complete. Still, calling
* ZSTD_DCtx_reset() can be useful to reset the context to a clean
* state, for instance if the last decompression call returned an
* error.
*/
size_t const ret = ZSTD_decompressStream(dctx, &output , &input);
CHECK_ZSTD(ret);
fwrite_orDie(buffOut, output.pos, fout); fwrite_orDie(buffOut, output.pos, fout);
} }
} }
ZSTD_freeDStream(dstream); ZSTD_freeDCtx(dctx);
fclose_orDie(fin); fclose_orDie(fin);
fclose_orDie(fout); fclose_orDie(fout);
free(buffIn); free(buffIn);
+58 -72
View File
@@ -16,9 +16,10 @@
/*=== Dependencies ===*/ /*=== Dependencies ===*/
#include <stdio.h> /* printf */ #include <stdio.h> // printf
#define ZSTD_STATIC_LINKING_ONLY #define ZSTD_STATIC_LINKING_ONLY
#include "zstd.h" #include <zstd.h> // presumes zstd library is installed
#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
/*=== functions ===*/ /*=== functions ===*/
@@ -61,90 +62,75 @@ int main(int argc, char const *argv[]) {
char const dataToCompress[INPUT_SIZE] = "abcde"; char const dataToCompress[INPUT_SIZE] = "abcde";
char compressedData[COMPRESSED_SIZE]; char compressedData[COMPRESSED_SIZE];
char decompressedData[INPUT_SIZE]; char decompressedData[INPUT_SIZE];
ZSTD_CStream* const cstream = ZSTD_createCStream(); /* the ZSTD_CCtx_params structure is a way to save parameters and use
if (cstream==NULL) { * them across multiple contexts. We use them here so we can call the
printf("Level %i : ZSTD_CStream Memory allocation failure \n", compressionLevel); * function ZSTD_estimateCStreamSize_usingCCtxParams().
return 1; */
} ZSTD_CCtx_params* const cctxParams = ZSTD_createCCtxParams();
CHECK(cctxParams != NULL, "ZSTD_createCCtxParams() failed!");
/* forces compressor to use maximum memory size for given compression level, /* Set the compression level. */
* by not providing any information on input size */ CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_compressionLevel, compressionLevel) );
ZSTD_parameters params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); /* Set the window log.
if (wLog) { /* special mode : specific wLog */ * The value 0 means use the default window log, which is equivalent to
printf("Using custom compression parameter : level 1 + wLog=%u \n", wLog); * not setting it.
params = ZSTD_getParams(1 /*compressionLevel*/, */
1 << wLog /*estimatedSrcSize*/, CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, wLog) );
0 /*no dictionary*/);
size_t const error = ZSTD_initCStream_advanced(cstream, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN);
if (ZSTD_isError(error)) {
printf("ZSTD_initCStream_advanced error : %s \n", ZSTD_getErrorName(error));
return 1;
}
} else {
size_t const error = ZSTD_initCStream(cstream, compressionLevel);
if (ZSTD_isError(error)) {
printf("ZSTD_initCStream error : %s \n", ZSTD_getErrorName(error));
return 1;
}
}
/* Force the compressor to allocate the maximum memory size for a given
* level by not providing the pledged source size, or calling
* ZSTD_compressStream2() with ZSTD_e_end.
*/
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
CHECK_ZSTD( ZSTD_CCtx_setParametersUsingCCtxParams(cctx, cctxParams) );
size_t compressedSize; size_t compressedSize;
{ ZSTD_inBuffer inBuff = { dataToCompress, sizeof(dataToCompress), 0 }; {
ZSTD_inBuffer inBuff = { dataToCompress, sizeof(dataToCompress), 0 };
ZSTD_outBuffer outBuff = { compressedData, sizeof(compressedData), 0 }; ZSTD_outBuffer outBuff = { compressedData, sizeof(compressedData), 0 };
size_t const cError = ZSTD_compressStream(cstream, &outBuff, &inBuff); CHECK_ZSTD( ZSTD_compressStream(cctx, &outBuff, &inBuff) );
if (ZSTD_isError(cError)) { size_t const remaining = ZSTD_endStream(cctx, &outBuff);
printf("ZSTD_compressStream error : %s \n", ZSTD_getErrorName(cError)); CHECK_ZSTD(remaining);
return 1; CHECK(remaining == 0, "Frame not flushed!");
}
size_t const fError = ZSTD_endStream(cstream, &outBuff);
if (ZSTD_isError(fError)) {
printf("ZSTD_endStream error : %s \n", ZSTD_getErrorName(fError));
return 1;
}
compressedSize = outBuff.pos; compressedSize = outBuff.pos;
} }
ZSTD_DStream* dstream = ZSTD_createDStream(); ZSTD_DCtx* const dctx = ZSTD_createDCtx();
if (dstream==NULL) { CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
printf("Level %i : ZSTD_DStream Memory allocation failure \n", compressionLevel); /* Set the maximum allowed window log.
return 1; * The value 0 means use the default window log, which is equivalent to
} * not setting it.
{ size_t const error = ZSTD_initDStream(dstream); */
if (ZSTD_isError(error)) { CHECK_ZSTD( ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, wLog) );
printf("ZSTD_initDStream error : %s \n", ZSTD_getErrorName(error)); /* forces decompressor to use maximum memory size, since the
return 1; * decompressed size is not stored in the frame header.
} */
}
/* forces decompressor to use maximum memory size, as decompressed size is not known */
{ ZSTD_inBuffer inBuff = { compressedData, compressedSize, 0 }; { ZSTD_inBuffer inBuff = { compressedData, compressedSize, 0 };
ZSTD_outBuffer outBuff = { decompressedData, sizeof(decompressedData), 0 }; ZSTD_outBuffer outBuff = { decompressedData, sizeof(decompressedData), 0 };
size_t const dResult = ZSTD_decompressStream(dstream, &outBuff, &inBuff); size_t const remaining = ZSTD_decompressStream(dctx, &outBuff, &inBuff);
if (ZSTD_isError(dResult)) { CHECK_ZSTD(remaining);
printf("ZSTD_decompressStream error : %s \n", ZSTD_getErrorName(dResult)); CHECK(remaining == 0, "Frame not complete!");
return 1; CHECK(outBuff.pos == sizeof(dataToCompress), "Bad decompression!");
}
if (dResult != 0) {
printf("ZSTD_decompressStream error : unfinished decompression \n");
return 1;
}
if (outBuff.pos != sizeof(dataToCompress)) {
printf("ZSTD_decompressStream error : incorrect decompression \n");
return 1;
}
} }
size_t const cstreamSize = ZSTD_sizeof_CStream(cstream); size_t const cstreamSize = ZSTD_sizeof_CStream(cctx);
size_t const cstreamEstimatedSize = wLog ? size_t const cstreamEstimatedSize = ZSTD_estimateCStreamSize_usingCCtxParams(cctxParams);
ZSTD_estimateCStreamSize_usingCParams(params.cParams) : size_t const dstreamSize = ZSTD_sizeof_DStream(dctx);
ZSTD_estimateCStreamSize(compressionLevel); size_t const dstreamEstimatedSize = ZSTD_estimateDStreamSize_fromFrame(compressedData, compressedSize);
size_t const dstreamSize = ZSTD_sizeof_DStream(dstream);
printf("Level %2i : Compression Mem = %5u KB (estimated : %5u KB) ; Decompression Mem = %4u KB \n", CHECK(cstreamSize <= cstreamEstimatedSize, "Compression mem (%u) > estimated (%u)",
(unsigned)cstreamSize, (unsigned)cstreamEstimatedSize);
CHECK(dstreamSize <= dstreamEstimatedSize, "Decompression mem (%u) > estimated (%u)",
(unsigned)dstreamSize, (unsigned)dstreamEstimatedSize);
printf("Level %2i : Compression Mem = %5u KB (estimated : %5u KB) ; Decompression Mem = %4u KB (estimated : %5u KB)\n",
compressionLevel, compressionLevel,
(unsigned)(cstreamSize>>10), (unsigned)(cstreamEstimatedSize>>10), (unsigned)(dstreamSize>>10)); (unsigned)(cstreamSize>>10), (unsigned)(cstreamEstimatedSize>>10),
(unsigned)(dstreamSize>>10), (unsigned)(dstreamEstimatedSize>>10));
ZSTD_freeDStream(dstream); ZSTD_freeDCtx(dctx);
ZSTD_freeCStream(cstream); ZSTD_freeCCtx(cctx);
ZSTD_freeCCtxParams(cctxParams);
if (wLog) break; /* single test */ if (wLog) break; /* single test */
} }
return 0; return 0;
+7 -3
View File
@@ -25,7 +25,7 @@ endif
CFLAGS ?= -O3 CFLAGS ?= -O3
DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \ -Wstrict-prototypes -Wundef -Wpointer-arith \
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
-Wredundant-decls -Wmissing-prototypes -Wc++-compat -Wredundant-decls -Wmissing-prototypes -Wc++-compat
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
@@ -56,6 +56,7 @@ ZSTD_FORCE_DECOMPRESS_SHORT ?= 0
ZSTD_FORCE_DECOMPRESS_LONG ?= 0 ZSTD_FORCE_DECOMPRESS_LONG ?= 0
ZSTD_NO_INLINE ?= 0 ZSTD_NO_INLINE ?= 0
ZSTD_STRIP_ERROR_STRINGS ?= 0 ZSTD_STRIP_ERROR_STRINGS ?= 0
ZSTD_LEGACY_MULTITHREADED_API ?= 0
ifeq ($(ZSTD_LIB_COMPRESSION), 0) ifeq ($(ZSTD_LIB_COMPRESSION), 0)
ZSTD_LIB_DICTBUILDER = 0 ZSTD_LIB_DICTBUILDER = 0
@@ -107,6 +108,10 @@ ifneq ($(ZSTD_STRIP_ERROR_STRINGS), 0)
CFLAGS += -DZSTD_STRIP_ERROR_STRINGS CFLAGS += -DZSTD_STRIP_ERROR_STRINGS
endif endif
ifneq ($(ZSTD_LEGACY_MULTITHREADED_API), 0)
CFLAGS += -DZSTD_LEGACY_MULTITHREADED_API
endif
ifneq ($(ZSTD_LEGACY_SUPPORT), 0) ifneq ($(ZSTD_LEGACY_SUPPORT), 0)
ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0) ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0)
ZSTD_FILES += $(shell ls legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]') ZSTD_FILES += $(shell ls legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]')
@@ -151,8 +156,7 @@ ifneq (,$(filter Windows%,$(OS)))
LIBZSTD = dll\libzstd.dll LIBZSTD = dll\libzstd.dll
$(LIBZSTD): $(ZSTD_FILES) $(LIBZSTD): $(ZSTD_FILES)
@echo compiling dynamic library $(LIBVER) @echo compiling dynamic library $(LIBVER)
@$(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -shared $^ -o $@ $(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -Wl,--out-implib,dll\libzstd.lib -shared $^ -o $@
dlltool -D $@ -d dll\libzstd.def -l dll\libzstd.lib
else else
+4 -2
View File
@@ -31,8 +31,6 @@ note that it's necessary to request the `-pthread` flag during link stage.
Multithreading capabilities are exposed Multithreading capabilities are exposed
via the [advanced API defined in `lib/zstd.h`](https://github.com/facebook/zstd/blob/v1.3.8/lib/zstd.h#L592). via the [advanced API defined in `lib/zstd.h`](https://github.com/facebook/zstd/blob/v1.3.8/lib/zstd.h#L592).
This API is still labelled experimental,
but is expected to become "stable" in the near future.
#### API #### API
@@ -110,6 +108,10 @@ The file structure is designed to make this selection manually achievable for an
which removes the error messages that are otherwise returned by which removes the error messages that are otherwise returned by
`ZSTD_getErrorName`. `ZSTD_getErrorName`.
- While invoking `make libzstd`, the build macro `ZSTD_LEGACY_MULTITHREADED_API=1`
will expose the deprecated `ZSTDMT` API exposed by `zstdmt_compress.h` in
the shared library, which is now hidden by default.
#### Windows : using MinGW+MSYS to create DLL #### Windows : using MinGW+MSYS to create DLL
+1 -1
View File
@@ -40,7 +40,7 @@
/** /**
* FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
* parameters. They must be inlined for the compiler to elimininate the constant * parameters. They must be inlined for the compiler to eliminate the constant
* branches. * branches.
*/ */
#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
+1 -1
View File
@@ -358,7 +358,7 @@ size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size
typedef enum { typedef enum {
FSE_repeat_none, /**< Cannot use the previous table */ FSE_repeat_none, /**< Cannot use the previous table */
FSE_repeat_check, /**< Can use the previous table but it must be checked */ FSE_repeat_check, /**< Can use the previous table but it must be checked */
FSE_repeat_valid /**< Can use the previous table and it is asumed to be valid */ FSE_repeat_valid /**< Can use the previous table and it is assumed to be valid */
} FSE_repeat; } FSE_repeat;
/* ***************************************** /* *****************************************
+2 -2
View File
@@ -14,8 +14,8 @@
* This file will hold wrapper for systems, which do not support pthreads * This file will hold wrapper for systems, which do not support pthreads
*/ */
/* create fake symbol to avoid empty trnaslation unit warning */ /* create fake symbol to avoid empty translation unit warning */
int g_ZSTD_threading_useles_symbol; int g_ZSTD_threading_useless_symbol;
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32) #if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
+2 -2
View File
@@ -66,10 +66,10 @@
/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */ /* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
/*!XXH_FORCE_NATIVE_FORMAT : /*!XXH_FORCE_NATIVE_FORMAT :
* By default, xxHash library provides endian-independant Hash values, based on little-endian convention. * By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
* Results are therefore identical for little-endian and big-endian CPU. * Results are therefore identical for little-endian and big-endian CPU.
* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
* Should endian-independance be of no importance for your application, you may set the #define below to 1, * Should endian-independence be of no importance for your application, you may set the #define below to 1,
* to improve speed for Big-endian CPU. * to improve speed for Big-endian CPU.
* This option has no impact on Little_Endian CPU. * This option has no impact on Little_Endian CPU.
*/ */
+55 -2
View File
@@ -53,8 +53,50 @@ extern "C" {
#undef MAX #undef MAX
#define MIN(a,b) ((a)<(b) ? (a) : (b)) #define MIN(a,b) ((a)<(b) ? (a) : (b))
#define MAX(a,b) ((a)>(b) ? (a) : (b)) #define MAX(a,b) ((a)>(b) ? (a) : (b))
#define CHECK_F(f) { size_t const errcod = f; if (ERR_isError(errcod)) return errcod; } /* check and Forward error code */
#define CHECK_E(f, e) { size_t const errcod = f; if (ERR_isError(errcod)) return ERROR(e); } /* check and send Error code */ /**
* Return the specified error if the condition evaluates to true.
*
* In debug modes, prints additional information. In order to do that
* (particularly, printing the conditional that failed), this can't just wrap
* RETURN_ERROR().
*/
#define RETURN_ERROR_IF(cond, err, ...) \
if (cond) { \
RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \
RAWLOG(3, ": " __VA_ARGS__); \
RAWLOG(3, "\n"); \
return ERROR(err); \
}
/**
* Unconditionally return the specified error.
*
* In debug modes, prints additional information.
*/
#define RETURN_ERROR(err, ...) \
do { \
RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \
RAWLOG(3, ": " __VA_ARGS__); \
RAWLOG(3, "\n"); \
return ERROR(err); \
} while(0);
/**
* If the provided expression evaluates to an error code, returns that error code.
*
* In debug modes, prints additional information.
*/
#define FORWARD_IF_ERROR(err, ...) \
do { \
size_t const err_code = (err); \
if (ERR_isError(err_code)) { \
RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \
RAWLOG(3, ": " __VA_ARGS__); \
RAWLOG(3, "\n"); \
return err_code; \
} \
} while(0);
/*-************************************* /*-*************************************
@@ -200,6 +242,17 @@ typedef struct {
U32 longLengthPos; U32 longLengthPos;
} seqStore_t; } seqStore_t;
/**
* Contains the compressed frame size and an upper-bound for the decompressed frame size.
* Note: before using `compressedSize`, check for errors using ZSTD_isError().
* similarly, before using `decompressedBound`, check for errors using:
* `decompressedBound != ZSTD_CONTENTSIZE_ERROR`
*/
typedef struct {
size_t compressedSize;
unsigned long long decompressedBound;
} ZSTD_frameSizeInfo; /* decompress & legacy */
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
+2 -2
View File
@@ -129,9 +129,9 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
{ U32 position = 0; { U32 position = 0;
U32 symbol; U32 symbol;
for (symbol=0; symbol<=maxSymbolValue; symbol++) { for (symbol=0; symbol<=maxSymbolValue; symbol++) {
int nbOccurences; int nbOccurrences;
int const freq = normalizedCounter[symbol]; int const freq = normalizedCounter[symbol];
for (nbOccurences=0; nbOccurences<freq; nbOccurences++) { for (nbOccurrences=0; nbOccurrences<freq; nbOccurrences++) {
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol; tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
position = (position + step) & tableMask; position = (position + step) & tableMask;
while (position > highThreshold) while (position > highThreshold)
+423 -296
View File
@@ -103,12 +103,31 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
return cctx; return cctx;
} }
/**
* Clears and frees all of the dictionaries in the CCtx.
*/
static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
{
ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem);
ZSTD_freeCDict(cctx->localDict.cdict);
memset(&cctx->localDict, 0, sizeof(cctx->localDict));
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
cctx->cdict = NULL;
}
static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)
{
size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;
size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);
return bufferSize + cdictSize;
}
static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx) static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
{ {
assert(cctx != NULL); assert(cctx != NULL);
assert(cctx->staticSize == 0); assert(cctx->staticSize == 0);
ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL; ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL; ZSTD_clearAllDicts(cctx);
#ifdef ZSTD_MULTITHREAD #ifdef ZSTD_MULTITHREAD
ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL; ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
#endif #endif
@@ -117,7 +136,8 @@ static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
{ {
if (cctx==NULL) return 0; /* support free on NULL */ if (cctx==NULL) return 0; /* support free on NULL */
if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */ RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
"not compatible with static CCtx");
ZSTD_freeCCtxContent(cctx); ZSTD_freeCCtxContent(cctx);
ZSTD_free(cctx, cctx->customMem); ZSTD_free(cctx, cctx->customMem);
return 0; return 0;
@@ -139,7 +159,7 @@ size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
{ {
if (cctx==NULL) return 0; /* support sizeof on NULL */ if (cctx==NULL) return 0; /* support sizeof on NULL */
return sizeof(*cctx) + cctx->workSpaceSize return sizeof(*cctx) + cctx->workSpaceSize
+ ZSTD_sizeof_CDict(cctx->cdictLocal) + ZSTD_sizeof_localDict(cctx->localDict)
+ ZSTD_sizeof_mtctx(cctx); + ZSTD_sizeof_mtctx(cctx);
} }
@@ -195,7 +215,7 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
} }
size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) { size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
if (!cctxParams) { return ERROR(GENERIC); } RETURN_ERROR_IF(!cctxParams, GENERIC);
memset(cctxParams, 0, sizeof(*cctxParams)); memset(cctxParams, 0, sizeof(*cctxParams));
cctxParams->compressionLevel = compressionLevel; cctxParams->compressionLevel = compressionLevel;
cctxParams->fParams.contentSizeFlag = 1; cctxParams->fParams.contentSizeFlag = 1;
@@ -204,8 +224,8 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel)
size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
{ {
if (!cctxParams) { return ERROR(GENERIC); } RETURN_ERROR_IF(!cctxParams, GENERIC);
CHECK_F( ZSTD_checkCParams(params.cParams) ); FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
memset(cctxParams, 0, sizeof(*cctxParams)); memset(cctxParams, 0, sizeof(*cctxParams));
cctxParams->cParams = params.cParams; cctxParams->cParams = params.cParams;
cctxParams->fParams = params.fParams; cctxParams->fParams = params.fParams;
@@ -359,6 +379,12 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
bounds.upperBound = ZSTD_dictForceCopy; /* note : how to ensure at compile time that this is the highest value enum ? */ bounds.upperBound = ZSTD_dictForceCopy; /* note : how to ensure at compile time that this is the highest value enum ? */
return bounds; return bounds;
case ZSTD_c_literalCompressionMode:
ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed);
bounds.lowerBound = ZSTD_lcm_auto;
bounds.upperBound = ZSTD_lcm_uncompressed;
return bounds;
default: default:
{ ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 }; { ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 };
return boundError; return boundError;
@@ -378,10 +404,22 @@ static int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
return 1; return 1;
} }
#define BOUNDCHECK(cParam, val) { \ /* ZSTD_cParam_clampBounds:
if (!ZSTD_cParam_withinBounds(cParam,val)) { \ * Clamps the value into the bounded range.
return ERROR(parameter_outOfBound); \ */
} } static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
{
ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
if (ZSTD_isError(bounds.error)) return bounds.error;
if (*value < bounds.lowerBound) *value = bounds.lowerBound;
if (*value > bounds.upperBound) *value = bounds.upperBound;
return 0;
}
#define BOUNDCHECK(cParam, val) { \
RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
parameter_outOfBound); \
}
static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
@@ -413,6 +451,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
case ZSTD_c_ldmBucketSizeLog: case ZSTD_c_ldmBucketSizeLog:
case ZSTD_c_ldmHashRateLog: case ZSTD_c_ldmHashRateLog:
case ZSTD_c_forceAttachDict: case ZSTD_c_forceAttachDict:
case ZSTD_c_literalCompressionMode:
default: default:
return 0; return 0;
} }
@@ -425,18 +464,17 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
if (ZSTD_isUpdateAuthorized(param)) { if (ZSTD_isUpdateAuthorized(param)) {
cctx->cParamsChanged = 1; cctx->cParamsChanged = 1;
} else { } else {
return ERROR(stage_wrong); RETURN_ERROR(stage_wrong);
} } } }
switch(param) switch(param)
{ {
case ZSTD_c_format : case ZSTD_c_nbWorkers:
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,
"MT not compatible with static alloc");
break;
case ZSTD_c_compressionLevel: case ZSTD_c_compressionLevel:
if (cctx->cdict) return ERROR(stage_wrong);
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
case ZSTD_c_windowLog: case ZSTD_c_windowLog:
case ZSTD_c_hashLog: case ZSTD_c_hashLog:
case ZSTD_c_chainLog: case ZSTD_c_chainLog:
@@ -444,49 +482,32 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
case ZSTD_c_minMatch: case ZSTD_c_minMatch:
case ZSTD_c_targetLength: case ZSTD_c_targetLength:
case ZSTD_c_strategy: case ZSTD_c_strategy:
if (cctx->cdict) return ERROR(stage_wrong); case ZSTD_c_ldmHashRateLog:
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); case ZSTD_c_format:
case ZSTD_c_contentSizeFlag: case ZSTD_c_contentSizeFlag:
case ZSTD_c_checksumFlag: case ZSTD_c_checksumFlag:
case ZSTD_c_dictIDFlag: case ZSTD_c_dictIDFlag:
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); case ZSTD_c_forceMaxWindow:
case ZSTD_c_forceMaxWindow : /* Force back-references to remain < windowSize,
* even when referencing into Dictionary content.
* default : 0 when using a CDict, 1 when using a Prefix */
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
case ZSTD_c_forceAttachDict: case ZSTD_c_forceAttachDict:
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); case ZSTD_c_literalCompressionMode:
case ZSTD_c_nbWorkers:
if ((value!=0) && cctx->staticSize) {
return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
}
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
case ZSTD_c_jobSize: case ZSTD_c_jobSize:
case ZSTD_c_overlapLog: case ZSTD_c_overlapLog:
case ZSTD_c_rsyncable: case ZSTD_c_rsyncable:
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
case ZSTD_c_enableLongDistanceMatching: case ZSTD_c_enableLongDistanceMatching:
case ZSTD_c_ldmHashLog: case ZSTD_c_ldmHashLog:
case ZSTD_c_ldmMinMatch: case ZSTD_c_ldmMinMatch:
case ZSTD_c_ldmBucketSizeLog: case ZSTD_c_ldmBucketSizeLog:
case ZSTD_c_ldmHashRateLog: break;
if (cctx->cdict) return ERROR(stage_wrong);
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
default: return ERROR(parameter_unsupported); default: RETURN_ERROR(parameter_unsupported);
} }
return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
} }
size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams, size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
ZSTD_cParameter param, int value) ZSTD_cParameter param, int value)
{ {
DEBUGLOG(4, "ZSTD_CCtxParam_setParameter (%i, %i)", (int)param, value); DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value);
switch(param) switch(param)
{ {
case ZSTD_c_format : case ZSTD_c_format :
@@ -495,11 +516,9 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
return (size_t)CCtxParams->format; return (size_t)CCtxParams->format;
case ZSTD_c_compressionLevel : { case ZSTD_c_compressionLevel : {
int cLevel = value; FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel(); if (value) { /* 0 : does not change current level */
if (cLevel < ZSTD_minCLevel()) cLevel = ZSTD_minCLevel(); CCtxParams->compressionLevel = value;
if (cLevel) { /* 0 : does not change current level */
CCtxParams->compressionLevel = cLevel;
} }
if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel; if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
return 0; /* return type (size_t) cannot represent negative values */ return 0; /* return type (size_t) cannot represent negative values */
@@ -573,33 +592,55 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
return CCtxParams->attachDictPref; return CCtxParams->attachDictPref;
} }
case ZSTD_c_literalCompressionMode : {
const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value;
BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
CCtxParams->literalCompressionMode = lcm;
return CCtxParams->literalCompressionMode;
}
case ZSTD_c_nbWorkers : case ZSTD_c_nbWorkers :
#ifndef ZSTD_MULTITHREAD #ifndef ZSTD_MULTITHREAD
if (value!=0) return ERROR(parameter_unsupported); RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
return 0; return 0;
#else #else
return ZSTDMT_CCtxParam_setNbWorkers(CCtxParams, value); FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
CCtxParams->nbWorkers = value;
return CCtxParams->nbWorkers;
#endif #endif
case ZSTD_c_jobSize : case ZSTD_c_jobSize :
#ifndef ZSTD_MULTITHREAD #ifndef ZSTD_MULTITHREAD
return ERROR(parameter_unsupported); RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
return 0;
#else #else
return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_jobSize, value); /* Adjust to the minimum non-default value. */
if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)
value = ZSTDMT_JOBSIZE_MIN;
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
assert(value >= 0);
CCtxParams->jobSize = value;
return CCtxParams->jobSize;
#endif #endif
case ZSTD_c_overlapLog : case ZSTD_c_overlapLog :
#ifndef ZSTD_MULTITHREAD #ifndef ZSTD_MULTITHREAD
return ERROR(parameter_unsupported); RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
return 0;
#else #else
return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_overlapLog, value); FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
CCtxParams->overlapLog = value;
return CCtxParams->overlapLog;
#endif #endif
case ZSTD_c_rsyncable : case ZSTD_c_rsyncable :
#ifndef ZSTD_MULTITHREAD #ifndef ZSTD_MULTITHREAD
return ERROR(parameter_unsupported); RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
return 0;
#else #else
return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_rsyncable, value); FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
CCtxParams->rsyncable = value;
return CCtxParams->rsyncable;
#endif #endif
case ZSTD_c_enableLongDistanceMatching : case ZSTD_c_enableLongDistanceMatching :
@@ -625,21 +666,21 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
return CCtxParams->ldmParams.bucketSizeLog; return CCtxParams->ldmParams.bucketSizeLog;
case ZSTD_c_ldmHashRateLog : case ZSTD_c_ldmHashRateLog :
if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN) RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
return ERROR(parameter_outOfBound); parameter_outOfBound);
CCtxParams->ldmParams.hashRateLog = value; CCtxParams->ldmParams.hashRateLog = value;
return CCtxParams->ldmParams.hashRateLog; return CCtxParams->ldmParams.hashRateLog;
default: return ERROR(parameter_unsupported); default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
} }
} }
size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value) size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value)
{ {
return ZSTD_CCtxParam_getParameter(&cctx->requestedParams, param, value); return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
} }
size_t ZSTD_CCtxParam_getParameter( size_t ZSTD_CCtxParams_getParameter(
ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value) ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value)
{ {
switch(param) switch(param)
@@ -686,6 +727,9 @@ size_t ZSTD_CCtxParam_getParameter(
case ZSTD_c_forceAttachDict : case ZSTD_c_forceAttachDict :
*value = CCtxParams->attachDictPref; *value = CCtxParams->attachDictPref;
break; break;
case ZSTD_c_literalCompressionMode :
*value = CCtxParams->literalCompressionMode;
break;
case ZSTD_c_nbWorkers : case ZSTD_c_nbWorkers :
#ifndef ZSTD_MULTITHREAD #ifndef ZSTD_MULTITHREAD
assert(CCtxParams->nbWorkers == 0); assert(CCtxParams->nbWorkers == 0);
@@ -694,7 +738,7 @@ size_t ZSTD_CCtxParam_getParameter(
break; break;
case ZSTD_c_jobSize : case ZSTD_c_jobSize :
#ifndef ZSTD_MULTITHREAD #ifndef ZSTD_MULTITHREAD
return ERROR(parameter_unsupported); RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
#else #else
assert(CCtxParams->jobSize <= INT_MAX); assert(CCtxParams->jobSize <= INT_MAX);
*value = (int)CCtxParams->jobSize; *value = (int)CCtxParams->jobSize;
@@ -702,14 +746,14 @@ size_t ZSTD_CCtxParam_getParameter(
#endif #endif
case ZSTD_c_overlapLog : case ZSTD_c_overlapLog :
#ifndef ZSTD_MULTITHREAD #ifndef ZSTD_MULTITHREAD
return ERROR(parameter_unsupported); RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
#else #else
*value = CCtxParams->overlapLog; *value = CCtxParams->overlapLog;
break; break;
#endif #endif
case ZSTD_c_rsyncable : case ZSTD_c_rsyncable :
#ifndef ZSTD_MULTITHREAD #ifndef ZSTD_MULTITHREAD
return ERROR(parameter_unsupported); RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
#else #else
*value = CCtxParams->rsyncable; *value = CCtxParams->rsyncable;
break; break;
@@ -729,7 +773,7 @@ size_t ZSTD_CCtxParam_getParameter(
case ZSTD_c_ldmHashRateLog : case ZSTD_c_ldmHashRateLog :
*value = CCtxParams->ldmParams.hashRateLog; *value = CCtxParams->ldmParams.hashRateLog;
break; break;
default: return ERROR(parameter_unsupported); default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
} }
return 0; return 0;
} }
@@ -745,8 +789,8 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params) ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
{ {
DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams"); DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
if (cctx->cdict) return ERROR(stage_wrong); RETURN_ERROR_IF(cctx->cdict, stage_wrong);
cctx->requestedParams = *params; cctx->requestedParams = *params;
return 0; return 0;
@@ -755,33 +799,71 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize) ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
{ {
DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize); DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1; cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
return 0; return 0;
} }
/**
* Initializes the local dict using the requested parameters.
* NOTE: This does not use the pledged src size, because it may be used for more
* than one compression.
*/
static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
{
ZSTD_localDict* const dl = &cctx->localDict;
ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
&cctx->requestedParams, 0, dl->dictSize);
if (dl->dict == NULL) {
/* No local dictionary. */
assert(dl->dictBuffer == NULL);
assert(dl->cdict == NULL);
assert(dl->dictSize == 0);
return 0;
}
if (dl->cdict != NULL) {
assert(cctx->cdict == dl->cdict);
/* Local dictionary already initialized. */
return 0;
}
assert(dl->dictSize > 0);
assert(cctx->cdict == NULL);
assert(cctx->prefixDict.dict == NULL);
dl->cdict = ZSTD_createCDict_advanced(
dl->dict,
dl->dictSize,
ZSTD_dlm_byRef,
dl->dictContentType,
cParams,
cctx->customMem);
RETURN_ERROR_IF(!dl->cdict, memory_allocation);
cctx->cdict = dl->cdict;
return 0;
}
size_t ZSTD_CCtx_loadDictionary_advanced( size_t ZSTD_CCtx_loadDictionary_advanced(
ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType) ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
{ {
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */ RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
"no malloc for static CCtx");
DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize); DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */ ZSTD_clearAllDicts(cctx); /* in case one already exists */
if (dict==NULL || dictSize==0) { /* no dictionary mode */ if (dict == NULL || dictSize == 0) /* no dictionary mode */
cctx->cdictLocal = NULL; return 0;
cctx->cdict = NULL; if (dictLoadMethod == ZSTD_dlm_byRef) {
cctx->localDict.dict = dict;
} else { } else {
ZSTD_compressionParameters const cParams = void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem);
ZSTD_getCParamsFromCCtxParams(&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize); RETURN_ERROR_IF(!dictBuffer, memory_allocation);
cctx->cdictLocal = ZSTD_createCDict_advanced( memcpy(dictBuffer, dict, dictSize);
dict, dictSize, cctx->localDict.dictBuffer = dictBuffer;
dictLoadMethod, dictContentType, cctx->localDict.dict = dictBuffer;
cParams, cctx->customMem);
cctx->cdict = cctx->cdictLocal;
if (cctx->cdictLocal == NULL)
return ERROR(memory_allocation);
} }
cctx->localDict.dictSize = dictSize;
cctx->localDict.dictContentType = dictContentType;
return 0; return 0;
} }
@@ -801,9 +883,10 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
{ {
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
/* Free the existing local cdict (if any) to save memory. */
ZSTD_clearAllDicts(cctx);
cctx->cdict = cdict; cctx->cdict = cdict;
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* exclusive */
return 0; return 0;
} }
@@ -815,8 +898,8 @@ size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSiz
size_t ZSTD_CCtx_refPrefix_advanced( size_t ZSTD_CCtx_refPrefix_advanced(
ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType) ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
{ {
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
cctx->cdict = NULL; /* prefix discards any prior cdict */ ZSTD_clearAllDicts(cctx);
cctx->prefixDict.dict = prefix; cctx->prefixDict.dict = prefix;
cctx->prefixDict.dictSize = prefixSize; cctx->prefixDict.dictSize = prefixSize;
cctx->prefixDict.dictContentType = dictContentType; cctx->prefixDict.dictContentType = dictContentType;
@@ -834,8 +917,8 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
} }
if ( (reset == ZSTD_reset_parameters) if ( (reset == ZSTD_reset_parameters)
|| (reset == ZSTD_reset_session_and_parameters) ) { || (reset == ZSTD_reset_session_and_parameters) ) {
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
cctx->cdict = NULL; ZSTD_clearAllDicts(cctx);
return ZSTD_CCtxParams_reset(&cctx->requestedParams); return ZSTD_CCtxParams_reset(&cctx->requestedParams);
} }
return 0; return 0;
@@ -888,10 +971,11 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
} }
/** ZSTD_adjustCParams_internal() : /** ZSTD_adjustCParams_internal() :
optimize `cPar` for a given input (`srcSize` and `dictSize`). * optimize `cPar` for a specified input (`srcSize` and `dictSize`).
mostly downsizing to reduce memory consumption and initialization latency. * mostly downsize to reduce memory consumption and initialization latency.
Both `srcSize` and `dictSize` are optional (use 0 if unknown). * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
Note : cPar is assumed validated. Use ZSTD_checkCParams() to ensure this condition. */ * note : for the time being, `srcSize==0` means "unknown" too, for compatibility with older convention.
* condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
static ZSTD_compressionParameters static ZSTD_compressionParameters
ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
unsigned long long srcSize, unsigned long long srcSize,
@@ -901,7 +985,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
assert(ZSTD_checkCParams(cPar)==0); assert(ZSTD_checkCParams(cPar)==0);
if (dictSize && (srcSize+1<2) /* srcSize unknown */ ) if (dictSize && (srcSize+1<2) /* ZSTD_CONTENTSIZE_UNKNOWN and 0 mean "unknown" */ )
srcSize = minSrcSize; /* presumed small when there is a dictionary */ srcSize = minSrcSize; /* presumed small when there is a dictionary */
else if (srcSize == 0) else if (srcSize == 0)
srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */ srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
@@ -922,7 +1006,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
} }
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */ cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */
return cPar; return cPar;
} }
@@ -932,7 +1016,7 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
unsigned long long srcSize, unsigned long long srcSize,
size_t dictSize) size_t dictSize)
{ {
cPar = ZSTD_clampCParams(cPar); cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize); return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
} }
@@ -973,8 +1057,7 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{ {
/* Estimate CCtx size is supported for single-threaded compression only. */ RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
if (params->nbWorkers > 0) { return ERROR(GENERIC); }
{ ZSTD_compressionParameters const cParams = { ZSTD_compressionParameters const cParams =
ZSTD_getCParamsFromCCtxParams(params, 0, 0); ZSTD_getCParamsFromCCtxParams(params, 0, 0);
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
@@ -1022,10 +1105,12 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel)
size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{ {
if (params->nbWorkers > 0) { return ERROR(GENERIC); } RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
{ size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params); { ZSTD_compressionParameters const cParams =
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog); ZSTD_getCParamsFromCCtxParams(params, 0, 0);
size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize; size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1; size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
size_t const streamingSize = inBuffSize + outBuffSize; size_t const streamingSize = inBuffSize + outBuffSize;
@@ -1367,13 +1452,13 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB", DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB",
zc->workSpaceSize >> 10, zc->workSpaceSize >> 10,
neededSpace >> 10); neededSpace >> 10);
/* static cctx : no resize, error out */
if (zc->staticSize) return ERROR(memory_allocation); RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
zc->workSpaceSize = 0; zc->workSpaceSize = 0;
ZSTD_free(zc->workSpace, zc->customMem); ZSTD_free(zc->workSpace, zc->customMem);
zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem); zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
if (zc->workSpace == NULL) return ERROR(memory_allocation); RETURN_ERROR_IF(zc->workSpace == NULL, memory_allocation);
zc->workSpaceSize = neededSpace; zc->workSpaceSize = neededSpace;
zc->workSpaceOversizedDuration = 0; zc->workSpaceOversizedDuration = 0;
@@ -1644,7 +1729,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
ZSTD_buffered_policy_e zbuff) ZSTD_buffered_policy_e zbuff)
{ {
DEBUGLOG(5, "ZSTD_copyCCtx_internal"); DEBUGLOG(5, "ZSTD_copyCCtx_internal");
if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong); RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong);
memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
{ ZSTD_CCtx_params params = dstCCtx->requestedParams; { ZSTD_CCtx_params params = dstCCtx->requestedParams;
@@ -1777,7 +1862,8 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock) static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
{ {
U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3); U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
dstSize_tooSmall);
MEM_writeLE24(dst, cBlockHeader24); MEM_writeLE24(dst, cBlockHeader24);
memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
return ZSTD_blockHeaderSize + srcSize; return ZSTD_blockHeaderSize + srcSize;
@@ -1788,7 +1874,7 @@ static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void
BYTE* const ostart = (BYTE* const)dst; BYTE* const ostart = (BYTE* const)dst;
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall);
switch(flSize) switch(flSize)
{ {
@@ -1878,7 +1964,7 @@ static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
} }
if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */ RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, "not enough space for compression");
{ HUF_repeat repeat = prevHuf->repeatMode; { HUF_repeat repeat = prevHuf->repeatMode;
int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0; int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1; if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
@@ -1960,7 +2046,7 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
* If x == 0: Return 0 * If x == 0: Return 0
* Else: Return floor(-log2(x / 256) * 256) * Else: Return floor(-log2(x / 256) * 256)
*/ */
static unsigned const kInverseProbabiltyLog256[256] = { static unsigned const kInverseProbabilityLog256[256] = {
0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162, 0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889, 1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734, 874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
@@ -1999,7 +2085,7 @@ static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t
if (count[s] != 0 && norm == 0) if (count[s] != 0 && norm == 0)
norm = 1; norm = 1;
assert(count[s] < total); assert(count[s] < total);
cost += count[s] * kInverseProbabiltyLog256[norm]; cost += count[s] * kInverseProbabilityLog256[norm];
} }
return cost >> 8; return cost >> 8;
} }
@@ -2022,7 +2108,7 @@ static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
unsigned const norm256 = normAcc << shift; unsigned const norm256 = normAcc << shift;
assert(norm256 > 0); assert(norm256 > 0);
assert(norm256 < 256); assert(norm256 < 256);
cost += count[s] * kInverseProbabiltyLog256[norm256]; cost += count[s] * kInverseProbabilityLog256[norm256];
} }
return cost >> 8; return cost >> 8;
} }
@@ -2050,21 +2136,17 @@ static size_t ZSTD_fseBitCost(
unsigned s; unsigned s;
FSE_CState_t cstate; FSE_CState_t cstate;
FSE_initCState(&cstate, ctable); FSE_initCState(&cstate, ctable);
if (ZSTD_getFSEMaxSymbolValue(ctable) < max) { RETURN_ERROR_IF(ZSTD_getFSEMaxSymbolValue(ctable) < max, GENERIC,
DEBUGLOG(5, "Repeat FSE_CTable has maxSymbolValue %u < %u", "Repeat FSE_CTable has maxSymbolValue %u < %u",
ZSTD_getFSEMaxSymbolValue(ctable), max); ZSTD_getFSEMaxSymbolValue(ctable), max);
return ERROR(GENERIC);
}
for (s = 0; s <= max; ++s) { for (s = 0; s <= max; ++s) {
unsigned const tableLog = cstate.stateLog; unsigned const tableLog = cstate.stateLog;
unsigned const badCost = (tableLog + 1) << kAccuracyLog; unsigned const badCost = (tableLog + 1) << kAccuracyLog;
unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog); unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
if (count[s] == 0) if (count[s] == 0)
continue; continue;
if (bitCost >= badCost) { RETURN_ERROR_IF(bitCost >= badCost, GENERIC,
DEBUGLOG(5, "Repeat FSE_CTable has Prob[%u] == 0", s); "Repeat FSE_CTable has Prob[%u] == 0", s);
return ERROR(GENERIC);
}
cost += count[s] * bitCost; cost += count[s] * bitCost;
} }
return cost >> kAccuracyLog; return cost >> kAccuracyLog;
@@ -2080,7 +2162,7 @@ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
BYTE wksp[FSE_NCOUNTBOUND]; BYTE wksp[FSE_NCOUNTBOUND];
S16 norm[MaxSeq + 1]; S16 norm[MaxSeq + 1];
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max); const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq, max)); FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog); return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
} }
@@ -2186,15 +2268,15 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
switch (type) { switch (type) {
case set_rle: case set_rle:
CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max)); FORWARD_IF_ERROR(FSE_buildCTable_rle(nextCTable, (BYTE)max));
if (dstCapacity==0) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(dstCapacity==0, dstSize_tooSmall);
*op = codeTable[0]; *op = codeTable[0];
return 1; return 1;
case set_repeat: case set_repeat:
memcpy(nextCTable, prevCTable, prevCTableSize); memcpy(nextCTable, prevCTable, prevCTableSize);
return 0; return 0;
case set_basic: case set_basic:
CHECK_F(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */ FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
return 0; return 0;
case set_compressed: { case set_compressed: {
S16 norm[MaxSeq + 1]; S16 norm[MaxSeq + 1];
@@ -2205,14 +2287,14 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
nbSeq_1--; nbSeq_1--;
} }
assert(nbSeq_1 > 1); assert(nbSeq_1 > 1);
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max)); FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return NCountSize; FORWARD_IF_ERROR(NCountSize);
CHECK_F(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize)); FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
return NCountSize; return NCountSize;
} }
} }
default: return assert(0), ERROR(GENERIC); default: assert(0); RETURN_ERROR(GENERIC);
} }
} }
@@ -2229,7 +2311,9 @@ ZSTD_encodeSequences_body(
FSE_CState_t stateOffsetBits; FSE_CState_t stateOffsetBits;
FSE_CState_t stateLitLength; FSE_CState_t stateLitLength;
CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */ RETURN_ERROR_IF(
ERR_isError(BIT_initCStream(&blockStream, dst, dstCapacity)),
dstSize_tooSmall, "not enough space remaining");
DEBUGLOG(6, "available space for bitstream : %i (dstCapacity=%u)", DEBUGLOG(6, "available space for bitstream : %i (dstCapacity=%u)",
(int)(blockStream.endPtr - blockStream.startPtr), (int)(blockStream.endPtr - blockStream.startPtr),
(unsigned)dstCapacity); (unsigned)dstCapacity);
@@ -2303,7 +2387,7 @@ ZSTD_encodeSequences_body(
FSE_flushCState(&blockStream, &stateLitLength); FSE_flushCState(&blockStream, &stateLitLength);
{ size_t const streamSize = BIT_closeCStream(&blockStream); { size_t const streamSize = BIT_closeCStream(&blockStream);
if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */ RETURN_ERROR_IF(streamSize==0, dstSize_tooSmall, "not enough space");
return streamSize; return streamSize;
} }
} }
@@ -2368,6 +2452,21 @@ static size_t ZSTD_encodeSequences(
sequences, nbSeq, longOffsets); sequences, nbSeq, longOffsets);
} }
static int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
{
switch (cctxParams->literalCompressionMode) {
case ZSTD_lcm_huffman:
return 0;
case ZSTD_lcm_uncompressed:
return 1;
default:
assert(0 /* impossible: pre-validated */);
/* fall-through */
case ZSTD_lcm_auto:
return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
}
}
/* ZSTD_compressSequences_internal(): /* ZSTD_compressSequences_internal():
* actually compresses both literals and sequences */ * actually compresses both literals and sequences */
MEM_STATIC size_t MEM_STATIC size_t
@@ -2403,22 +2502,22 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
/* Compress literals */ /* Compress literals */
{ const BYTE* const literals = seqStorePtr->litStart; { const BYTE* const literals = seqStorePtr->litStart;
size_t const litSize = seqStorePtr->lit - literals; size_t const litSize = seqStorePtr->lit - literals;
int const disableLiteralCompression = (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
size_t const cSize = ZSTD_compressLiterals( size_t const cSize = ZSTD_compressLiterals(
&prevEntropy->huf, &nextEntropy->huf, &prevEntropy->huf, &nextEntropy->huf,
cctxParams->cParams.strategy, disableLiteralCompression, cctxParams->cParams.strategy,
ZSTD_disableLiteralsCompression(cctxParams),
op, dstCapacity, op, dstCapacity,
literals, litSize, literals, litSize,
workspace, wkspSize, workspace, wkspSize,
bmi2); bmi2);
if (ZSTD_isError(cSize)) FORWARD_IF_ERROR(cSize);
return cSize;
assert(cSize <= dstCapacity); assert(cSize <= dstCapacity);
op += cSize; op += cSize;
} }
/* Sequences Header */ /* Sequences Header */
if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
dstSize_tooSmall);
if (nbSeq < 0x7F) if (nbSeq < 0x7F)
*op++ = (BYTE)nbSeq; *op++ = (BYTE)nbSeq;
else if (nbSeq < LONGNBSEQ) else if (nbSeq < LONGNBSEQ)
@@ -2452,7 +2551,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL, count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable), prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable),
workspace, wkspSize); workspace, wkspSize);
if (ZSTD_isError(countSize)) return countSize; FORWARD_IF_ERROR(countSize);
if (LLtype == set_compressed) if (LLtype == set_compressed)
lastNCount = op; lastNCount = op;
op += countSize; op += countSize;
@@ -2474,7 +2573,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable), prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable),
workspace, wkspSize); workspace, wkspSize);
if (ZSTD_isError(countSize)) return countSize; FORWARD_IF_ERROR(countSize);
if (Offtype == set_compressed) if (Offtype == set_compressed)
lastNCount = op; lastNCount = op;
op += countSize; op += countSize;
@@ -2494,7 +2593,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML, count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable), prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable),
workspace, wkspSize); workspace, wkspSize);
if (ZSTD_isError(countSize)) return countSize; FORWARD_IF_ERROR(countSize);
if (MLtype == set_compressed) if (MLtype == set_compressed)
lastNCount = op; lastNCount = op;
op += countSize; op += countSize;
@@ -2509,10 +2608,10 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
CTable_LitLength, llCodeTable, CTable_LitLength, llCodeTable,
sequences, nbSeq, sequences, nbSeq,
longOffsets, bmi2); longOffsets, bmi2);
if (ZSTD_isError(bitstreamSize)) return bitstreamSize; FORWARD_IF_ERROR(bitstreamSize);
op += bitstreamSize; op += bitstreamSize;
/* zstd versions <= 1.3.4 mistakenly report corruption when /* zstd versions <= 1.3.4 mistakenly report corruption when
* FSE_readNCount() recieves a buffer < 4 bytes. * FSE_readNCount() receives a buffer < 4 bytes.
* Fixed by https://github.com/facebook/zstd/pull/1146. * Fixed by https://github.com/facebook/zstd/pull/1146.
* This can happen when the last set_compressed table present is 2 * This can happen when the last set_compressed table present is 2
* bytes and the bitstream is only one byte. * bytes and the bitstream is only one byte.
@@ -2552,7 +2651,7 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
*/ */
if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity)) if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
return 0; /* block not compressed */ return 0; /* block not compressed */
if (ZSTD_isError(cSize)) return cSize; FORWARD_IF_ERROR(cSize);
/* Check compressibility */ /* Check compressibility */
{ size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy); { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
@@ -2641,7 +2740,10 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
goto out; /* don't even attempt compression below a certain srcSize */ goto out; /* don't even attempt compression below a certain srcSize */
} }
ZSTD_resetSeqStore(&(zc->seqStore)); ZSTD_resetSeqStore(&(zc->seqStore));
ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; /* required for optimal parser to read stats from dictionary */ /* required for optimal parser to read stats from dictionary */
ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
/* tell the optimal parser how we expect to compress literals */
ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
/* a gap between an attached dict and the current window is not safe, /* a gap between an attached dict and the current window is not safe,
* they must remain adjacent, * they must remain adjacent,
@@ -2679,7 +2781,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
ldmSeqStore.seq = zc->ldmSequences; ldmSeqStore.seq = zc->ldmSequences;
ldmSeqStore.capacity = zc->maxNbLdmSequences; ldmSeqStore.capacity = zc->maxNbLdmSequences;
/* Updates ldmSeqStore.size */ /* Updates ldmSeqStore.size */
CHECK_F(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore, FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
&zc->appliedParams.ldmParams, &zc->appliedParams.ldmParams,
src, srcSize)); src, srcSize));
/* Updates ldmSeqStore.pos */ /* Updates ldmSeqStore.pos */
@@ -2752,8 +2854,9 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
ZSTD_matchState_t* const ms = &cctx->blockState.matchState; ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE) RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE,
return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */ dstSize_tooSmall,
"not enough space to store compressed block");
if (remaining < blockSize) blockSize = remaining; if (remaining < blockSize) blockSize = remaining;
if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) { if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) {
@@ -2774,11 +2877,11 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
{ size_t cSize = ZSTD_compressBlock_internal(cctx, { size_t cSize = ZSTD_compressBlock_internal(cctx,
op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
ip, blockSize); ip, blockSize);
if (ZSTD_isError(cSize)) return cSize; FORWARD_IF_ERROR(cSize);
if (cSize == 0) { /* block is not compressible */ if (cSize == 0) { /* block is not compressible */
cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
if (ZSTD_isError(cSize)) return cSize; FORWARD_IF_ERROR(cSize);
} else { } else {
U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
MEM_writeLE24(op, cBlockHeader24); MEM_writeLE24(op, cBlockHeader24);
@@ -2811,11 +2914,11 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
U32 const fcsCode = params.fParams.contentSizeFlag ? U32 const fcsCode = params.fParams.contentSizeFlag ?
(pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */ (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) ); BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
size_t pos=0; size_t pos=0;
assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)); assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
if (dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall);
DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u", DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
!params.fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode); !params.fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
@@ -2823,7 +2926,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
MEM_writeLE32(dst, ZSTD_MAGICNUMBER); MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
pos = 4; pos = 4;
} }
op[pos++] = frameHeaderDecriptionByte; op[pos++] = frameHeaderDescriptionByte;
if (!singleSegment) op[pos++] = windowLogByte; if (!singleSegment) op[pos++] = windowLogByte;
switch(dictIDSizeCode) switch(dictIDSizeCode)
{ {
@@ -2847,11 +2950,11 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
/* ZSTD_writeLastEmptyBlock() : /* ZSTD_writeLastEmptyBlock() :
* output an empty Block with end-of-frame mark to complete a frame * output an empty Block with end-of-frame mark to complete a frame
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h)) * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
* or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize) * or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
*/ */
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity) size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
{ {
if (dstCapacity < ZSTD_blockHeaderSize) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall);
{ U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */ { U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
MEM_writeLE24(dst, cBlockHeader24); MEM_writeLE24(dst, cBlockHeader24);
return ZSTD_blockHeaderSize; return ZSTD_blockHeaderSize;
@@ -2860,10 +2963,9 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq) size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
{ {
if (cctx->stage != ZSTDcs_init) RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong);
return ERROR(stage_wrong); RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
if (cctx->appliedParams.ldmParams.enableLdm) parameter_unsupported);
return ERROR(parameter_unsupported);
cctx->externSeqStore.seq = seq; cctx->externSeqStore.seq = seq;
cctx->externSeqStore.size = nbSeq; cctx->externSeqStore.size = nbSeq;
cctx->externSeqStore.capacity = nbSeq; cctx->externSeqStore.capacity = nbSeq;
@@ -2882,12 +2984,13 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u", DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
cctx->stage, (unsigned)srcSize); cctx->stage, (unsigned)srcSize);
if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */ RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,
"missing init (ZSTD_compressBegin)");
if (frame && (cctx->stage==ZSTDcs_init)) { if (frame && (cctx->stage==ZSTDcs_init)) {
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
cctx->pledgedSrcSizePlusOne-1, cctx->dictID); cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
if (ZSTD_isError(fhSize)) return fhSize; FORWARD_IF_ERROR(fhSize);
dstCapacity -= fhSize; dstCapacity -= fhSize;
dst = (char*)dst + fhSize; dst = (char*)dst + fhSize;
cctx->stage = ZSTDcs_ongoing; cctx->stage = ZSTDcs_ongoing;
@@ -2922,17 +3025,18 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
{ size_t const cSize = frame ? { size_t const cSize = frame ?
ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) : ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize); ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
if (ZSTD_isError(cSize)) return cSize; FORWARD_IF_ERROR(cSize);
cctx->consumedSrcSize += srcSize; cctx->consumedSrcSize += srcSize;
cctx->producedCSize += (cSize + fhSize); cctx->producedCSize += (cSize + fhSize);
assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */ if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1); ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) { RETURN_ERROR_IF(
DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u", cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,
(unsigned)cctx->pledgedSrcSizePlusOne-1, (unsigned)cctx->consumedSrcSize); srcSize_wrong,
return ERROR(srcSize_wrong); "error : pledgedSrcSize = %u, while realSrcSize >= %u",
} (unsigned)cctx->pledgedSrcSizePlusOne-1,
(unsigned)cctx->consumedSrcSize);
} }
return cSize + fhSize; return cSize + fhSize;
} }
@@ -2957,7 +3061,7 @@ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{ {
size_t const blockSizeMax = ZSTD_getBlockSize(cctx); size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
if (srcSize > blockSizeMax) return ERROR(srcSize_wrong); RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong);
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */); return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
} }
@@ -3020,9 +3124,9 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
NOTE: This behavior is not standard and could be improved in the future. */ NOTE: This behavior is not standard and could be improved in the future. */
static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) { static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) {
U32 s; U32 s;
if (dictMaxSymbolValue < maxSymbolValue) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted);
for (s = 0; s <= maxSymbolValue; ++s) { for (s = 0; s <= maxSymbolValue; ++s) {
if (normalizedCounter[s] == 0) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted);
} }
return 0; return 0;
} }
@@ -3060,53 +3164,56 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
{ unsigned maxSymbolValue = 255; { unsigned maxSymbolValue = 255;
size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr); size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted);
if (maxSymbolValue < 255) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted);
dictPtr += hufHeaderSize; dictPtr += hufHeaderSize;
} }
{ unsigned offcodeLog; { unsigned offcodeLog;
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
/* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
/* fill all offset symbols to avoid garbage at end of table */ /* fill all offset symbols to avoid garbage at end of table */
CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.offcodeCTable, RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
offcodeNCount, MaxOff, offcodeLog, bs->entropy.fse.offcodeCTable,
workspace, HUF_WORKSPACE_SIZE), offcodeNCount, MaxOff, offcodeLog,
dictionary_corrupted); workspace, HUF_WORKSPACE_SIZE)),
dictionary_corrupted);
dictPtr += offcodeHeaderSize; dictPtr += offcodeHeaderSize;
} }
{ short matchlengthNCount[MaxML+1]; { short matchlengthNCount[MaxML+1];
unsigned matchlengthMaxValue = MaxML, matchlengthLog; unsigned matchlengthMaxValue = MaxML, matchlengthLog;
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
/* Every match length code must have non-zero probability */ /* Every match length code must have non-zero probability */
CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML)); FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.matchlengthCTable, RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
matchlengthNCount, matchlengthMaxValue, matchlengthLog, bs->entropy.fse.matchlengthCTable,
workspace, HUF_WORKSPACE_SIZE), matchlengthNCount, matchlengthMaxValue, matchlengthLog,
dictionary_corrupted); workspace, HUF_WORKSPACE_SIZE)),
dictionary_corrupted);
dictPtr += matchlengthHeaderSize; dictPtr += matchlengthHeaderSize;
} }
{ short litlengthNCount[MaxLL+1]; { short litlengthNCount[MaxLL+1];
unsigned litlengthMaxValue = MaxLL, litlengthLog; unsigned litlengthMaxValue = MaxLL, litlengthLog;
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
/* Every literal length code must have non-zero probability */ /* Every literal length code must have non-zero probability */
CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL)); FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.litlengthCTable, RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
litlengthNCount, litlengthMaxValue, litlengthLog, bs->entropy.fse.litlengthCTable,
workspace, HUF_WORKSPACE_SIZE), litlengthNCount, litlengthMaxValue, litlengthLog,
dictionary_corrupted); workspace, HUF_WORKSPACE_SIZE)),
dictionary_corrupted);
dictPtr += litlengthHeaderSize; dictPtr += litlengthHeaderSize;
} }
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
bs->rep[0] = MEM_readLE32(dictPtr+0); bs->rep[0] = MEM_readLE32(dictPtr+0);
bs->rep[1] = MEM_readLE32(dictPtr+4); bs->rep[1] = MEM_readLE32(dictPtr+4);
bs->rep[2] = MEM_readLE32(dictPtr+8); bs->rep[2] = MEM_readLE32(dictPtr+8);
@@ -3119,19 +3226,19 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
} }
/* All offset values <= dictContentSize + 128 KB must be representable */ /* All offset values <= dictContentSize + 128 KB must be representable */
CHECK_F (ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff))); FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
/* All repCodes must be <= dictContentSize and != 0*/ /* All repCodes must be <= dictContentSize and != 0*/
{ U32 u; { U32 u;
for (u=0; u<3; u++) { for (u=0; u<3; u++) {
if (bs->rep[u] == 0) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted);
if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted);
} } } }
bs->entropy.huf.repeatMode = HUF_repeat_valid; bs->entropy.huf.repeatMode = HUF_repeat_valid;
bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid; bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid; bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid; bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm)); FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm));
return dictID; return dictID;
} }
} }
@@ -3161,8 +3268,7 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
DEBUGLOG(4, "raw content dictionary detected"); DEBUGLOG(4, "raw content dictionary detected");
return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm); return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
} }
if (dictContentType == ZSTD_dct_fullDict) RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong);
return ERROR(dictionary_wrong);
assert(0); /* impossible */ assert(0); /* impossible */
} }
@@ -3189,13 +3295,13 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff); return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
} }
CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
ZSTDcrp_continue, zbuff) ); ZSTDcrp_continue, zbuff) );
{ {
size_t const dictID = ZSTD_compress_insertDictionary( size_t const dictID = ZSTD_compress_insertDictionary(
cctx->blockState.prevCBlock, &cctx->blockState.matchState, cctx->blockState.prevCBlock, &cctx->blockState.matchState,
&params, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace); &params, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace);
if (ZSTD_isError(dictID)) return dictID; FORWARD_IF_ERROR(dictID);
assert(dictID <= (size_t)(U32)-1); assert(dictID <= (size_t)(U32)-1);
cctx->dictID = (U32)dictID; cctx->dictID = (U32)dictID;
} }
@@ -3212,7 +3318,7 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
{ {
DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog); DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog);
/* compression parameters verification and optimization */ /* compression parameters verification and optimization */
CHECK_F( ZSTD_checkCParams(params.cParams) ); FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
return ZSTD_compressBegin_internal(cctx, return ZSTD_compressBegin_internal(cctx,
dict, dictSize, dictContentType, dtlm, dict, dictSize, dictContentType, dtlm,
cdict, cdict,
@@ -3260,12 +3366,12 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
size_t fhSize = 0; size_t fhSize = 0;
DEBUGLOG(4, "ZSTD_writeEpilogue"); DEBUGLOG(4, "ZSTD_writeEpilogue");
if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */ RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing");
/* special case : empty frame */ /* special case : empty frame */
if (cctx->stage == ZSTDcs_init) { if (cctx->stage == ZSTDcs_init) {
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0); fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
if (ZSTD_isError(fhSize)) return fhSize; FORWARD_IF_ERROR(fhSize);
dstCapacity -= fhSize; dstCapacity -= fhSize;
op += fhSize; op += fhSize;
cctx->stage = ZSTDcs_ongoing; cctx->stage = ZSTDcs_ongoing;
@@ -3274,7 +3380,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
if (cctx->stage != ZSTDcs_ending) { if (cctx->stage != ZSTDcs_ending) {
/* write one last empty block, make it the "last" block */ /* write one last empty block, make it the "last" block */
U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0; U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
if (dstCapacity<4) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
MEM_writeLE32(op, cBlockHeader24); MEM_writeLE32(op, cBlockHeader24);
op += ZSTD_blockHeaderSize; op += ZSTD_blockHeaderSize;
dstCapacity -= ZSTD_blockHeaderSize; dstCapacity -= ZSTD_blockHeaderSize;
@@ -3282,7 +3388,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
if (cctx->appliedParams.fParams.checksumFlag) { if (cctx->appliedParams.fParams.checksumFlag) {
U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
if (dstCapacity<4) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum); DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
MEM_writeLE32(op, checksum); MEM_writeLE32(op, checksum);
op += 4; op += 4;
@@ -3300,18 +3406,20 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
size_t const cSize = ZSTD_compressContinue_internal(cctx, size_t const cSize = ZSTD_compressContinue_internal(cctx,
dst, dstCapacity, src, srcSize, dst, dstCapacity, src, srcSize,
1 /* frame mode */, 1 /* last chunk */); 1 /* frame mode */, 1 /* last chunk */);
if (ZSTD_isError(cSize)) return cSize; FORWARD_IF_ERROR(cSize);
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize); endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
if (ZSTD_isError(endResult)) return endResult; FORWARD_IF_ERROR(endResult);
assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */ if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1); ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
DEBUGLOG(4, "end of frame : controlling src size"); DEBUGLOG(4, "end of frame : controlling src size");
if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) { RETURN_ERROR_IF(
DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u", cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,
(unsigned)cctx->pledgedSrcSizePlusOne-1, (unsigned)cctx->consumedSrcSize); srcSize_wrong,
return ERROR(srcSize_wrong); "error : pledgedSrcSize = %u, while realSrcSize = %u",
} } (unsigned)cctx->pledgedSrcSizePlusOne-1,
(unsigned)cctx->consumedSrcSize);
}
return cSize + endResult; return cSize + endResult;
} }
@@ -3339,7 +3447,7 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
ZSTD_parameters params) ZSTD_parameters params)
{ {
DEBUGLOG(4, "ZSTD_compress_advanced"); DEBUGLOG(4, "ZSTD_compress_advanced");
CHECK_F(ZSTD_checkCParams(params.cParams)); FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams));
return ZSTD_compress_internal(cctx, return ZSTD_compress_internal(cctx,
dst, dstCapacity, dst, dstCapacity,
src, srcSize, src, srcSize,
@@ -3356,7 +3464,7 @@ size_t ZSTD_compress_advanced_internal(
ZSTD_CCtx_params params) ZSTD_CCtx_params params)
{ {
DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize); DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
CHECK_F( ZSTD_compressBegin_internal(cctx, FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
params, srcSize, ZSTDb_not_buffered) ); params, srcSize, ZSTDb_not_buffered) );
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
@@ -3440,7 +3548,7 @@ static size_t ZSTD_initCDict_internal(
void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem); void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem);
cdict->dictBuffer = internalBuffer; cdict->dictBuffer = internalBuffer;
cdict->dictContent = internalBuffer; cdict->dictContent = internalBuffer;
if (!internalBuffer) return ERROR(memory_allocation); RETURN_ERROR_IF(!internalBuffer, memory_allocation);
memcpy(internalBuffer, dictBuffer, dictSize); memcpy(internalBuffer, dictBuffer, dictSize);
} }
cdict->dictContentSize = dictSize; cdict->dictContentSize = dictSize;
@@ -3466,7 +3574,7 @@ static size_t ZSTD_initCDict_internal(
&cdict->cBlockState, &cdict->matchState, &params, &cdict->cBlockState, &cdict->matchState, &params,
cdict->dictContent, cdict->dictContentSize, cdict->dictContent, cdict->dictContentSize,
dictContentType, ZSTD_dtlm_full, cdict->workspace); dictContentType, ZSTD_dtlm_full, cdict->workspace);
if (ZSTD_isError(dictID)) return dictID; FORWARD_IF_ERROR(dictID);
assert(dictID <= (size_t)(U32)-1); assert(dictID <= (size_t)(U32)-1);
cdict->dictID = (U32)dictID; cdict->dictID = (U32)dictID;
} }
@@ -3596,7 +3704,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize) ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
{ {
DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced"); DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
if (cdict==NULL) return ERROR(dictionary_wrong); RETURN_ERROR_IF(cdict==NULL, dictionary_wrong);
{ ZSTD_CCtx_params params = cctx->requestedParams; { ZSTD_CCtx_params params = cctx->requestedParams;
params.cParams = ZSTD_getCParamsFromCDict(cdict); params.cParams = ZSTD_getCParamsFromCDict(cdict);
/* Increase window log to fit the entire dictionary and source if the /* Increase window log to fit the entire dictionary and source if the
@@ -3632,7 +3740,7 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
const void* src, size_t srcSize, const void* src, size_t srcSize,
const ZSTD_CDict* cdict, ZSTD_frameParameters fParams) const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
{ {
CHECK_F (ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */ FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
} }
@@ -3700,7 +3808,7 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
assert(!((dict) && (cdict))); /* either dict or cdict, not both */ assert(!((dict) && (cdict))); /* either dict or cdict, not both */
CHECK_F( ZSTD_compressBegin_internal(cctx, FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
dict, dictSize, dictContentType, ZSTD_dtlm_fast, dict, dictSize, dictContentType, ZSTD_dtlm_fast,
cdict, cdict,
params, pledgedSrcSize, params, pledgedSrcSize,
@@ -3718,13 +3826,17 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
/* ZSTD_resetCStream(): /* ZSTD_resetCStream():
* pledgedSrcSize == 0 means "unknown" */ * pledgedSrcSize == 0 means "unknown" */
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize) size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
{ {
ZSTD_CCtx_params params = zcs->requestedParams; /* temporary : 0 interpreted as "unknown" during transition period.
* Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
* 0 will be interpreted as "empty" in the future.
*/
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize); DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
params.fParams.contentSizeFlag = 1; FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize); return 0;
} }
/*! ZSTD_initCStream_internal() : /*! ZSTD_initCStream_internal() :
@@ -3736,32 +3848,18 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
ZSTD_CCtx_params params, unsigned long long pledgedSrcSize) ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
{ {
DEBUGLOG(4, "ZSTD_initCStream_internal"); DEBUGLOG(4, "ZSTD_initCStream_internal");
params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize); FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
zcs->requestedParams = params;
assert(!((dict) && (cdict))); /* either dict or cdict, not both */ assert(!((dict) && (cdict))); /* either dict or cdict, not both */
if (dict) {
if (dict && dictSize >= 8) { FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
DEBUGLOG(4, "loading dictionary of size %u", (unsigned)dictSize);
if (zcs->staticSize) { /* static CCtx : never uses malloc */
/* incompatible with internal cdict creation */
return ERROR(memory_allocation);
}
ZSTD_freeCDict(zcs->cdictLocal);
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
ZSTD_dlm_byCopy, ZSTD_dct_auto,
params.cParams, zcs->customMem);
zcs->cdict = zcs->cdictLocal;
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
} else { } else {
if (cdict) { /* Dictionary is cleared if !cdict */
params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict; it includes windowLog */ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
}
ZSTD_freeCDict(zcs->cdictLocal);
zcs->cdictLocal = NULL;
zcs->cdict = cdict;
} }
return 0;
return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
} }
/* ZSTD_initCStream_usingCDict_advanced() : /* ZSTD_initCStream_usingCDict_advanced() :
@@ -3772,22 +3870,20 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
unsigned long long pledgedSrcSize) unsigned long long pledgedSrcSize)
{ {
DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced"); DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
if (!cdict) return ERROR(dictionary_wrong); /* cannot handle NULL cdict (does not know what to do) */ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
{ ZSTD_CCtx_params params = zcs->requestedParams; FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
params.cParams = ZSTD_getCParamsFromCDict(cdict); zcs->requestedParams.fParams = fParams;
params.fParams = fParams; FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
return ZSTD_initCStream_internal(zcs, return 0;
NULL, 0, cdict,
params, pledgedSrcSize);
}
} }
/* note : cdict must outlive compression session */ /* note : cdict must outlive compression session */
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict) size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
{ {
ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksum */, 0 /* hideDictID */ };
DEBUGLOG(4, "ZSTD_initCStream_usingCDict"); DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); /* note : will check that cdict != NULL */ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
return 0;
} }
@@ -3797,33 +3893,53 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
* dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */ * dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
const void* dict, size_t dictSize, const void* dict, size_t dictSize,
ZSTD_parameters params, unsigned long long pledgedSrcSize) ZSTD_parameters params, unsigned long long pss)
{ {
DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u", /* for compatibility with older programs relying on this behavior.
(unsigned)pledgedSrcSize, params.fParams.contentSizeFlag); * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN.
CHECK_F( ZSTD_checkCParams(params.cParams) ); * This line will be removed in the future.
if ((pledgedSrcSize==0) && (params.fParams.contentSizeFlag==0)) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */ */
U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
DEBUGLOG(4, "ZSTD_initCStream_advanced");
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params); zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, zcs->requestedParams, pledgedSrcSize); FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
return 0;
} }
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel) size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
{ {
ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel); DEBUGLOG(4, "ZSTD_initCStream_usingDict");
return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, zcs->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN); FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
return 0;
} }
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss) size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
{ {
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; /* temporary : 0 interpreted as "unknown" during transition period. Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. `0` will be interpreted as "empty" in the future */ /* temporary : 0 interpreted as "unknown" during transition period.
ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel); * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, zcs->requestedParams, pledgedSrcSize); * 0 will be interpreted as "empty" in the future.
*/
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
DEBUGLOG(4, "ZSTD_initCStream_srcSize");
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
return 0;
} }
size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel) size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
{ {
DEBUGLOG(4, "ZSTD_initCStream"); DEBUGLOG(4, "ZSTD_initCStream");
return ZSTD_initCStream_srcSize(zcs, compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN); FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
return 0;
} }
/*====== Compression ======*/ /*====== Compression ======*/
@@ -3847,10 +3963,10 @@ static size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
* internal function for all *compressStream*() variants * internal function for all *compressStream*() variants
* non-static, because can be called from zstdmt_compress.c * non-static, because can be called from zstdmt_compress.c
* @return : hint size for next input */ * @return : hint size for next input */
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
ZSTD_outBuffer* output, ZSTD_outBuffer* output,
ZSTD_inBuffer* input, ZSTD_inBuffer* input,
ZSTD_EndDirective const flushMode) ZSTD_EndDirective const flushMode)
{ {
const char* const istart = (const char*)input->src; const char* const istart = (const char*)input->src;
const char* const iend = istart + input->size; const char* const iend = istart + input->size;
@@ -3873,8 +3989,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
switch(zcs->streamStage) switch(zcs->streamStage)
{ {
case zcss_init: case zcss_init:
/* call ZSTD_initCStream() first ! */ RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!");
return ERROR(init_missing);
case zcss_load: case zcss_load:
if ( (flushMode == ZSTD_e_end) if ( (flushMode == ZSTD_e_end)
@@ -3884,7 +3999,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
size_t const cSize = ZSTD_compressEnd(zcs, size_t const cSize = ZSTD_compressEnd(zcs,
op, oend-op, ip, iend-ip); op, oend-op, ip, iend-ip);
DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize); DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
if (ZSTD_isError(cSize)) return cSize; FORWARD_IF_ERROR(cSize);
ip = iend; ip = iend;
op += cSize; op += cSize;
zcs->frameEnded = 1; zcs->frameEnded = 1;
@@ -3925,7 +4040,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
zcs->inBuff + zcs->inToCompress, iSize) : zcs->inBuff + zcs->inToCompress, iSize) :
ZSTD_compressContinue(zcs, cDst, oSize, ZSTD_compressContinue(zcs, cDst, oSize,
zcs->inBuff + zcs->inToCompress, iSize); zcs->inBuff + zcs->inToCompress, iSize);
if (ZSTD_isError(cSize)) return cSize; FORWARD_IF_ERROR(cSize);
zcs->frameEnded = lastBlock; zcs->frameEnded = lastBlock;
/* prepare next block */ /* prepare next block */
zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
@@ -4001,7 +4116,7 @@ static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)
size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input) size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
{ {
CHECK_F( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) ); FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) );
return ZSTD_nextInputSizeHint_MTorST(zcs); return ZSTD_nextInputSizeHint_MTorST(zcs);
} }
@@ -4013,14 +4128,15 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
{ {
DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp); DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
/* check conditions */ /* check conditions */
if (output->pos > output->size) return ERROR(GENERIC); RETURN_ERROR_IF(output->pos > output->size, GENERIC);
if (input->pos > input->size) return ERROR(GENERIC); RETURN_ERROR_IF(input->pos > input->size, GENERIC);
assert(cctx!=NULL); assert(cctx!=NULL);
/* transparent initialization stage */ /* transparent initialization stage */
if (cctx->streamStage == zcss_init) { if (cctx->streamStage == zcss_init) {
ZSTD_CCtx_params params = cctx->requestedParams; ZSTD_CCtx_params params = cctx->requestedParams;
ZSTD_prefixDict const prefixDict = cctx->prefixDict; ZSTD_prefixDict const prefixDict = cctx->prefixDict;
FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) ); /* Init the local dict if present. */
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
@@ -4039,11 +4155,11 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
params.nbWorkers); params.nbWorkers);
cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem); cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
if (cctx->mtctx == NULL) return ERROR(memory_allocation); RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation);
} }
/* mt compression */ /* mt compression */
DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
CHECK_F( ZSTDMT_initCStream_internal( FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
cctx->mtctx, cctx->mtctx,
prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent, prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent,
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) ); cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
@@ -4051,7 +4167,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
cctx->appliedParams.nbWorkers = params.nbWorkers; cctx->appliedParams.nbWorkers = params.nbWorkers;
} else } else
#endif #endif
{ CHECK_F( ZSTD_resetCStream_internal(cctx, { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
cctx->cdict, cctx->cdict,
params, cctx->pledgedSrcSizePlusOne-1) ); params, cctx->pledgedSrcSizePlusOne-1) );
@@ -4063,20 +4179,30 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
/* compression stage */ /* compression stage */
#ifdef ZSTD_MULTITHREAD #ifdef ZSTD_MULTITHREAD
if (cctx->appliedParams.nbWorkers > 0) { if (cctx->appliedParams.nbWorkers > 0) {
int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
size_t flushMin;
assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */);
if (cctx->cParamsChanged) { if (cctx->cParamsChanged) {
ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams); ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
cctx->cParamsChanged = 0; cctx->cParamsChanged = 0;
} }
{ size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp); do {
flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
if ( ZSTD_isError(flushMin) if ( ZSTD_isError(flushMin)
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */ || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
} }
DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic"); FORWARD_IF_ERROR(flushMin);
return flushMin; } while (forceMaxProgress && flushMin != 0 && output->pos < output->size);
} } DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
/* Either we don't require maximum forward progress, we've finished the
* flush, or we are out of output space.
*/
assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size);
return flushMin;
}
#endif #endif
CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) ); FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) );
DEBUGLOG(5, "completed ZSTD_compressStream2"); DEBUGLOG(5, "completed ZSTD_compressStream2");
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */ return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
} }
@@ -4107,10 +4233,10 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
dst, dstCapacity, &oPos, dst, dstCapacity, &oPos,
src, srcSize, &iPos, src, srcSize, &iPos,
ZSTD_e_end); ZSTD_e_end);
if (ZSTD_isError(result)) return result; FORWARD_IF_ERROR(result);
if (result != 0) { /* compression not completed, due to lack of output space */ if (result != 0) { /* compression not completed, due to lack of output space */
assert(oPos == dstCapacity); assert(oPos == dstCapacity);
return ERROR(dstSize_tooSmall); RETURN_ERROR(dstSize_tooSmall);
} }
assert(iPos == srcSize); /* all input is expected consumed */ assert(iPos == srcSize); /* all input is expected consumed */
return oPos; return oPos;
@@ -4132,7 +4258,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
{ {
ZSTD_inBuffer input = { NULL, 0, 0 }; ZSTD_inBuffer input = { NULL, 0, 0 };
size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end); size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
CHECK_F( remainingToFlush ); FORWARD_IF_ERROR( remainingToFlush );
if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */ if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */
/* single thread mode : attempt to calculate remaining to flush more precisely */ /* single thread mode : attempt to calculate remaining to flush more precisely */
{ size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE; { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
@@ -4151,7 +4277,7 @@ int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
{ /* "default" - guarantees a monotonically increasing memory budget */ { /* "default" - for any srcSize > 256 KB */
/* W, C, H, S, L, TL, strat */ /* W, C, H, S, L, TL, strat */
{ 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
{ 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
@@ -4258,13 +4384,13 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
}; };
/*! ZSTD_getCParams() : /*! ZSTD_getCParams() :
* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
* Size values are optional, provide 0 if not known or unused */ * Size values are optional, provide 0 if not known or unused */
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
{ {
size_t const addedSize = srcSizeHint ? 0 : 500; size_t const addedSize = srcSizeHint ? 0 : 500;
U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : (U64)-1; U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : ZSTD_CONTENTSIZE_UNKNOWN; /* intentional overflow for srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN */
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */ U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
int row = compressionLevel; int row = compressionLevel;
DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel); DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel);
if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
@@ -4272,13 +4398,14 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
{ ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row]; { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */ if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); /* refine parameters based on srcSize & dictSize */
} }
} }
/*! ZSTD_getParams() : /*! ZSTD_getParams() :
* same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`). * same idea as ZSTD_getCParams()
* All fields of `ZSTD_frameParameters` are set to default (0) */ * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
* Fields of `ZSTD_frameParameters` are set to default values */
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
ZSTD_parameters params; ZSTD_parameters params;
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize); ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
+14 -11
View File
@@ -36,9 +36,9 @@ extern "C" {
#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1 now means "unsorted". #define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1 now means "unsorted".
It could be confused for a real successor at index "1", if sorted as larger than its predecessor. It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
It's not a big deal though : candidate will just be sorted again. It's not a big deal though : candidate will just be sorted again.
Additionnally, candidate position 1 will be lost. Additionally, candidate position 1 will be lost.
But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss. But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be misdhandled after table re-use with a different strategy The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy
Constant required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */ Constant required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
@@ -54,6 +54,14 @@ typedef struct ZSTD_prefixDict_s {
ZSTD_dictContentType_e dictContentType; ZSTD_dictContentType_e dictContentType;
} ZSTD_prefixDict; } ZSTD_prefixDict;
typedef struct {
void* dictBuffer;
void const* dict;
size_t dictSize;
ZSTD_dictContentType_e dictContentType;
ZSTD_CDict* cdict;
} ZSTD_localDict;
typedef struct { typedef struct {
U32 CTable[HUF_CTABLE_SIZE_U32(255)]; U32 CTable[HUF_CTABLE_SIZE_U32(255)];
HUF_repeat repeatMode; HUF_repeat repeatMode;
@@ -107,6 +115,7 @@ typedef struct {
U32 offCodeSumBasePrice; /* to compare to log2(offreq) */ U32 offCodeSumBasePrice; /* to compare to log2(offreq) */
ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */ ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */
const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */ const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */
ZSTD_literalCompressionMode_e literalCompressionMode;
} optState_t; } optState_t;
typedef struct { typedef struct {
@@ -188,6 +197,7 @@ struct ZSTD_CCtx_params_s {
* 1<<wLog, even for dictionary */ * 1<<wLog, even for dictionary */
ZSTD_dictAttachPref_e attachDictPref; ZSTD_dictAttachPref_e attachDictPref;
ZSTD_literalCompressionMode_e literalCompressionMode;
/* Multithreading: used to pass parameters to mtctx */ /* Multithreading: used to pass parameters to mtctx */
int nbWorkers; int nbWorkers;
@@ -243,7 +253,7 @@ struct ZSTD_CCtx_s {
U32 frameEnded; U32 frameEnded;
/* Dictionary */ /* Dictionary */
ZSTD_CDict* cdictLocal; ZSTD_localDict localDict;
const ZSTD_CDict* cdict; const ZSTD_CDict* cdict;
ZSTD_prefixDict prefixDict; /* single-usage dictionary */ ZSTD_prefixDict prefixDict; /* single-usage dictionary */
@@ -806,13 +816,6 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
void ZSTD_resetSeqStore(seqStore_t* ssPtr); void ZSTD_resetSeqStore(seqStore_t* ssPtr);
/*! ZSTD_compressStream_generic() :
* Private use only. To be called from zstdmt_compress.c in single-thread mode. */
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
ZSTD_outBuffer* output,
ZSTD_inBuffer* input,
ZSTD_EndDirective const flushMode);
/*! ZSTD_getCParamsFromCDict() : /*! ZSTD_getCParamsFromCDict() :
* as the name implies */ * as the name implies */
ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict); ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
@@ -839,7 +842,7 @@ size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
/* ZSTD_writeLastEmptyBlock() : /* ZSTD_writeLastEmptyBlock() :
* output an empty Block with end-of-frame mark to complete a frame * output an empty Block with end-of-frame mark to complete a frame
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h)) * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
* or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize) * or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
*/ */
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity); size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
+204 -125
View File
@@ -45,7 +45,155 @@ FORCE_INLINE_TEMPLATE
size_t ZSTD_compressBlock_fast_generic( size_t ZSTD_compressBlock_fast_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize, void const* src, size_t srcSize,
U32 const mls, ZSTD_dictMode_e const dictMode) U32 const mls)
{
const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable;
U32 const hlog = cParams->hashLog;
/* support stepSize of 0 */
size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1;
const BYTE* const base = ms->window.base;
const BYTE* const istart = (const BYTE*)src;
/* We check ip0 (ip + 0) and ip1 (ip + 1) each loop */
const BYTE* ip0 = istart;
const BYTE* ip1;
const BYTE* anchor = istart;
const U32 prefixStartIndex = ms->window.dictLimit;
const BYTE* const prefixStart = base + prefixStartIndex;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - HASH_READ_SIZE;
U32 offset_1=rep[0], offset_2=rep[1];
U32 offsetSaved = 0;
/* init */
ip0 += (ip0 == prefixStart);
ip1 = ip0 + 1;
{
U32 const maxRep = (U32)(ip0 - prefixStart);
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
}
/* Main Search Loop */
while (ip1 < ilimit) { /* < instead of <=, because check at ip0+2 */
size_t mLength;
BYTE const* ip2 = ip0 + 2;
size_t const h0 = ZSTD_hashPtr(ip0, hlog, mls);
U32 const val0 = MEM_read32(ip0);
size_t const h1 = ZSTD_hashPtr(ip1, hlog, mls);
U32 const val1 = MEM_read32(ip1);
U32 const current0 = (U32)(ip0-base);
U32 const current1 = (U32)(ip1-base);
U32 const matchIndex0 = hashTable[h0];
U32 const matchIndex1 = hashTable[h1];
BYTE const* repMatch = ip2-offset_1;
const BYTE* match0 = base + matchIndex0;
const BYTE* match1 = base + matchIndex1;
U32 offcode;
hashTable[h0] = current0; /* update hash table */
hashTable[h1] = current1; /* update hash table */
assert(ip0 + 1 == ip1);
if ((offset_1 > 0) & (MEM_read32(repMatch) == MEM_read32(ip2))) {
mLength = ip2[-1] == repMatch[-1] ? 1 : 0;
ip0 = ip2 - mLength;
match0 = repMatch - mLength;
offcode = 0;
goto _match;
}
if ((matchIndex0 > prefixStartIndex) && MEM_read32(match0) == val0) {
/* found a regular match */
goto _offset;
}
if ((matchIndex1 > prefixStartIndex) && MEM_read32(match1) == val1) {
/* found a regular match after one literal */
ip0 = ip1;
match0 = match1;
goto _offset;
}
{
size_t const step = ((ip0-anchor) >> (kSearchStrength - 1)) + stepSize;
assert(step >= 2);
ip0 += step;
ip1 += step;
continue;
}
_offset: /* Requires: ip0, match0 */
/* Compute the offset code */
offset_2 = offset_1;
offset_1 = (U32)(ip0-match0);
offcode = offset_1 + ZSTD_REP_MOVE;
mLength = 0;
/* Count the backwards match length */
while (((ip0>anchor) & (match0>prefixStart))
&& (ip0[-1] == match0[-1])) { ip0--; match0--; mLength++; } /* catch up */
_match: /* Requires: ip0, match0, offcode */
/* Count the forward length */
mLength += ZSTD_count(ip0+mLength+4, match0+mLength+4, iend) + 4;
ZSTD_storeSeq(seqStore, ip0-anchor, anchor, offcode, mLength-MINMATCH);
/* match found */
ip0 += mLength;
anchor = ip0;
ip1 = ip0 + 1;
if (ip0 <= ilimit) {
/* Fill Table */
assert(base+current0+2 > istart); /* check base overflow */
hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */
hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);
while ( (ip0 <= ilimit)
&& ( (offset_2>0)
& (MEM_read32(ip0) == MEM_read32(ip0 - offset_2)) )) {
/* store sequence */
size_t const rLength = ZSTD_count(ip0+4, ip0+4-offset_2, iend) + 4;
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);
ip0 += rLength;
ip1 = ip0 + 1;
ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
anchor = ip0;
continue; /* faster when present (confirmed on gcc-8) ... (?) */
}
}
}
/* save reps for next block */
rep[0] = offset_1 ? offset_1 : offsetSaved;
rep[1] = offset_2 ? offset_2 : offsetSaved;
/* Return the last literals size */
return iend - anchor;
}
size_t ZSTD_compressBlock_fast(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize)
{
ZSTD_compressionParameters const* cParams = &ms->cParams;
U32 const mls = cParams->minMatch;
assert(ms->dictMatchState == NULL);
switch(mls)
{
default: /* includes case 3 */
case 4 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4);
case 5 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5);
case 6 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6);
case 7 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7);
}
}
FORCE_INLINE_TEMPLATE
size_t ZSTD_compressBlock_fast_dictMatchState_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize, U32 const mls)
{ {
const ZSTD_compressionParameters* const cParams = &ms->cParams; const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable; U32* const hashTable = ms->hashTable;
@@ -64,46 +212,26 @@ size_t ZSTD_compressBlock_fast_generic(
U32 offsetSaved = 0; U32 offsetSaved = 0;
const ZSTD_matchState_t* const dms = ms->dictMatchState; const ZSTD_matchState_t* const dms = ms->dictMatchState;
const ZSTD_compressionParameters* const dictCParams = const ZSTD_compressionParameters* const dictCParams = &dms->cParams ;
dictMode == ZSTD_dictMatchState ? const U32* const dictHashTable = dms->hashTable;
&dms->cParams : NULL; const U32 dictStartIndex = dms->window.dictLimit;
const U32* const dictHashTable = dictMode == ZSTD_dictMatchState ? const BYTE* const dictBase = dms->window.base;
dms->hashTable : NULL; const BYTE* const dictStart = dictBase + dictStartIndex;
const U32 dictStartIndex = dictMode == ZSTD_dictMatchState ? const BYTE* const dictEnd = dms->window.nextSrc;
dms->window.dictLimit : 0; const U32 dictIndexDelta = prefixStartIndex - (U32)(dictEnd - dictBase);
const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
dms->window.base : NULL;
const BYTE* const dictStart = dictMode == ZSTD_dictMatchState ?
dictBase + dictStartIndex : NULL;
const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
dms->window.nextSrc : NULL;
const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
prefixStartIndex - (U32)(dictEnd - dictBase) :
0;
const U32 dictAndPrefixLength = (U32)(ip - prefixStart + dictEnd - dictStart); const U32 dictAndPrefixLength = (U32)(ip - prefixStart + dictEnd - dictStart);
const U32 dictHLog = dictMode == ZSTD_dictMatchState ? const U32 dictHLog = dictCParams->hashLog;
dictCParams->hashLog : hlog;
assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
/* otherwise, we would get index underflow when translating a dict index /* otherwise, we would get index underflow when translating a dict index
* into a local index */ * into a local index */
assert(dictMode != ZSTD_dictMatchState assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
|| prefixStartIndex >= (U32)(dictEnd - dictBase));
/* init */ /* init */
ip += (dictAndPrefixLength == 0); ip += (dictAndPrefixLength == 0);
if (dictMode == ZSTD_noDict) { /* dictMatchState repCode checks don't currently handle repCode == 0
U32 const maxRep = (U32)(ip - prefixStart); * disabling. */
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0; assert(offset_1 <= dictAndPrefixLength);
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0; assert(offset_2 <= dictAndPrefixLength);
}
if (dictMode == ZSTD_dictMatchState) {
/* dictMatchState repCode checks don't currently handle repCode == 0
* disabling. */
assert(offset_1 <= dictAndPrefixLength);
assert(offset_2 <= dictAndPrefixLength);
}
/* Main Search Loop */ /* Main Search Loop */
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */ while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
@@ -113,50 +241,37 @@ size_t ZSTD_compressBlock_fast_generic(
U32 const matchIndex = hashTable[h]; U32 const matchIndex = hashTable[h];
const BYTE* match = base + matchIndex; const BYTE* match = base + matchIndex;
const U32 repIndex = current + 1 - offset_1; const U32 repIndex = current + 1 - offset_1;
const BYTE* repMatch = (dictMode == ZSTD_dictMatchState const BYTE* repMatch = (repIndex < prefixStartIndex) ?
&& repIndex < prefixStartIndex) ?
dictBase + (repIndex - dictIndexDelta) : dictBase + (repIndex - dictIndexDelta) :
base + repIndex; base + repIndex;
hashTable[h] = current; /* update hash table */ hashTable[h] = current; /* update hash table */
if ( (dictMode == ZSTD_dictMatchState) if ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */
&& ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4; mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
ip++; ip++;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH); ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
} else if ( dictMode == ZSTD_noDict
&& ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
ip++;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
} else if ( (matchIndex <= prefixStartIndex) ) { } else if ( (matchIndex <= prefixStartIndex) ) {
if (dictMode == ZSTD_dictMatchState) { size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls);
size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls); U32 const dictMatchIndex = dictHashTable[dictHash];
U32 const dictMatchIndex = dictHashTable[dictHash]; const BYTE* dictMatch = dictBase + dictMatchIndex;
const BYTE* dictMatch = dictBase + dictMatchIndex; if (dictMatchIndex <= dictStartIndex ||
if (dictMatchIndex <= dictStartIndex || MEM_read32(dictMatch) != MEM_read32(ip)) {
MEM_read32(dictMatch) != MEM_read32(ip)) {
assert(stepSize >= 1);
ip += ((ip-anchor) >> kSearchStrength) + stepSize;
continue;
} else {
/* found a dict match */
U32 const offset = (U32)(current-dictMatchIndex-dictIndexDelta);
mLength = ZSTD_count_2segments(ip+4, dictMatch+4, iend, dictEnd, prefixStart) + 4;
while (((ip>anchor) & (dictMatch>dictStart))
&& (ip[-1] == dictMatch[-1])) {
ip--; dictMatch--; mLength++;
} /* catch up */
offset_2 = offset_1;
offset_1 = offset;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
}
} else {
assert(stepSize >= 1); assert(stepSize >= 1);
ip += ((ip-anchor) >> kSearchStrength) + stepSize; ip += ((ip-anchor) >> kSearchStrength) + stepSize;
continue; continue;
} else {
/* found a dict match */
U32 const offset = (U32)(current-dictMatchIndex-dictIndexDelta);
mLength = ZSTD_count_2segments(ip+4, dictMatch+4, iend, dictEnd, prefixStart) + 4;
while (((ip>anchor) & (dictMatch>dictStart))
&& (ip[-1] == dictMatch[-1])) {
ip--; dictMatch--; mLength++;
} /* catch up */
offset_2 = offset_1;
offset_1 = offset;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
} }
} else if (MEM_read32(match) != MEM_read32(ip)) { } else if (MEM_read32(match) != MEM_read32(ip)) {
/* it's not a match, and we're not going to check the dictionary */ /* it's not a match, and we're not going to check the dictionary */
@@ -185,41 +300,27 @@ size_t ZSTD_compressBlock_fast_generic(
hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base); hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base);
/* check immediate repcode */ /* check immediate repcode */
if (dictMode == ZSTD_dictMatchState) { while (ip <= ilimit) {
while (ip <= ilimit) { U32 const current2 = (U32)(ip-base);
U32 const current2 = (U32)(ip-base); U32 const repIndex2 = current2 - offset_2;
U32 const repIndex2 = current2 - offset_2; const BYTE* repMatch2 = repIndex2 < prefixStartIndex ?
const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase - dictIndexDelta + repIndex2 :
dictBase - dictIndexDelta + repIndex2 : base + repIndex2;
base + repIndex2; if ( ((U32)((prefixStartIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
if ( ((U32)((prefixStartIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */) && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) { const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH); hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2; ip += repLength2;
ip += repLength2;
anchor = ip;
continue;
}
break;
}
}
if (dictMode == ZSTD_noDict) {
while ( (ip <= ilimit)
&& ( (offset_2>0)
& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
/* store sequence */
size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = (U32)(ip-base);
ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
ip += rLength;
anchor = ip; anchor = ip;
continue; /* faster when present ... (?) */ continue;
} } } } }
break;
}
}
}
/* save reps for next block */ /* save reps for next block */
rep[0] = offset_1 ? offset_1 : offsetSaved; rep[0] = offset_1 ? offset_1 : offsetSaved;
@@ -229,28 +330,6 @@ size_t ZSTD_compressBlock_fast_generic(
return iend - anchor; return iend - anchor;
} }
size_t ZSTD_compressBlock_fast(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize)
{
ZSTD_compressionParameters const* cParams = &ms->cParams;
U32 const mls = cParams->minMatch;
assert(ms->dictMatchState == NULL);
switch(mls)
{
default: /* includes case 3 */
case 4 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_noDict);
case 5 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_noDict);
case 6 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_noDict);
case 7 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_noDict);
}
}
size_t ZSTD_compressBlock_fast_dictMatchState( size_t ZSTD_compressBlock_fast_dictMatchState(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize) void const* src, size_t srcSize)
@@ -262,13 +341,13 @@ size_t ZSTD_compressBlock_fast_dictMatchState(
{ {
default: /* includes case 3 */ default: /* includes case 3 */
case 4 : case 4 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_dictMatchState); return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 4);
case 5 : case 5 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_dictMatchState); return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 5);
case 6 : case 6 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_dictMatchState); return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 6);
case 7 : case 7 :
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_dictMatchState); return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 7);
} }
} }
+1 -1
View File
@@ -19,7 +19,7 @@ extern "C" {
U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip); U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). pre-emptively increase value of ZSTD_DUBT_UNSORTED_MARK */ void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */
size_t ZSTD_compressBlock_btlazy2( size_t ZSTD_compressBlock_btlazy2(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+1 -1
View File
@@ -429,7 +429,7 @@ size_t ZSTD_ldm_generateSequences(
*/ */
assert(ldmState->window.nextSrc >= (BYTE const*)src + srcSize); assert(ldmState->window.nextSrc >= (BYTE const*)src + srcSize);
/* The input could be very large (in zstdmt), so it must be broken up into /* The input could be very large (in zstdmt), so it must be broken up into
* chunks to enforce the maximmum distance and handle overflow correction. * chunks to enforce the maximum distance and handle overflow correction.
*/ */
assert(sequences->pos <= sequences->size); assert(sequences->pos <= sequences->size);
assert(sequences->size <= sequences->capacity); assert(sequences->size <= sequences->capacity);
+27 -11
View File
@@ -64,9 +64,15 @@ MEM_STATIC double ZSTD_fCost(U32 price)
} }
#endif #endif
static int ZSTD_compressedLiterals(optState_t const* const optPtr)
{
return optPtr->literalCompressionMode != ZSTD_lcm_uncompressed;
}
static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel) static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
{ {
optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel); if (ZSTD_compressedLiterals(optPtr))
optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel); optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);
optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel); optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);
optPtr->offCodeSumBasePrice = WEIGHT(optPtr->offCodeSum, optLevel); optPtr->offCodeSumBasePrice = WEIGHT(optPtr->offCodeSum, optLevel);
@@ -99,6 +105,7 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
const BYTE* const src, size_t const srcSize, const BYTE* const src, size_t const srcSize,
int const optLevel) int const optLevel)
{ {
int const compressedLiterals = ZSTD_compressedLiterals(optPtr);
DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize); DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize);
optPtr->priceType = zop_dynamic; optPtr->priceType = zop_dynamic;
@@ -113,9 +120,10 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
/* huffman table presumed generated by dictionary */ /* huffman table presumed generated by dictionary */
optPtr->priceType = zop_dynamic; optPtr->priceType = zop_dynamic;
assert(optPtr->litFreq != NULL); if (compressedLiterals) {
optPtr->litSum = 0; unsigned lit;
{ unsigned lit; assert(optPtr->litFreq != NULL);
optPtr->litSum = 0;
for (lit=0; lit<=MaxLit; lit++) { for (lit=0; lit<=MaxLit; lit++) {
U32 const scaleLog = 11; /* scale to 2K */ U32 const scaleLog = 11; /* scale to 2K */
U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit); U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit);
@@ -163,10 +171,11 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
} else { /* not a dictionary */ } else { /* not a dictionary */
assert(optPtr->litFreq != NULL); assert(optPtr->litFreq != NULL);
{ unsigned lit = MaxLit; if (compressedLiterals) {
unsigned lit = MaxLit;
HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */ HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
} }
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
{ unsigned ll; { unsigned ll;
for (ll=0; ll<=MaxLL; ll++) for (ll=0; ll<=MaxLL; ll++)
@@ -190,7 +199,8 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
} else { /* new block : re-use previous statistics, scaled down */ } else { /* new block : re-use previous statistics, scaled down */
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1); if (compressedLiterals)
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0); optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0);
optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0); optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0);
optPtr->offCodeSum = ZSTD_downscaleStat(optPtr->offCodeFreq, MaxOff, 0); optPtr->offCodeSum = ZSTD_downscaleStat(optPtr->offCodeFreq, MaxOff, 0);
@@ -207,6 +217,10 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
int optLevel) int optLevel)
{ {
if (litLength == 0) return 0; if (litLength == 0) return 0;
if (!ZSTD_compressedLiterals(optPtr))
return (litLength << 3) * BITCOST_MULTIPLIER; /* Uncompressed - 8 bytes per literal. */
if (optPtr->priceType == zop_predef) if (optPtr->priceType == zop_predef)
return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */ return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */
@@ -310,7 +324,8 @@ static void ZSTD_updateStats(optState_t* const optPtr,
U32 offsetCode, U32 matchLength) U32 offsetCode, U32 matchLength)
{ {
/* literals */ /* literals */
{ U32 u; if (ZSTD_compressedLiterals(optPtr)) {
U32 u;
for (u=0; u < litLength; u++) for (u=0; u < litLength; u++)
optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD; optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
optPtr->litSum += litLength*ZSTD_LITFREQ_ADD; optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
@@ -870,7 +885,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
/* large match -> immediate encoding */ /* large match -> immediate encoding */
{ U32 const maxML = matches[nbMatches-1].len; { U32 const maxML = matches[nbMatches-1].len;
U32 const maxOffset = matches[nbMatches-1].off; U32 const maxOffset = matches[nbMatches-1].off;
DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new serie", DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
nbMatches, maxML, maxOffset, (U32)(ip-prefixStart)); nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
if (maxML > sufficient_len) { if (maxML > sufficient_len) {
@@ -1108,7 +1123,8 @@ static U32 ZSTD_upscaleStat(unsigned* table, U32 lastEltIndex, int bonus)
/* used in 2-pass strategy */ /* used in 2-pass strategy */
MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr) MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
{ {
optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0); if (ZSTD_compressedLiterals(optPtr))
optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0); optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0);
optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0); optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0);
optPtr->offCodeSum = ZSTD_upscaleStat(optPtr->offCodeFreq, MaxOff, 0); optPtr->offCodeSum = ZSTD_upscaleStat(optPtr->offCodeFreq, MaxOff, 0);
@@ -1117,7 +1133,7 @@ MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
/* ZSTD_initStats_ultra(): /* ZSTD_initStats_ultra():
* make a first compression pass, just to seed stats with more accurate starting values. * make a first compression pass, just to seed stats with more accurate starting values.
* only works on first block, with no dictionary and no ldm. * only works on first block, with no dictionary and no ldm.
* this function cannot error, hence its constract must be respected. * this function cannot error, hence its contract must be respected.
*/ */
static void static void
ZSTD_initStats_ultra(ZSTD_matchState_t* ms, ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
+41 -49
View File
@@ -22,6 +22,7 @@
/* ====== Dependencies ====== */ /* ====== Dependencies ====== */
#include <string.h> /* memcpy, memset */ #include <string.h> /* memcpy, memset */
#include <limits.h> /* INT_MAX, UINT_MAX */ #include <limits.h> /* INT_MAX, UINT_MAX */
#include "mem.h" /* MEM_STATIC */
#include "pool.h" /* threadpool */ #include "pool.h" /* threadpool */
#include "threading.h" /* mutex */ #include "threading.h" /* mutex */
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */ #include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
@@ -456,7 +457,7 @@ typedef struct {
* Must be acquired after the main mutex when acquiring both. * Must be acquired after the main mutex when acquiring both.
*/ */
ZSTD_pthread_mutex_t ldmWindowMutex; ZSTD_pthread_mutex_t ldmWindowMutex;
ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is udpated */ ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is updated */
ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */ ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */
} serialState_t; } serialState_t;
@@ -647,7 +648,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
buffer_t dstBuff = job->dstBuff; buffer_t dstBuff = job->dstBuff;
size_t lastCBlockSize = 0; size_t lastCBlockSize = 0;
/* ressources */ /* resources */
if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation)); if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation));
if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */ if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */
dstBuff = ZSTDMT_getBuffer(job->bufPool); dstBuff = ZSTDMT_getBuffer(job->bufPool);
@@ -672,7 +673,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
if (ZSTD_isError(initError)) JOB_ERROR(initError); if (ZSTD_isError(initError)) JOB_ERROR(initError);
} else { /* srcStart points at reloaded section */ } else { /* srcStart points at reloaded section */
U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size; U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
{ size_t const forceWindowError = ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob); { size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError); if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
} }
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, { size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
@@ -864,14 +865,10 @@ static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {
* Internal use only */ * Internal use only */
size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers) size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
{ {
if (nbWorkers > ZSTDMT_NBWORKERS_MAX) nbWorkers = ZSTDMT_NBWORKERS_MAX; return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);
params->nbWorkers = nbWorkers;
params->overlapLog = ZSTDMT_OVERLAPLOG_DEFAULT;
params->jobSize = 0;
return nbWorkers;
} }
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem) MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem)
{ {
ZSTDMT_CCtx* mtctx; ZSTDMT_CCtx* mtctx;
U32 nbJobs = nbWorkers + 2; U32 nbJobs = nbWorkers + 2;
@@ -906,6 +903,17 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
return mtctx; return mtctx;
} }
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
{
#ifdef ZSTD_MULTITHREAD
return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem);
#else
(void)nbWorkers;
(void)cMem;
return NULL;
#endif
}
ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers) ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
{ {
return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem); return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
@@ -986,26 +994,13 @@ ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
{ {
case ZSTDMT_p_jobSize : case ZSTDMT_p_jobSize :
DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value); DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value);
if ( value != 0 /* default */ return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value);
&& value < ZSTDMT_JOBSIZE_MIN)
value = ZSTDMT_JOBSIZE_MIN;
assert(value >= 0);
if (value > ZSTDMT_JOBSIZE_MAX) value = ZSTDMT_JOBSIZE_MAX;
params->jobSize = value;
return value;
case ZSTDMT_p_overlapLog : case ZSTDMT_p_overlapLog :
DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value); DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value);
if (value < ZSTD_OVERLAPLOG_MIN) value = ZSTD_OVERLAPLOG_MIN; return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value);
if (value > ZSTD_OVERLAPLOG_MAX) value = ZSTD_OVERLAPLOG_MAX;
params->overlapLog = value;
return value;
case ZSTDMT_p_rsyncable : case ZSTDMT_p_rsyncable :
value = (value != 0); DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value);
params->rsyncable = value; return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value);
return value;
default : default :
return ERROR(parameter_unsupported); return ERROR(parameter_unsupported);
} }
@@ -1021,32 +1016,29 @@ size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter,
{ {
switch (parameter) { switch (parameter) {
case ZSTDMT_p_jobSize: case ZSTDMT_p_jobSize:
assert(mtctx->params.jobSize <= INT_MAX); return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value);
*value = (int)(mtctx->params.jobSize);
break;
case ZSTDMT_p_overlapLog: case ZSTDMT_p_overlapLog:
*value = mtctx->params.overlapLog; return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value);
break;
case ZSTDMT_p_rsyncable: case ZSTDMT_p_rsyncable:
*value = mtctx->params.rsyncable; return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value);
break;
default: default:
return ERROR(parameter_unsupported); return ERROR(parameter_unsupported);
} }
return 0;
} }
/* Sets parameters relevant to the compression job, /* Sets parameters relevant to the compression job,
* initializing others to default values. */ * initializing others to default values. */
static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params) static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
{ {
ZSTD_CCtx_params jobParams; ZSTD_CCtx_params jobParams = params;
memset(&jobParams, 0, sizeof(jobParams)); /* Clear parameters related to multithreading */
jobParams.forceWindow = 0;
jobParams.cParams = params.cParams; jobParams.nbWorkers = 0;
jobParams.fParams = params.fParams; jobParams.jobSize = 0;
jobParams.compressionLevel = params.compressionLevel; jobParams.overlapLog = 0;
jobParams.rsyncable = 0;
memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t));
memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem));
return jobParams; return jobParams;
} }
@@ -1056,7 +1048,7 @@ static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers) static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
{ {
if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation); if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);
CHECK_F( ZSTDMT_expandJobsTable(mtctx, nbWorkers) ); FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) );
mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers); mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers);
if (mtctx->bufPool == NULL) return ERROR(memory_allocation); if (mtctx->bufPool == NULL) return ERROR(memory_allocation);
mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers); mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);
@@ -1263,7 +1255,7 @@ static size_t ZSTDMT_compress_advanced_internal(
if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize)) if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize))
return ERROR(memory_allocation); return ERROR(memory_allocation);
CHECK_F( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */ FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */
{ unsigned u; { unsigned u;
for (u=0; u<nbJobs; u++) { for (u=0; u<nbJobs; u++) {
@@ -1396,7 +1388,7 @@ size_t ZSTDMT_initCStream_internal(
/* init */ /* init */
if (params.nbWorkers != mtctx->params.nbWorkers) if (params.nbWorkers != mtctx->params.nbWorkers)
CHECK_F( ZSTDMT_resize(mtctx, params.nbWorkers) ); FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) );
if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN; if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX; if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX;
@@ -1547,7 +1539,7 @@ size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) {
/* ZSTDMT_writeLastEmptyBlock() /* ZSTDMT_writeLastEmptyBlock()
* Write a single empty block with an end-of-frame to finish a frame. * Write a single empty block with an end-of-frame to finish a frame.
* Job must be created from streaming variant. * Job must be created from streaming variant.
* This function is always successfull if expected conditions are fulfilled. * This function is always successful if expected conditions are fulfilled.
*/ */
static void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job) static void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job)
{ {
@@ -1987,7 +1979,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
assert(input->pos <= input->size); assert(input->pos <= input->size);
if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */ if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp); return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp);
} }
if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) { if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
@@ -2051,7 +2043,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|| ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */ || ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */
size_t const jobSize = mtctx->inBuff.filled; size_t const jobSize = mtctx->inBuff.filled;
assert(mtctx->inBuff.filled <= mtctx->targetSectionSize); assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);
CHECK_F( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) ); FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
} }
/* check for potential compressed data ready to be flushed */ /* check for potential compressed data ready to be flushed */
@@ -2065,7 +2057,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input) size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
{ {
CHECK_F( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) ); FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
/* recommended next input size : fill current input buffer */ /* recommended next input size : fill current input buffer */
return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */ return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
@@ -2082,7 +2074,7 @@ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* ou
|| ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */ || ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)", DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
(U32)srcSize, (U32)endFrame); (U32)srcSize, (U32)endFrame);
CHECK_F( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) ); FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
} }
/* check if there is any data available to flush */ /* check if there is any data available to flush */
+43 -26
View File
@@ -17,10 +17,25 @@
/* Note : This is an internal API. /* Note : This is an internal API.
* Some methods are still exposed (ZSTDLIB_API), * These APIs used to be exposed with ZSTDLIB_API,
* because it used to be the only way to invoke MT compression. * because it used to be the only way to invoke MT compression.
* Now, it's recommended to use ZSTD_compress_generic() instead. * Now, it's recommended to use ZSTD_compress2 and ZSTD_compressStream2()
* These methods will stop being exposed in a future version */ * instead.
*
* If you depend on these APIs and can't switch, then define
* ZSTD_LEGACY_MULTITHREADED_API when making the dynamic library.
* However, we may completely remove these functions in a future
* release, so please switch soon.
*
* This API requires ZSTD_MULTITHREAD to be defined during compilation,
* otherwise ZSTDMT_createCCtx*() will fail.
*/
#ifdef ZSTD_LEGACY_MULTITHREADED_API
# define ZSTDMT_API ZSTDLIB_API
#else
# define ZSTDMT_API
#endif
/* === Dependencies === */ /* === Dependencies === */
#include <stddef.h> /* size_t */ #include <stddef.h> /* size_t */
@@ -40,17 +55,19 @@
/* === Memory management === */ /* === Memory management === */
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx; typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers); /* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
ZSTD_customMem cMem); ZSTD_customMem cMem);
ZSTDLIB_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx); ZSTDMT_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
ZSTDLIB_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx); ZSTDMT_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
/* === Simple one-pass compression function === */ /* === Simple one-pass compression function === */
ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx, ZSTDMT_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
void* dst, size_t dstCapacity, void* dst, size_t dstCapacity,
const void* src, size_t srcSize, const void* src, size_t srcSize,
int compressionLevel); int compressionLevel);
@@ -59,31 +76,31 @@ ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
/* === Streaming functions === */ /* === Streaming functions === */
ZSTDLIB_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel); ZSTDMT_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */ ZSTDMT_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
ZSTDLIB_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx); ZSTDMT_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
ZSTDLIB_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input); ZSTDMT_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
ZSTDLIB_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */ ZSTDMT_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
ZSTDLIB_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */ ZSTDMT_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
/* === Advanced functions and parameters === */ /* === Advanced functions and parameters === */
ZSTDLIB_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx, ZSTDMT_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
void* dst, size_t dstCapacity, void* dst, size_t dstCapacity,
const void* src, size_t srcSize, const void* src, size_t srcSize,
const ZSTD_CDict* cdict, const ZSTD_CDict* cdict,
ZSTD_parameters params, ZSTD_parameters params,
int overlapLog); int overlapLog);
ZSTDLIB_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx, ZSTDMT_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */ const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */
ZSTD_parameters params, ZSTD_parameters params,
unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */ unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */
ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx, ZSTDMT_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
const ZSTD_CDict* cdict, const ZSTD_CDict* cdict,
ZSTD_frameParameters fparams, ZSTD_frameParameters fparams,
unsigned long long pledgedSrcSize); /* note : zero means empty */ unsigned long long pledgedSrcSize); /* note : zero means empty */
@@ -92,7 +109,7 @@ ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */ * List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
typedef enum { typedef enum {
ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */ ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compressionr ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */ ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compression ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
ZSTDMT_p_rsyncable /* Enables rsyncable mode. */ ZSTDMT_p_rsyncable /* Enables rsyncable mode. */
} ZSTDMT_parameter; } ZSTDMT_parameter;
@@ -101,12 +118,12 @@ typedef enum {
* The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__ * The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__
* Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions. * Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */ * @return : 0, or an error code (which can be tested using ZSTD_isError()) */
ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value); ZSTDMT_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
/* ZSTDMT_getMTCtxParameter() : /* ZSTDMT_getMTCtxParameter() :
* Query the ZSTDMT_CCtx for a parameter value. * Query the ZSTDMT_CCtx for a parameter value.
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */ * @return : 0, or an error code (which can be tested using ZSTD_isError()) */
ZSTDLIB_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value); ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
/*! ZSTDMT_compressStream_generic() : /*! ZSTDMT_compressStream_generic() :
@@ -116,7 +133,7 @@ ZSTDLIB_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter
* 0 if fully flushed * 0 if fully flushed
* or an error code * or an error code
* note : needs to be init using any ZSTD_initCStream*() variant */ * note : needs to be init using any ZSTD_initCStream*() variant */
ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
ZSTD_outBuffer* output, ZSTD_outBuffer* output,
ZSTD_inBuffer* input, ZSTD_inBuffer* input,
ZSTD_EndDirective endOp); ZSTD_EndDirective endOp);
+4 -4
View File
@@ -105,9 +105,9 @@ ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE); ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
/* load entropy tables */ /* load entropy tables */
CHECK_E( ZSTD_loadDEntropy(&ddict->entropy, RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
ddict->dictContent, ddict->dictSize), &ddict->entropy, ddict->dictContent, ddict->dictSize)),
dictionary_corrupted ); dictionary_corrupted);
ddict->entropyPresent = 1; ddict->entropyPresent = 1;
return 0; return 0;
} }
@@ -133,7 +133,7 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
/* parse dictionary content */ /* parse dictionary content */
CHECK_F( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) ); FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
return 0; return 0;
} }
+283 -190
View File
@@ -106,6 +106,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
dctx->ddictLocal = NULL; dctx->ddictLocal = NULL;
dctx->dictEnd = NULL; dctx->dictEnd = NULL;
dctx->ddictIsCold = 0; dctx->ddictIsCold = 0;
dctx->dictUses = ZSTD_dont_use;
dctx->inBuff = NULL; dctx->inBuff = NULL;
dctx->inBuffSize = 0; dctx->inBuffSize = 0;
dctx->outBuffSize = 0; dctx->outBuffSize = 0;
@@ -147,13 +148,20 @@ ZSTD_DCtx* ZSTD_createDCtx(void)
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem); return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
} }
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
{
ZSTD_freeDDict(dctx->ddictLocal);
dctx->ddictLocal = NULL;
dctx->ddict = NULL;
dctx->dictUses = ZSTD_dont_use;
}
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
{ {
if (dctx==NULL) return 0; /* support free on NULL */ if (dctx==NULL) return 0; /* support free on NULL */
if (dctx->staticSize) return ERROR(memory_allocation); /* not compatible with static DCtx */ RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
{ ZSTD_customMem const cMem = dctx->customMem; { ZSTD_customMem const cMem = dctx->customMem;
ZSTD_freeDDict(dctx->ddictLocal); ZSTD_clearDict(dctx);
dctx->ddictLocal = NULL;
ZSTD_free(dctx->inBuff, cMem); ZSTD_free(dctx->inBuff, cMem);
dctx->inBuff = NULL; dctx->inBuff = NULL;
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
@@ -203,7 +211,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format) static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
{ {
size_t const minInputSize = ZSTD_startingInputLength(format); size_t const minInputSize = ZSTD_startingInputLength(format);
if (srcSize < minInputSize) return ERROR(srcSize_wrong); RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1]; { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
U32 const dictID= fhd & 3; U32 const dictID= fhd & 3;
@@ -238,7 +246,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */ memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
if (srcSize < minInputSize) return minInputSize; if (srcSize < minInputSize) return minInputSize;
if (src==NULL) return ERROR(GENERIC); /* invalid parameter */ RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
if ( (format != ZSTD_f_zstd1_magicless) if ( (format != ZSTD_f_zstd1_magicless)
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) { && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
@@ -251,7 +259,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
zfhPtr->frameType = ZSTD_skippableFrame; zfhPtr->frameType = ZSTD_skippableFrame;
return 0; return 0;
} }
return ERROR(prefix_unknown); RETURN_ERROR(prefix_unknown);
} }
/* ensure there is enough `srcSize` to fully read/decode frame header */ /* ensure there is enough `srcSize` to fully read/decode frame header */
@@ -269,14 +277,13 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
U64 windowSize = 0; U64 windowSize = 0;
U32 dictID = 0; U32 dictID = 0;
U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN; U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
if ((fhdByte & 0x08) != 0) RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
return ERROR(frameParameter_unsupported); /* reserved bits, must be zero */ "reserved bits, must be zero");
if (!singleSegment) { if (!singleSegment) {
BYTE const wlByte = ip[pos++]; BYTE const wlByte = ip[pos++];
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN; U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
if (windowLog > ZSTD_WINDOWLOG_MAX) RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
return ERROR(frameParameter_windowTooLarge);
windowSize = (1ULL << windowLog); windowSize = (1ULL << windowLog);
windowSize += (windowSize >> 3) * (wlByte&7); windowSize += (windowSize >> 3) * (wlByte&7);
} }
@@ -348,12 +355,11 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE; size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
U32 sizeU32; U32 sizeU32;
if (srcSize < ZSTD_SKIPPABLEHEADERSIZE) RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
return ERROR(srcSize_wrong);
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE); sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
if ((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32) RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
return ERROR(frameParameter_unsupported); frameParameter_unsupported);
return skippableHeaderSize + sizeU32; return skippableHeaderSize + sizeU32;
} }
@@ -428,13 +434,89 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
{ {
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format); size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
if (ZSTD_isError(result)) return result; /* invalid header */ if (ZSTD_isError(result)) return result; /* invalid header */
if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */ RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
return ERROR(dictionary_wrong); /* Skip the dictID check in fuzzing mode, because it makes the search
* harder.
*/
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
dictionary_wrong);
#endif
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0); if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
return 0; return 0;
} }
static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
{
ZSTD_frameSizeInfo frameSizeInfo;
frameSizeInfo.compressedSize = ret;
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
return frameSizeInfo;
}
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
{
ZSTD_frameSizeInfo frameSizeInfo;
memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
if (ZSTD_isLegacy(src, srcSize))
return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
#endif
if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
return frameSizeInfo;
} else {
const BYTE* ip = (const BYTE*)src;
const BYTE* const ipstart = ip;
size_t remainingSize = srcSize;
size_t nbBlocks = 0;
ZSTD_frameHeader zfh;
/* Extract Frame Header */
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
if (ZSTD_isError(ret))
return ZSTD_errorFrameSizeInfo(ret);
if (ret > 0)
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
}
ip += zfh.headerSize;
remainingSize -= zfh.headerSize;
/* Iterate over each block */
while (1) {
blockProperties_t blockProperties;
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTD_isError(cBlockSize))
return ZSTD_errorFrameSizeInfo(cBlockSize);
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
ip += ZSTD_blockHeaderSize + cBlockSize;
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
nbBlocks++;
if (blockProperties.lastBlock) break;
}
/* Final frame content checksum */
if (zfh.checksumFlag) {
if (remainingSize < 4)
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
ip += 4;
}
frameSizeInfo.compressedSize = ip - ipstart;
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
? zfh.frameContentSize
: nbBlocks * zfh.blockSizeMax;
return frameSizeInfo;
}
}
/** ZSTD_findFrameCompressedSize() : /** ZSTD_findFrameCompressedSize() :
* compatible with legacy mode * compatible with legacy mode
@@ -443,53 +525,34 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
* @return : the compressed size of the frame starting at `src` */ * @return : the compressed size of the frame starting at `src` */
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
{ {
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
if (ZSTD_isLegacy(src, srcSize)) return frameSizeInfo.compressedSize;
return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
#endif
if ( (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START ) {
return readSkippableFrameSize(src, srcSize);
} else {
const BYTE* ip = (const BYTE*)src;
const BYTE* const ipstart = ip;
size_t remainingSize = srcSize;
ZSTD_frameHeader zfh;
/* Extract Frame Header */
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
if (ZSTD_isError(ret)) return ret;
if (ret > 0) return ERROR(srcSize_wrong);
}
ip += zfh.headerSize;
remainingSize -= zfh.headerSize;
/* Loop on each block */
while (1) {
blockProperties_t blockProperties;
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTD_isError(cBlockSize)) return cBlockSize;
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
return ERROR(srcSize_wrong);
ip += ZSTD_blockHeaderSize + cBlockSize;
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
if (blockProperties.lastBlock) break;
}
if (zfh.checksumFlag) { /* Final frame content checksum */
if (remainingSize < 4) return ERROR(srcSize_wrong);
ip += 4;
}
return ip - ipstart;
}
} }
/** ZSTD_decompressBound() :
* compatible with legacy mode
* `src` must point to the start of a ZSTD frame or a skippeable frame
* `srcSize` must be at least as large as the frame contained
* @return : the maximum decompressed size of the compressed source
*/
unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
{
unsigned long long bound = 0;
/* Iterate over each frame */
while (srcSize > 0) {
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
size_t const compressedSize = frameSizeInfo.compressedSize;
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
return ZSTD_CONTENTSIZE_ERROR;
src = (const BYTE*)src + compressedSize;
srcSize -= compressedSize;
bound += decompressedBound;
}
return bound;
}
/*-************************************************************* /*-*************************************************************
* Frame decoding * Frame decoding
@@ -522,9 +585,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
DEBUGLOG(5, "ZSTD_copyRawBlock"); DEBUGLOG(5, "ZSTD_copyRawBlock");
if (dst == NULL) { if (dst == NULL) {
if (srcSize == 0) return 0; if (srcSize == 0) return 0;
return ERROR(dstBuffer_null); RETURN_ERROR(dstBuffer_null);
} }
if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall);
memcpy(dst, src, srcSize); memcpy(dst, src, srcSize);
return srcSize; return srcSize;
} }
@@ -535,9 +598,9 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
{ {
if (dst == NULL) { if (dst == NULL) {
if (regenSize == 0) return 0; if (regenSize == 0) return 0;
return ERROR(dstBuffer_null); RETURN_ERROR(dstBuffer_null);
} }
if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall);
memset(dst, b, regenSize); memset(dst, b, regenSize);
return regenSize; return regenSize;
} }
@@ -560,15 +623,16 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr); DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
/* check */ /* check */
if (remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize) RETURN_ERROR_IF(
return ERROR(srcSize_wrong); remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize,
srcSize_wrong);
/* Frame Header */ /* Frame Header */
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_FRAMEHEADERSIZE_PREFIX); { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_FRAMEHEADERSIZE_PREFIX);
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize; if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
if (remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize) RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
return ERROR(srcSize_wrong); srcSize_wrong);
CHECK_F( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) ); FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize; ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
} }
@@ -581,7 +645,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
ip += ZSTD_blockHeaderSize; ip += ZSTD_blockHeaderSize;
remainingSrcSize -= ZSTD_blockHeaderSize; remainingSrcSize -= ZSTD_blockHeaderSize;
if (cBlockSize > remainingSrcSize) return ERROR(srcSize_wrong); RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
switch(blockProperties.blockType) switch(blockProperties.blockType)
{ {
@@ -596,7 +660,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
break; break;
case bt_reserved : case bt_reserved :
default: default:
return ERROR(corruption_detected); RETURN_ERROR(corruption_detected);
} }
if (ZSTD_isError(decodedSize)) return decodedSize; if (ZSTD_isError(decodedSize)) return decodedSize;
@@ -609,15 +673,15 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
} }
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) { if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
if ((U64)(op-ostart) != dctx->fParams.frameContentSize) { RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
return ERROR(corruption_detected); corruption_detected);
} } }
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */ if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
U32 checkRead; U32 checkRead;
if (remainingSrcSize<4) return ERROR(checksum_wrong); RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong);
checkRead = MEM_readLE32(ip); checkRead = MEM_readLE32(ip);
if (checkRead != checkCalc) return ERROR(checksum_wrong); RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong);
ip += 4; ip += 4;
remainingSrcSize -= 4; remainingSrcSize -= 4;
} }
@@ -652,8 +716,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
size_t decodedSize; size_t decodedSize;
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize); size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
if (ZSTD_isError(frameSize)) return frameSize; if (ZSTD_isError(frameSize)) return frameSize;
/* legacy support is not compatible with static dctx */ RETURN_ERROR_IF(dctx->staticSize, memory_allocation,
if (dctx->staticSize) return ERROR(memory_allocation); "legacy support is not compatible with static dctx");
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize); decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
if (ZSTD_isError(decodedSize)) return decodedSize; if (ZSTD_isError(decodedSize)) return decodedSize;
@@ -676,7 +740,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
size_t const skippableSize = readSkippableFrameSize(src, srcSize); size_t const skippableSize = readSkippableFrameSize(src, srcSize);
if (ZSTD_isError(skippableSize)) if (ZSTD_isError(skippableSize))
return skippableSize; return skippableSize;
if (srcSize < skippableSize) return ERROR(srcSize_wrong); RETURN_ERROR_IF(srcSize < skippableSize, srcSize_wrong);
src = (const BYTE *)src + skippableSize; src = (const BYTE *)src + skippableSize;
srcSize -= skippableSize; srcSize -= skippableSize;
@@ -685,29 +749,29 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
if (ddict) { if (ddict) {
/* we were called from ZSTD_decompress_usingDDict */ /* we were called from ZSTD_decompress_usingDDict */
CHECK_F(ZSTD_decompressBegin_usingDDict(dctx, ddict)); FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
} else { } else {
/* this will initialize correctly with no dict if dict == NULL, so /* this will initialize correctly with no dict if dict == NULL, so
* use this in all cases but ddict */ * use this in all cases but ddict */
CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize)); FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
} }
ZSTD_checkContinuity(dctx, dst); ZSTD_checkContinuity(dctx, dst);
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity, { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
&src, &srcSize); &src, &srcSize);
if ( (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown) RETURN_ERROR_IF(
&& (moreThan1Frame==1) ) { (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
/* at least one frame successfully completed, && (moreThan1Frame==1),
* but following bytes are garbage : srcSize_wrong,
* it's more likely to be a srcSize error, "at least one frame successfully completed, but following "
* specifying more bytes than compressed size of frame(s). "bytes are garbage: it's more likely to be a srcSize error, "
* This error message replaces ERROR(prefix_unknown), "specifying more bytes than compressed size of frame(s). This "
* which would be confusing, as the first header is actually correct. "error message replaces ERROR(prefix_unknown), which would be "
* Note that one could be unlucky, it might be a corruption error instead, "confusing, as the first header is actually correct. Note that "
* happening right at the place where we expect zstd magic bytes. "one could be unlucky, it might be a corruption error instead, "
* But this is _much_ less likely than a srcSize field error. */ "happening right at the place where we expect zstd magic "
return ERROR(srcSize_wrong); "bytes. But this is _much_ less likely than a srcSize field "
} "error.");
if (ZSTD_isError(res)) return res; if (ZSTD_isError(res)) return res;
assert(res <= dstCapacity); assert(res <= dstCapacity);
dst = (BYTE*)dst + res; dst = (BYTE*)dst + res;
@@ -716,7 +780,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
moreThan1Frame = 1; moreThan1Frame = 1;
} /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */ } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */ RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
return (BYTE*)dst - (BYTE*)dststart; return (BYTE*)dst - (BYTE*)dststart;
} }
@@ -730,9 +794,26 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
} }
static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
{
switch (dctx->dictUses) {
default:
assert(0 /* Impossible */);
/* fall-through */
case ZSTD_dont_use:
ZSTD_clearDict(dctx);
return NULL;
case ZSTD_use_indefinitely:
return dctx->ddict;
case ZSTD_use_once:
dctx->dictUses = ZSTD_dont_use;
return dctx->ddict;
}
}
size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{ {
return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0); return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
} }
@@ -741,7 +822,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1) #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
size_t regenSize; size_t regenSize;
ZSTD_DCtx* const dctx = ZSTD_createDCtx(); ZSTD_DCtx* const dctx = ZSTD_createDCtx();
if (dctx==NULL) return ERROR(memory_allocation); RETURN_ERROR_IF(dctx==NULL, memory_allocation);
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize); regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
ZSTD_freeDCtx(dctx); ZSTD_freeDCtx(dctx);
return regenSize; return regenSize;
@@ -791,8 +872,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
{ {
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize); DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
/* Sanity check */ /* Sanity check */
if (srcSize != dctx->expected) RETURN_ERROR_IF(srcSize != dctx->expected, srcSize_wrong, "not allowed");
return ERROR(srcSize_wrong); /* not allowed */
if (dstCapacity) ZSTD_checkContinuity(dctx, dst); if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
switch (dctx->stage) switch (dctx->stage)
@@ -817,7 +897,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
case ZSTDds_decodeFrameHeader: case ZSTDds_decodeFrameHeader:
assert(src != NULL); assert(src != NULL);
memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize); memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize)); FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
dctx->expected = ZSTD_blockHeaderSize; dctx->expected = ZSTD_blockHeaderSize;
dctx->stage = ZSTDds_decodeBlockHeader; dctx->stage = ZSTDds_decodeBlockHeader;
return 0; return 0;
@@ -867,7 +947,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
break; break;
case bt_reserved : /* should never happen */ case bt_reserved : /* should never happen */
default: default:
return ERROR(corruption_detected); RETURN_ERROR(corruption_detected);
} }
if (ZSTD_isError(rSize)) return rSize; if (ZSTD_isError(rSize)) return rSize;
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize); DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
@@ -876,10 +956,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */ if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize); DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) { RETURN_ERROR_IF(
if (dctx->decodedSize != dctx->fParams.frameContentSize) { dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
return ERROR(corruption_detected); && dctx->decodedSize != dctx->fParams.frameContentSize,
} } corruption_detected);
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */ if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
dctx->expected = 4; dctx->expected = 4;
dctx->stage = ZSTDds_checkChecksum; dctx->stage = ZSTDds_checkChecksum;
@@ -900,7 +980,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
U32 const check32 = MEM_readLE32(src); U32 const check32 = MEM_readLE32(src);
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32); DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
if (check32 != h32) return ERROR(checksum_wrong); RETURN_ERROR_IF(check32 != h32, checksum_wrong);
dctx->expected = 0; dctx->expected = 0;
dctx->stage = ZSTDds_getFrameHeaderSize; dctx->stage = ZSTDds_getFrameHeaderSize;
return 0; return 0;
@@ -921,7 +1001,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
default: default:
assert(0); /* impossible */ assert(0); /* impossible */
return ERROR(GENERIC); /* some compiler require default to do something */ RETURN_ERROR(GENERIC); /* some compiler require default to do something */
} }
} }
@@ -945,7 +1025,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
const BYTE* dictPtr = (const BYTE*)dict; const BYTE* dictPtr = (const BYTE*)dict;
const BYTE* const dictEnd = dictPtr + dictSize; const BYTE* const dictEnd = dictPtr + dictSize;
if (dictSize <= 8) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */ assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
dictPtr += 8; /* skip header = magic + dictID */ dictPtr += 8; /* skip header = magic + dictID */
@@ -964,16 +1044,16 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
dictPtr, dictEnd - dictPtr, dictPtr, dictEnd - dictPtr,
workspace, workspaceSize); workspace, workspaceSize);
#endif #endif
if (HUF_isError(hSize)) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
dictPtr += hSize; dictPtr += hSize;
} }
{ short offcodeNCount[MaxOff+1]; { short offcodeNCount[MaxOff+1];
unsigned offcodeMaxValue = MaxOff, offcodeLog; unsigned offcodeMaxValue = MaxOff, offcodeLog;
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
if (offcodeMaxValue > MaxOff) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
ZSTD_buildFSETable( entropy->OFTable, ZSTD_buildFSETable( entropy->OFTable,
offcodeNCount, offcodeMaxValue, offcodeNCount, offcodeMaxValue,
OF_base, OF_bits, OF_base, OF_bits,
@@ -984,9 +1064,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
{ short matchlengthNCount[MaxML+1]; { short matchlengthNCount[MaxML+1];
unsigned matchlengthMaxValue = MaxML, matchlengthLog; unsigned matchlengthMaxValue = MaxML, matchlengthLog;
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
if (matchlengthMaxValue > MaxML) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
ZSTD_buildFSETable( entropy->MLTable, ZSTD_buildFSETable( entropy->MLTable,
matchlengthNCount, matchlengthMaxValue, matchlengthNCount, matchlengthMaxValue,
ML_base, ML_bits, ML_base, ML_bits,
@@ -997,9 +1077,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
{ short litlengthNCount[MaxLL+1]; { short litlengthNCount[MaxLL+1];
unsigned litlengthMaxValue = MaxLL, litlengthLog; unsigned litlengthMaxValue = MaxLL, litlengthLog;
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
if (litlengthMaxValue > MaxLL) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
ZSTD_buildFSETable( entropy->LLTable, ZSTD_buildFSETable( entropy->LLTable,
litlengthNCount, litlengthMaxValue, litlengthNCount, litlengthMaxValue,
LL_base, LL_bits, LL_base, LL_bits,
@@ -1007,12 +1087,13 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
dictPtr += litlengthHeaderSize; dictPtr += litlengthHeaderSize;
} }
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
{ int i; { int i;
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12)); size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
for (i=0; i<3; i++) { for (i=0; i<3; i++) {
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4; U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
if (rep==0 || rep >= dictContentSize) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(rep==0 || rep >= dictContentSize,
dictionary_corrupted);
entropy->rep[i] = rep; entropy->rep[i] = rep;
} } } }
@@ -1030,7 +1111,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
/* load entropy tables */ /* load entropy tables */
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize); { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
dict = (const char*)dict + eSize; dict = (const char*)dict + eSize;
dictSize -= eSize; dictSize -= eSize;
} }
@@ -1064,9 +1145,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
{ {
CHECK_F( ZSTD_decompressBegin(dctx) ); FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
if (dict && dictSize) if (dict && dictSize)
CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted); RETURN_ERROR_IF(
ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
dictionary_corrupted);
return 0; return 0;
} }
@@ -1085,7 +1168,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
DEBUGLOG(4, "DDict is %s", DEBUGLOG(4, "DDict is %s",
dctx->ddictIsCold ? "~cold~" : "hot!"); dctx->ddictIsCold ? "~cold~" : "hot!");
} }
CHECK_F( ZSTD_decompressBegin(dctx) ); FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
if (ddict) { /* NULL ddict is equivalent to no dictionary */ if (ddict) { /* NULL ddict is equivalent to no dictionary */
ZSTD_copyDDictParameters(dctx, ddict); ZSTD_copyDDictParameters(dctx, ddict);
} }
@@ -1104,7 +1187,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
} }
/*! ZSTD_getDictID_fromFrame() : /*! ZSTD_getDictID_fromFrame() :
* Provides the dictID required to decompresse frame stored within `src`. * Provides the dictID required to decompress frame stored within `src`.
* If @return == 0, the dictID could not be decoded. * If @return == 0, the dictID could not be decoded.
* This could for one of the following reasons : * This could for one of the following reasons :
* - The frame does not require a dictionary (most common case). * - The frame does not require a dictionary (most common case).
@@ -1176,15 +1259,14 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_dictContentType_e dictContentType) ZSTD_dictContentType_e dictContentType)
{ {
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
ZSTD_freeDDict(dctx->ddictLocal); ZSTD_clearDict(dctx);
if (dict && dictSize >= 8) { if (dict && dictSize >= 8) {
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem); dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
if (dctx->ddictLocal == NULL) return ERROR(memory_allocation); RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
} else { dctx->ddict = dctx->ddictLocal;
dctx->ddictLocal = NULL; dctx->dictUses = ZSTD_use_indefinitely;
} }
dctx->ddict = dctx->ddictLocal;
return 0; return 0;
} }
@@ -1200,7 +1282,9 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType) size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
{ {
return ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType); FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
dctx->dictUses = ZSTD_use_once;
return 0;
} }
size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize) size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
@@ -1215,9 +1299,8 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize) size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
{ {
DEBUGLOG(4, "ZSTD_initDStream_usingDict"); DEBUGLOG(4, "ZSTD_initDStream_usingDict");
zds->streamStage = zdss_init; FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
zds->noForwardProgress = 0; FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
CHECK_F( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
return ZSTD_FRAMEHEADERSIZE_PREFIX; return ZSTD_FRAMEHEADERSIZE_PREFIX;
} }
@@ -1225,7 +1308,7 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
size_t ZSTD_initDStream(ZSTD_DStream* zds) size_t ZSTD_initDStream(ZSTD_DStream* zds)
{ {
DEBUGLOG(4, "ZSTD_initDStream"); DEBUGLOG(4, "ZSTD_initDStream");
return ZSTD_initDStream_usingDict(zds, NULL, 0); return ZSTD_initDStream_usingDDict(zds, NULL);
} }
/* ZSTD_initDStream_usingDDict() : /* ZSTD_initDStream_usingDDict() :
@@ -1233,9 +1316,9 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
* this function cannot fail */ * this function cannot fail */
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict) size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
{ {
size_t const initResult = ZSTD_initDStream(dctx); FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
dctx->ddict = ddict; FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
return initResult; return ZSTD_FRAMEHEADERSIZE_PREFIX;
} }
/* ZSTD_resetDStream() : /* ZSTD_resetDStream() :
@@ -1243,19 +1326,19 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
* this function cannot fail */ * this function cannot fail */
size_t ZSTD_resetDStream(ZSTD_DStream* dctx) size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
{ {
DEBUGLOG(4, "ZSTD_resetDStream"); FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
dctx->streamStage = zdss_loadHeader;
dctx->lhSize = dctx->inPos = dctx->outStart = dctx->outEnd = 0;
dctx->legacyVersion = 0;
dctx->hostageByte = 0;
return ZSTD_FRAMEHEADERSIZE_PREFIX; return ZSTD_FRAMEHEADERSIZE_PREFIX;
} }
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict) size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
{ {
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
dctx->ddict = ddict; ZSTD_clearDict(dctx);
if (ddict) {
dctx->ddict = ddict;
dctx->dictUses = ZSTD_use_indefinitely;
}
return 0; return 0;
} }
@@ -1267,9 +1350,9 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax); ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
size_t const min = (size_t)1 << bounds.lowerBound; size_t const min = (size_t)1 << bounds.lowerBound;
size_t const max = (size_t)1 << bounds.upperBound; size_t const max = (size_t)1 << bounds.upperBound;
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
if (maxWindowSize < min) return ERROR(parameter_outOfBound); RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
if (maxWindowSize > max) return ERROR(parameter_outOfBound); RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
dctx->maxWindowSize = maxWindowSize; dctx->maxWindowSize = maxWindowSize;
return 0; return 0;
} }
@@ -1311,15 +1394,15 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
} }
#define CHECK_DBOUNDS(p,v) { \ #define CHECK_DBOUNDS(p,v) { \
if (!ZSTD_dParam_withinBounds(p, v)) \ RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
return ERROR(parameter_outOfBound); \
} }
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value) size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
{ {
if (dctx->streamStage != zdss_init) return ERROR(stage_wrong); RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
switch(dParam) { switch(dParam) {
case ZSTD_d_windowLogMax: case ZSTD_d_windowLogMax:
if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
CHECK_DBOUNDS(ZSTD_d_windowLogMax, value); CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
dctx->maxWindowSize = ((size_t)1) << value; dctx->maxWindowSize = ((size_t)1) << value;
return 0; return 0;
@@ -1329,19 +1412,20 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
return 0; return 0;
default:; default:;
} }
return ERROR(parameter_unsupported); RETURN_ERROR(parameter_unsupported);
} }
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset) size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
{ {
if ( (reset == ZSTD_reset_session_only) if ( (reset == ZSTD_reset_session_only)
|| (reset == ZSTD_reset_session_and_parameters) ) { || (reset == ZSTD_reset_session_and_parameters) ) {
(void)ZSTD_initDStream(dctx); dctx->streamStage = zdss_init;
dctx->noForwardProgress = 0;
} }
if ( (reset == ZSTD_reset_parameters) if ( (reset == ZSTD_reset_parameters)
|| (reset == ZSTD_reset_session_and_parameters) ) { || (reset == ZSTD_reset_session_and_parameters) ) {
if (dctx->streamStage != zdss_init) RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
return ERROR(stage_wrong); ZSTD_clearDict(dctx);
dctx->format = ZSTD_f_zstd1; dctx->format = ZSTD_f_zstd1;
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
} }
@@ -1360,7 +1444,8 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2); unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize); unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
size_t const minRBSize = (size_t) neededSize; size_t const minRBSize = (size_t) neededSize;
if ((unsigned long long)minRBSize != neededSize) return ERROR(frameParameter_windowTooLarge); RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
frameParameter_windowTooLarge);
return minRBSize; return minRBSize;
} }
@@ -1378,9 +1463,9 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
ZSTD_frameHeader zfh; ZSTD_frameHeader zfh;
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize); size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
if (ZSTD_isError(err)) return err; if (ZSTD_isError(err)) return err;
if (err>0) return ERROR(srcSize_wrong); RETURN_ERROR_IF(err>0, srcSize_wrong);
if (zfh.windowSize > windowSizeMax) RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
return ERROR(frameParameter_windowTooLarge); frameParameter_windowTooLarge);
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize); return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
} }
@@ -1406,16 +1491,16 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
U32 someMoreWork = 1; U32 someMoreWork = 1;
DEBUGLOG(5, "ZSTD_decompressStream"); DEBUGLOG(5, "ZSTD_decompressStream");
if (input->pos > input->size) { /* forbidden */ RETURN_ERROR_IF(
DEBUGLOG(5, "in: pos: %u vs size: %u", input->pos > input->size,
(U32)input->pos, (U32)input->size); srcSize_wrong,
return ERROR(srcSize_wrong); "forbidden. in: pos: %u vs size: %u",
} (U32)input->pos, (U32)input->size);
if (output->pos > output->size) { /* forbidden */ RETURN_ERROR_IF(
DEBUGLOG(5, "out: pos: %u vs size: %u", output->pos > output->size,
(U32)output->pos, (U32)output->size); dstSize_tooSmall,
return ERROR(dstSize_tooSmall); "forbidden. out: pos: %u vs size: %u",
} (U32)output->pos, (U32)output->size);
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos)); DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
while (someMoreWork) { while (someMoreWork) {
@@ -1423,15 +1508,18 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
{ {
case zdss_init : case zdss_init :
DEBUGLOG(5, "stage zdss_init => transparent reset "); DEBUGLOG(5, "stage zdss_init => transparent reset ");
ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */ zds->streamStage = zdss_loadHeader;
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
zds->legacyVersion = 0;
zds->hostageByte = 0;
/* fall-through */ /* fall-through */
case zdss_loadHeader : case zdss_loadHeader :
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip)); DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
if (zds->legacyVersion) { if (zds->legacyVersion) {
/* legacy support is incompatible with static dctx */ RETURN_ERROR_IF(zds->staticSize, memory_allocation,
if (zds->staticSize) return ERROR(memory_allocation); "legacy support is incompatible with static dctx");
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input); { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
if (hint==0) zds->streamStage = zdss_init; if (hint==0) zds->streamStage = zdss_init;
return hint; return hint;
@@ -1443,12 +1531,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart); U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
if (legacyVersion) { if (legacyVersion) {
const void* const dict = zds->ddict ? ZSTD_DDict_dictContent(zds->ddict) : NULL; ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);
size_t const dictSize = zds->ddict ? ZSTD_DDict_dictSize(zds->ddict) : 0; const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;
size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;
DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion); DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
/* legacy support is incompatible with static dctx */ RETURN_ERROR_IF(zds->staticSize, memory_allocation,
if (zds->staticSize) return ERROR(memory_allocation); "legacy support is incompatible with static dctx");
CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
zds->previousLegacyVersion, legacyVersion, zds->previousLegacyVersion, legacyVersion,
dict, dictSize)); dict, dictSize));
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion; zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
@@ -1482,7 +1571,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart); size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
if (cSize <= (size_t)(iend-istart)) { if (cSize <= (size_t)(iend-istart)) {
/* shortcut : using single-pass mode */ /* shortcut : using single-pass mode */
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds->ddict); size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
if (ZSTD_isError(decompressedSize)) return decompressedSize; if (ZSTD_isError(decompressedSize)) return decompressedSize;
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()") DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
ip = istart + cSize; ip = istart + cSize;
@@ -1495,13 +1584,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
/* Consume header (see ZSTDds_decodeFrameHeader) */ /* Consume header (see ZSTDds_decodeFrameHeader) */
DEBUGLOG(4, "Consume header"); DEBUGLOG(4, "Consume header");
CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict)); FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE); zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
zds->stage = ZSTDds_skipFrame; zds->stage = ZSTDds_skipFrame;
} else { } else {
CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize)); FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
zds->expected = ZSTD_blockHeaderSize; zds->expected = ZSTD_blockHeaderSize;
zds->stage = ZSTDds_decodeBlockHeader; zds->stage = ZSTDds_decodeBlockHeader;
} }
@@ -1511,7 +1600,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
(U32)(zds->fParams.windowSize >>10), (U32)(zds->fParams.windowSize >>10),
(U32)(zds->maxWindowSize >> 10) ); (U32)(zds->maxWindowSize >> 10) );
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN); zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge); RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
frameParameter_windowTooLarge);
/* Adapt buffer sizes to frame header instructions */ /* Adapt buffer sizes to frame header instructions */
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
@@ -1525,14 +1615,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
if (zds->staticSize) { /* static DCtx */ if (zds->staticSize) { /* static DCtx */
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize); DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */ assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx)) RETURN_ERROR_IF(
return ERROR(memory_allocation); bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
memory_allocation);
} else { } else {
ZSTD_free(zds->inBuff, zds->customMem); ZSTD_free(zds->inBuff, zds->customMem);
zds->inBuffSize = 0; zds->inBuffSize = 0;
zds->outBuffSize = 0; zds->outBuffSize = 0;
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem); zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
if (zds->inBuff == NULL) return ERROR(memory_allocation); RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
} }
zds->inBuffSize = neededInBuffSize; zds->inBuffSize = neededInBuffSize;
zds->outBuff = zds->inBuff + zds->inBuffSize; zds->outBuff = zds->inBuff + zds->inBuffSize;
@@ -1574,7 +1665,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
if (isSkipFrame) { if (isSkipFrame) {
loadedSize = MIN(toLoad, (size_t)(iend-ip)); loadedSize = MIN(toLoad, (size_t)(iend-ip));
} else { } else {
if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */ RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
corruption_detected,
"should never happen");
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip); loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
} }
ip += loadedSize; ip += loadedSize;
@@ -1615,7 +1708,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
default: default:
assert(0); /* impossible */ assert(0); /* impossible */
return ERROR(GENERIC); /* some compiler require default to do something */ RETURN_ERROR(GENERIC); /* some compiler require default to do something */
} } } }
/* result */ /* result */
@@ -1624,8 +1717,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
if ((ip==istart) && (op==ostart)) { /* no forward progress */ if ((ip==istart) && (op==ostart)) { /* no forward progress */
zds->noForwardProgress ++; zds->noForwardProgress ++;
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) { if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
if (op==oend) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
if (ip==iend) return ERROR(srcSize_wrong); RETURN_ERROR_IF(ip==iend, srcSize_wrong);
assert(0); assert(0);
} }
} else { } else {
+51 -47
View File
@@ -56,14 +56,15 @@ static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
blockProperties_t* bpPtr) blockProperties_t* bpPtr)
{ {
if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong);
{ U32 const cBlockHeader = MEM_readLE24(src); { U32 const cBlockHeader = MEM_readLE24(src);
U32 const cSize = cBlockHeader >> 3; U32 const cSize = cBlockHeader >> 3;
bpPtr->lastBlock = cBlockHeader & 1; bpPtr->lastBlock = cBlockHeader & 1;
bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3); bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
bpPtr->origSize = cSize; /* only useful for RLE */ bpPtr->origSize = cSize; /* only useful for RLE */
if (bpPtr->blockType == bt_rle) return 1; if (bpPtr->blockType == bt_rle) return 1;
if (bpPtr->blockType == bt_reserved) return ERROR(corruption_detected); RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected);
return cSize; return cSize;
} }
} }
@@ -78,7 +79,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
{ {
if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected); RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected);
{ const BYTE* const istart = (const BYTE*) src; { const BYTE* const istart = (const BYTE*) src;
symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
@@ -86,11 +87,11 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
switch(litEncType) switch(litEncType)
{ {
case set_repeat: case set_repeat:
if (dctx->litEntropy==0) return ERROR(dictionary_corrupted); RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted);
/* fall-through */ /* fall-through */
case set_compressed: case set_compressed:
if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */ RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3");
{ size_t lhSize, litSize, litCSize; { size_t lhSize, litSize, litCSize;
U32 singleStream=0; U32 singleStream=0;
U32 const lhlCode = (istart[0] >> 2) & 3; U32 const lhlCode = (istart[0] >> 2) & 3;
@@ -118,8 +119,8 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
litCSize = (lhc >> 22) + (istart[4] << 10); litCSize = (lhc >> 22) + (istart[4] << 10);
break; break;
} }
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected); RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected);
if (litCSize + lhSize > srcSize) return ERROR(corruption_detected); RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected);
/* prefetch huffman table if cold */ /* prefetch huffman table if cold */
if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) { if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {
@@ -157,7 +158,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
} }
} }
if (HUF_isError(hufSuccess)) return ERROR(corruption_detected); RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected);
dctx->litPtr = dctx->litBuffer; dctx->litPtr = dctx->litBuffer;
dctx->litSize = litSize; dctx->litSize = litSize;
@@ -187,7 +188,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
} }
if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
if (litSize+lhSize > srcSize) return ERROR(corruption_detected); RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected);
memcpy(dctx->litBuffer, istart+lhSize, litSize); memcpy(dctx->litBuffer, istart+lhSize, litSize);
dctx->litPtr = dctx->litBuffer; dctx->litPtr = dctx->litBuffer;
dctx->litSize = litSize; dctx->litSize = litSize;
@@ -216,17 +217,17 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
case 3: case 3:
lhSize = 3; lhSize = 3;
litSize = MEM_readLE24(istart) >> 4; litSize = MEM_readLE24(istart) >> 4;
if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */ RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4");
break; break;
} }
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected); RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected);
memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
dctx->litPtr = dctx->litBuffer; dctx->litPtr = dctx->litBuffer;
dctx->litSize = litSize; dctx->litSize = litSize;
return lhSize+1; return lhSize+1;
} }
default: default:
return ERROR(corruption_detected); /* impossible */ RETURN_ERROR(corruption_detected, "impossible");
} }
} }
} }
@@ -436,8 +437,8 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
switch(type) switch(type)
{ {
case set_rle : case set_rle :
if (!srcSize) return ERROR(srcSize_wrong); RETURN_ERROR_IF(!srcSize, srcSize_wrong);
if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected); RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected);
{ U32 const symbol = *(const BYTE*)src; { U32 const symbol = *(const BYTE*)src;
U32 const baseline = baseValue[symbol]; U32 const baseline = baseValue[symbol];
U32 const nbBits = nbAdditionalBits[symbol]; U32 const nbBits = nbAdditionalBits[symbol];
@@ -449,7 +450,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
*DTablePtr = defaultTable; *DTablePtr = defaultTable;
return 0; return 0;
case set_repeat: case set_repeat:
if (!flagRepeatTable) return ERROR(corruption_detected); RETURN_ERROR_IF(!flagRepeatTable, corruption_detected);
/* prefetch FSE table if used */ /* prefetch FSE table if used */
if (ddictIsCold && (nbSeq > 24 /* heuristic */)) { if (ddictIsCold && (nbSeq > 24 /* heuristic */)) {
const void* const pStart = *DTablePtr; const void* const pStart = *DTablePtr;
@@ -461,15 +462,15 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
{ unsigned tableLog; { unsigned tableLog;
S16 norm[MaxSeq+1]; S16 norm[MaxSeq+1];
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
if (FSE_isError(headerSize)) return ERROR(corruption_detected); RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected);
if (tableLog > maxLog) return ERROR(corruption_detected); RETURN_ERROR_IF(tableLog > maxLog, corruption_detected);
ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog); ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog);
*DTablePtr = DTableSpace; *DTablePtr = DTableSpace;
return headerSize; return headerSize;
} }
default : /* impossible */ default :
assert(0); assert(0);
return ERROR(GENERIC); RETURN_ERROR(GENERIC, "impossible");
} }
} }
@@ -483,28 +484,28 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
DEBUGLOG(5, "ZSTD_decodeSeqHeaders"); DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
/* check */ /* check */
if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong); RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong);
/* SeqHead */ /* SeqHead */
nbSeq = *ip++; nbSeq = *ip++;
if (!nbSeq) { if (!nbSeq) {
*nbSeqPtr=0; *nbSeqPtr=0;
if (srcSize != 1) return ERROR(srcSize_wrong); RETURN_ERROR_IF(srcSize != 1, srcSize_wrong);
return 1; return 1;
} }
if (nbSeq > 0x7F) { if (nbSeq > 0x7F) {
if (nbSeq == 0xFF) { if (nbSeq == 0xFF) {
if (ip+2 > iend) return ERROR(srcSize_wrong); RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong);
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2; nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
} else { } else {
if (ip >= iend) return ERROR(srcSize_wrong); RETURN_ERROR_IF(ip >= iend, srcSize_wrong);
nbSeq = ((nbSeq-0x80)<<8) + *ip++; nbSeq = ((nbSeq-0x80)<<8) + *ip++;
} }
} }
*nbSeqPtr = nbSeq; *nbSeqPtr = nbSeq;
/* FSE table descriptors */ /* FSE table descriptors */
if (ip+4 > iend) return ERROR(srcSize_wrong); /* minimum possible size */ RETURN_ERROR_IF(ip+4 > iend, srcSize_wrong); /* minimum possible size */
{ symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
@@ -517,7 +518,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
LL_base, LL_bits, LL_base, LL_bits,
LL_defaultDTable, dctx->fseEntropy, LL_defaultDTable, dctx->fseEntropy,
dctx->ddictIsCold, nbSeq); dctx->ddictIsCold, nbSeq);
if (ZSTD_isError(llhSize)) return ERROR(corruption_detected); RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected);
ip += llhSize; ip += llhSize;
} }
@@ -527,7 +528,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
OF_base, OF_bits, OF_base, OF_bits,
OF_defaultDTable, dctx->fseEntropy, OF_defaultDTable, dctx->fseEntropy,
dctx->ddictIsCold, nbSeq); dctx->ddictIsCold, nbSeq);
if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected); RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected);
ip += ofhSize; ip += ofhSize;
} }
@@ -537,7 +538,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
ML_base, ML_bits, ML_base, ML_bits,
ML_defaultDTable, dctx->fseEntropy, ML_defaultDTable, dctx->fseEntropy,
dctx->ddictIsCold, nbSeq); dctx->ddictIsCold, nbSeq);
if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected); RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected);
ip += mlhSize; ip += mlhSize;
} }
} }
@@ -590,8 +591,8 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
const BYTE* match = oLitEnd - sequence.offset; const BYTE* match = oLitEnd - sequence.offset;
/* check */ /* check */
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must fit within dstBuffer */ RETURN_ERROR_IF(oMatchEnd>oend, dstSize_tooSmall, "last match must fit within dstBuffer");
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* try to read beyond literal buffer */ RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "try to read beyond literal buffer");
/* copy literals */ /* copy literals */
while (op < oLitEnd) *op++ = *(*litPtr)++; while (op < oLitEnd) *op++ = *(*litPtr)++;
@@ -599,7 +600,7 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
/* copy Match */ /* copy Match */
if (sequence.offset > (size_t)(oLitEnd - base)) { if (sequence.offset > (size_t)(oLitEnd - base)) {
/* offset beyond prefix */ /* offset beyond prefix */
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected); RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - vBase),corruption_detected);
match = dictEnd - (base-match); match = dictEnd - (base-match);
if (match + sequence.matchLength <= dictEnd) { if (match + sequence.matchLength <= dictEnd) {
memmove(oLitEnd, match, sequence.matchLength); memmove(oLitEnd, match, sequence.matchLength);
@@ -631,8 +632,8 @@ size_t ZSTD_execSequence(BYTE* op,
const BYTE* match = oLitEnd - sequence.offset; const BYTE* match = oLitEnd - sequence.offset;
/* check */ /* check */
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ RETURN_ERROR_IF(oMatchEnd>oend, dstSize_tooSmall, "last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend");
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */ RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "over-read beyond lit buffer");
if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd); if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
/* copy Literals */ /* copy Literals */
@@ -645,8 +646,7 @@ size_t ZSTD_execSequence(BYTE* op,
/* copy Match */ /* copy Match */
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
/* offset beyond prefix -> go into extDict */ /* offset beyond prefix -> go into extDict */
if (sequence.offset > (size_t)(oLitEnd - virtualStart)) RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected);
return ERROR(corruption_detected);
match = dictEnd + (match - prefixStart); match = dictEnd + (match - prefixStart);
if (match + sequence.matchLength <= dictEnd) { if (match + sequence.matchLength <= dictEnd) {
memmove(oLitEnd, match, sequence.matchLength); memmove(oLitEnd, match, sequence.matchLength);
@@ -712,8 +712,8 @@ size_t ZSTD_execSequenceLong(BYTE* op,
const BYTE* match = sequence.match; const BYTE* match = sequence.match;
/* check */ /* check */
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ RETURN_ERROR_IF(oMatchEnd > oend, dstSize_tooSmall, "last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend");
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */ RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "over-read beyond lit buffer");
if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd); if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
/* copy Literals */ /* copy Literals */
@@ -726,7 +726,7 @@ size_t ZSTD_execSequenceLong(BYTE* op,
/* copy Match */ /* copy Match */
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
/* offset beyond prefix */ /* offset beyond prefix */
if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected); RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - dictStart), corruption_detected);
if (match + sequence.matchLength <= dictEnd) { if (match + sequence.matchLength <= dictEnd) {
memmove(oLitEnd, match, sequence.matchLength); memmove(oLitEnd, match, sequence.matchLength);
return sequenceLength; return sequenceLength;
@@ -801,7 +801,7 @@ ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD)
/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum /* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
* offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1) * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
* bits before reloading. This value is the maximum number of bytes we read * bits before reloading. This value is the maximum number of bytes we read
* after reloading when we are decoding long offets. * after reloading when we are decoding long offsets.
*/ */
#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \ #define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
(ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \ (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
@@ -911,7 +911,9 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
seqState_t seqState; seqState_t seqState;
dctx->fseEntropy = 1; dctx->fseEntropy = 1;
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; } { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected); RETURN_ERROR_IF(
ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
corruption_detected);
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
@@ -927,14 +929,14 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
/* check if reached exact end */ /* check if reached exact end */
DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq); DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
if (nbSeq) return ERROR(corruption_detected); RETURN_ERROR_IF(nbSeq, corruption_detected);
/* save reps for next block */ /* save reps for next block */
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); } { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
} }
/* last literal segment */ /* last literal segment */
{ size_t const lastLLSize = litEnd - litPtr; { size_t const lastLLSize = litEnd - litPtr;
if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall);
memcpy(op, litPtr, lastLLSize); memcpy(op, litPtr, lastLLSize);
op += lastLLSize; op += lastLLSize;
} }
@@ -1066,7 +1068,9 @@ ZSTD_decompressSequencesLong_body(
seqState.pos = (size_t)(op-prefixStart); seqState.pos = (size_t)(op-prefixStart);
seqState.dictEnd = dictEnd; seqState.dictEnd = dictEnd;
assert(iend >= ip); assert(iend >= ip);
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected); RETURN_ERROR_IF(
ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
corruption_detected);
ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
@@ -1076,7 +1080,7 @@ ZSTD_decompressSequencesLong_body(
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset); sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */ PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
} }
if (seqNb<seqAdvance) return ERROR(corruption_detected); RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected);
/* decode and decompress */ /* decode and decompress */
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) { for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
@@ -1087,7 +1091,7 @@ ZSTD_decompressSequencesLong_body(
sequences[seqNb & STORED_SEQS_MASK] = sequence; sequences[seqNb & STORED_SEQS_MASK] = sequence;
op += oneSeqSize; op += oneSeqSize;
} }
if (seqNb<nbSeq) return ERROR(corruption_detected); RETURN_ERROR_IF(seqNb<nbSeq, corruption_detected);
/* finish queue */ /* finish queue */
seqNb -= seqAdvance; seqNb -= seqAdvance;
@@ -1103,7 +1107,7 @@ ZSTD_decompressSequencesLong_body(
/* last literal segment */ /* last literal segment */
{ size_t const lastLLSize = litEnd - litPtr; { size_t const lastLLSize = litEnd - litPtr;
if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall); RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall);
memcpy(op, litPtr, lastLLSize); memcpy(op, litPtr, lastLLSize);
op += lastLLSize; op += lastLLSize;
} }
@@ -1176,7 +1180,7 @@ ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
/* ZSTD_decompressSequencesLong() : /* ZSTD_decompressSequencesLong() :
* decompression function triggered when a minimum share of offsets is considered "long", * decompression function triggered when a minimum share of offsets is considered "long",
* aka out of cache. * aka out of cache.
* note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes mearning "farther than memory cache distance". * note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes meaning "farther than memory cache distance".
* This function will try to mitigate main memory latency through the use of prefetching */ * This function will try to mitigate main memory latency through the use of prefetching */
static size_t static size_t
ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx, ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
@@ -1240,7 +1244,7 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN)))); ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN))));
DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize); DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong);
/* Decode literals section */ /* Decode literals section */
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize); { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
@@ -89,6 +89,12 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
typedef enum { zdss_init=0, zdss_loadHeader, typedef enum { zdss_init=0, zdss_loadHeader,
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage; zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
typedef enum {
ZSTD_use_indefinitely = -1, /* Use the dictionary indefinitely */
ZSTD_dont_use = 0, /* Do not use the dictionary (if one exists free it) */
ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
} ZSTD_dictUses_e;
struct ZSTD_DCtx_s struct ZSTD_DCtx_s
{ {
const ZSTD_seqSymbol* LLTptr; const ZSTD_seqSymbol* LLTptr;
@@ -123,6 +129,7 @@ struct ZSTD_DCtx_s
const ZSTD_DDict* ddict; /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */ const ZSTD_DDict* ddict; /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */
U32 dictID; U32 dictID;
int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */ int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
ZSTD_dictUses_e dictUses;
/* streaming */ /* streaming */
ZSTD_dStreamStage streamStage; ZSTD_dStreamStage streamStage;
+58 -13
View File
@@ -391,7 +391,7 @@ static void COVER_group(COVER_ctx_t *ctx, const void *group,
* *
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1}) * Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
* *
* Once the dmer d is in the dictionay we set F(d) = 0. * Once the dmer d is in the dictionary we set F(d) = 0.
*/ */
static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs, static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs,
COVER_map_t *activeDmers, U32 begin, COVER_map_t *activeDmers, U32 begin,
@@ -435,7 +435,7 @@ static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs,
U32 *delDmerOcc = COVER_map_at(activeDmers, delDmer); U32 *delDmerOcc = COVER_map_at(activeDmers, delDmer);
activeSegment.begin += 1; activeSegment.begin += 1;
*delDmerOcc -= 1; *delDmerOcc -= 1;
/* If this is the last occurence of the dmer, subtract its score */ /* If this is the last occurrence of the dmer, subtract its score */
if (*delDmerOcc == 0) { if (*delDmerOcc == 0) {
COVER_map_remove(activeDmers, delDmer); COVER_map_remove(activeDmers, delDmer);
activeSegment.score -= freqs[delDmer]; activeSegment.score -= freqs[delDmer];
@@ -627,6 +627,39 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
return 1; return 1;
} }
void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel)
{
const double ratio = (double)nbDmers / maxDictSize;
if (ratio >= 10) {
return;
}
LOCALDISPLAYLEVEL(displayLevel, 1,
"WARNING: The maximum dictionary size %u is too large "
"compared to the source size %u! "
"size(source)/size(dictionary) = %f, but it should be >= "
"10! This may lead to a subpar dictionary! We recommend "
"training on sources at least 10x, and up to 100x the "
"size of the dictionary!\n", (U32)maxDictSize,
(U32)nbDmers, ratio);
}
COVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize,
U32 nbDmers, U32 k, U32 passes)
{
const U32 minEpochSize = k * 10;
COVER_epoch_info_t epochs;
epochs.num = MAX(1, maxDictSize / k / passes);
epochs.size = nbDmers / epochs.num;
if (epochs.size >= minEpochSize) {
assert(epochs.size * epochs.num <= nbDmers);
return epochs;
}
epochs.size = MIN(minEpochSize, nbDmers);
epochs.num = nbDmers / epochs.size;
assert(epochs.size * epochs.num <= nbDmers);
return epochs;
}
/** /**
* Given the prepared context build the dictionary. * Given the prepared context build the dictionary.
*/ */
@@ -636,28 +669,34 @@ static size_t COVER_buildDictionary(const COVER_ctx_t *ctx, U32 *freqs,
ZDICT_cover_params_t parameters) { ZDICT_cover_params_t parameters) {
BYTE *const dict = (BYTE *)dictBuffer; BYTE *const dict = (BYTE *)dictBuffer;
size_t tail = dictBufferCapacity; size_t tail = dictBufferCapacity;
/* Divide the data up into epochs of equal size. /* Divide the data into epochs. We will select one segment from each epoch. */
* We will select at least one segment from each epoch. const COVER_epoch_info_t epochs = COVER_computeEpochs(
*/ (U32)dictBufferCapacity, (U32)ctx->suffixSize, parameters.k, 4);
const unsigned epochs = MAX(1, (U32)(dictBufferCapacity / parameters.k / 4)); const size_t maxZeroScoreRun = MAX(10, MIN(100, epochs.num >> 3));
const unsigned epochSize = (U32)(ctx->suffixSize / epochs); size_t zeroScoreRun = 0;
size_t epoch; size_t epoch;
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n", DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
epochs, epochSize); (U32)epochs.num, (U32)epochs.size);
/* Loop through the epochs until there are no more segments or the dictionary /* Loop through the epochs until there are no more segments or the dictionary
* is full. * is full.
*/ */
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs) { for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) {
const U32 epochBegin = (U32)(epoch * epochSize); const U32 epochBegin = (U32)(epoch * epochs.size);
const U32 epochEnd = epochBegin + epochSize; const U32 epochEnd = epochBegin + epochs.size;
size_t segmentSize; size_t segmentSize;
/* Select a segment */ /* Select a segment */
COVER_segment_t segment = COVER_selectSegment( COVER_segment_t segment = COVER_selectSegment(
ctx, freqs, activeDmers, epochBegin, epochEnd, parameters); ctx, freqs, activeDmers, epochBegin, epochEnd, parameters);
/* If the segment covers no dmers, then we are out of content */ /* If the segment covers no dmers, then we are out of content.
* There may be new content in other epochs, for continue for some time.
*/
if (segment.score == 0) { if (segment.score == 0) {
break; if (++zeroScoreRun >= maxZeroScoreRun) {
break;
}
continue;
} }
zeroScoreRun = 0;
/* Trim the segment if necessary and if it is too small then we are done */ /* Trim the segment if necessary and if it is too small then we are done */
segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail); segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);
if (segmentSize < parameters.d) { if (segmentSize < parameters.d) {
@@ -706,6 +745,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_cover(
parameters.d, parameters.splitPoint)) { parameters.d, parameters.splitPoint)) {
return ERROR(GENERIC); return ERROR(GENERIC);
} }
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, g_displayLevel);
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) { if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n"); DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
COVER_ctx_destroy(&ctx); COVER_ctx_destroy(&ctx);
@@ -977,6 +1017,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
unsigned k; unsigned k;
COVER_best_t best; COVER_best_t best;
POOL_ctx *pool = NULL; POOL_ctx *pool = NULL;
int warned = 0;
/* Checks */ /* Checks */
if (splitPoint <= 0 || splitPoint > 1) { if (splitPoint <= 0 || splitPoint > 1) {
@@ -1019,6 +1060,10 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
POOL_free(pool); POOL_free(pool);
return ERROR(GENERIC); return ERROR(GENERIC);
} }
if (!warned) {
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, displayLevel);
warned = 1;
}
/* Loop through k reusing the same context */ /* Loop through k reusing the same context */
for (k = kMinK; k <= kMaxK; k += kStepSize) { for (k = kMinK; k <= kMaxK; k += kStepSize) {
/* Prepare the arguments */ /* Prepare the arguments */
+29
View File
@@ -38,6 +38,35 @@ typedef struct {
U32 score; U32 score;
} COVER_segment_t; } COVER_segment_t;
/**
*Number of epochs and size of each epoch.
*/
typedef struct {
U32 num;
U32 size;
} COVER_epoch_info_t;
/**
* Computes the number of epochs and the size of each epoch.
* We will make sure that each epoch gets at least 10 * k bytes.
*
* The COVER algorithms divide the data up into epochs of equal size and
* select one segment from each epoch.
*
* @param maxDictSize The maximum allowed dictionary size.
* @param nbDmers The number of dmers we are training on.
* @param k The parameter k (segment size).
* @param passes The target number of passes over the dmer corpus.
* More passes means a better dictionary.
*/
COVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize, U32 nbDmers,
U32 k, U32 passes);
/**
* Warns the user when their corpus is too small.
*/
void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel);
/** /**
* Checks total compressed size of a dictionary * Checks total compressed size of a dictionary
*/ */
+25 -13
View File
@@ -132,7 +132,7 @@ typedef struct {
* *
* Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1}) * Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})
* *
* Once the dmer with hash value d is in the dictionay we set F(d) = 0. * Once the dmer with hash value d is in the dictionary we set F(d) = 0.
*/ */
static COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx, static COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
U32 *freqs, U32 begin, U32 end, U32 *freqs, U32 begin, U32 end,
@@ -161,7 +161,7 @@ static COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,
/* Get hash value of current dmer */ /* Get hash value of current dmer */
const size_t idx = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, f, d); const size_t idx = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, f, d);
/* Add frequency of this index to score if this is the first occurence of index in active segment */ /* Add frequency of this index to score if this is the first occurrence of index in active segment */
if (segmentFreqs[idx] == 0) { if (segmentFreqs[idx] == 0) {
activeSegment.score += freqs[idx]; activeSegment.score += freqs[idx];
} }
@@ -386,29 +386,35 @@ FASTCOVER_buildDictionary(const FASTCOVER_ctx_t* ctx,
{ {
BYTE *const dict = (BYTE *)dictBuffer; BYTE *const dict = (BYTE *)dictBuffer;
size_t tail = dictBufferCapacity; size_t tail = dictBufferCapacity;
/* Divide the data up into epochs of equal size. /* Divide the data into epochs. We will select one segment from each epoch. */
* We will select at least one segment from each epoch. const COVER_epoch_info_t epochs = COVER_computeEpochs(
*/ (U32)dictBufferCapacity, (U32)ctx->nbDmers, parameters.k, 1);
const unsigned epochs = MAX(1, (U32)(dictBufferCapacity / parameters.k)); const size_t maxZeroScoreRun = 10;
const unsigned epochSize = (U32)(ctx->nbDmers / epochs); size_t zeroScoreRun = 0;
size_t epoch; size_t epoch;
DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n", DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n",
epochs, epochSize); (U32)epochs.num, (U32)epochs.size);
/* Loop through the epochs until there are no more segments or the dictionary /* Loop through the epochs until there are no more segments or the dictionary
* is full. * is full.
*/ */
for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs) { for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) {
const U32 epochBegin = (U32)(epoch * epochSize); const U32 epochBegin = (U32)(epoch * epochs.size);
const U32 epochEnd = epochBegin + epochSize; const U32 epochEnd = epochBegin + epochs.size;
size_t segmentSize; size_t segmentSize;
/* Select a segment */ /* Select a segment */
COVER_segment_t segment = FASTCOVER_selectSegment( COVER_segment_t segment = FASTCOVER_selectSegment(
ctx, freqs, epochBegin, epochEnd, parameters, segmentFreqs); ctx, freqs, epochBegin, epochEnd, parameters, segmentFreqs);
/* If the segment covers no dmers, then we are out of content */ /* If the segment covers no dmers, then we are out of content.
* There may be new content in other epochs, for continue for some time.
*/
if (segment.score == 0) { if (segment.score == 0) {
break; if (++zeroScoreRun >= maxZeroScoreRun) {
break;
}
continue;
} }
zeroScoreRun = 0;
/* Trim the segment if necessary and if it is too small then we are done */ /* Trim the segment if necessary and if it is too small then we are done */
segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail); segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);
@@ -564,6 +570,7 @@ ZDICT_trainFromBuffer_fastCover(void* dictBuffer, size_t dictBufferCapacity,
DISPLAYLEVEL(1, "Failed to initialize context\n"); DISPLAYLEVEL(1, "Failed to initialize context\n");
return ERROR(GENERIC); return ERROR(GENERIC);
} }
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, g_displayLevel);
/* Build the dictionary */ /* Build the dictionary */
DISPLAYLEVEL(2, "Building dictionary\n"); DISPLAYLEVEL(2, "Building dictionary\n");
{ {
@@ -616,6 +623,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
unsigned k; unsigned k;
COVER_best_t best; COVER_best_t best;
POOL_ctx *pool = NULL; POOL_ctx *pool = NULL;
int warned = 0;
/* Checks */ /* Checks */
if (splitPoint <= 0 || splitPoint > 1) { if (splitPoint <= 0 || splitPoint > 1) {
LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect splitPoint\n"); LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect splitPoint\n");
@@ -664,6 +672,10 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
POOL_free(pool); POOL_free(pool);
return ERROR(GENERIC); return ERROR(GENERIC);
} }
if (!warned) {
COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, displayLevel);
warned = 1;
}
/* Loop through k reusing the same context */ /* Loop through k reusing the same context */
for (k = kMinK; k <= kMaxK; k += kStepSize) { for (k = kMinK; k <= kMaxK; k += kStepSize) {
/* Prepare the arguments */ /* Prepare the arguments */
+18 -8
View File
@@ -46,7 +46,12 @@ extern "C" {
* The resulting dictionary will be saved into `dictBuffer`. * The resulting dictionary will be saved into `dictBuffer`.
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
* or an error code, which can be tested with ZDICT_isError(). * or an error code, which can be tested with ZDICT_isError().
* Note: ZDICT_trainFromBuffer() requires about 9 bytes of memory for each input byte. * Note: Dictionary training will fail if there are not enough samples to construct a
* dictionary, or if most of the samples are too small (< 8 bytes being the lower limit).
* If dictionary training fails, you should use zstd without a dictionary, as the dictionary
* would've been ineffective anyways. If you believe your samples would benefit from a dictionary
* please open an issue with details, and we can look into it.
* Note: ZDICT_trainFromBuffer()'s memory usage is about 6 MB.
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB. * Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`. * It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
* In general, it's recommended to provide a few thousands samples, though this can vary a lot. * In general, it's recommended to provide a few thousands samples, though this can vary a lot.
@@ -110,6 +115,7 @@ typedef struct {
* The resulting dictionary will be saved into `dictBuffer`. * The resulting dictionary will be saved into `dictBuffer`.
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
* or an error code, which can be tested with ZDICT_isError(). * or an error code, which can be tested with ZDICT_isError().
* See ZDICT_trainFromBuffer() for details on failure modes.
* Note: ZDICT_trainFromBuffer_cover() requires about 9 bytes of memory for each input byte. * Note: ZDICT_trainFromBuffer_cover() requires about 9 bytes of memory for each input byte.
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB. * Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`. * It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
@@ -133,8 +139,9 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_cover(
* If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [50, 2000]. * If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [50, 2000].
* *
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
* or an error code, which can be tested with ZDICT_isError(). * or an error code, which can be tested with ZDICT_isError().
* On success `*parameters` contains the parameters selected. * On success `*parameters` contains the parameters selected.
* See ZDICT_trainFromBuffer() for details on failure modes.
* Note: ZDICT_optimizeTrainFromBuffer_cover() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread. * Note: ZDICT_optimizeTrainFromBuffer_cover() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread.
*/ */
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover( ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
@@ -151,7 +158,8 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
* The resulting dictionary will be saved into `dictBuffer`. * The resulting dictionary will be saved into `dictBuffer`.
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
* or an error code, which can be tested with ZDICT_isError(). * or an error code, which can be tested with ZDICT_isError().
* Note: ZDICT_trainFromBuffer_fastCover() requires about 1 bytes of memory for each input byte and additionally another 6 * 2^f bytes of memory . * See ZDICT_trainFromBuffer() for details on failure modes.
* Note: ZDICT_trainFromBuffer_fastCover() requires 6 * 2^f bytes of memory.
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB. * Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`. * It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
* In general, it's recommended to provide a few thousands samples, though this can vary a lot. * In general, it's recommended to provide a few thousands samples, though this can vary a lot.
@@ -175,9 +183,10 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_fastCover(void *dictBuffer,
* If accel is zero, default value of 1 is used. * If accel is zero, default value of 1 is used.
* *
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
* or an error code, which can be tested with ZDICT_isError(). * or an error code, which can be tested with ZDICT_isError().
* On success `*parameters` contains the parameters selected. * On success `*parameters` contains the parameters selected.
* Note: ZDICT_optimizeTrainFromBuffer_fastCover() requires about 1 byte of memory for each input byte and additionally another 6 * 2^f bytes of memory for each thread. * See ZDICT_trainFromBuffer() for details on failure modes.
* Note: ZDICT_optimizeTrainFromBuffer_fastCover() requires about 6 * 2^f bytes of memory for each thread.
*/ */
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer, ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer,
size_t dictBufferCapacity, const void* samplesBuffer, size_t dictBufferCapacity, const void* samplesBuffer,
@@ -195,7 +204,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer,
* maxDictSize must be >= dictContentSize, and must be >= ZDICT_DICTSIZE_MIN bytes. * maxDictSize must be >= dictContentSize, and must be >= ZDICT_DICTSIZE_MIN bytes.
* *
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`), * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`),
* or an error code, which can be tested by ZDICT_isError(). * or an error code, which can be tested by ZDICT_isError().
* Note: ZDICT_finalizeDictionary() will push notifications into stderr if instructed to, using notificationLevel>0. * Note: ZDICT_finalizeDictionary() will push notifications into stderr if instructed to, using notificationLevel>0.
* Note 2: dictBuffer and dictContent can overlap * Note 2: dictBuffer and dictContent can overlap
*/ */
@@ -219,6 +228,7 @@ typedef struct {
* `parameters` is optional and can be provided with values set to 0 to mean "default". * `parameters` is optional and can be provided with values set to 0 to mean "default".
* @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
* or an error code, which can be tested with ZDICT_isError(). * or an error code, which can be tested with ZDICT_isError().
* See ZDICT_trainFromBuffer() for details on failure modes.
* Tips: In general, a reasonable dictionary has a size of ~ 100 KB. * Tips: In general, a reasonable dictionary has a size of ~ 100 KB.
* It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`. * It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.
* In general, it's recommended to provide a few thousands samples, though this can vary a lot. * In general, it's recommended to provide a few thousands samples, though this can vary a lot.
+3 -2
View File
@@ -6,14 +6,15 @@ COPY programs\datagen.h bin\example\
COPY programs\util.h bin\example\ COPY programs\util.h bin\example\
COPY programs\platform.h bin\example\ COPY programs\platform.h bin\example\
COPY lib\common\mem.h bin\example\ COPY lib\common\mem.h bin\example\
COPY lib\common\zstd_errors.h bin\example\
COPY lib\common\zstd_internal.h bin\example\ COPY lib\common\zstd_internal.h bin\example\
COPY lib\common\error_private.h bin\example\ COPY lib\common\error_private.h bin\example\
COPY lib\common\xxhash.h bin\example\ COPY lib\common\xxhash.h bin\example\
COPY lib\zstd.h bin\include\
COPY lib\libzstd.a bin\static\libzstd_static.lib COPY lib\libzstd.a bin\static\libzstd_static.lib
COPY lib\dll\libzstd.* bin\dll\ COPY lib\dll\libzstd.* bin\dll\
COPY lib\dll\example\Makefile bin\example\ COPY lib\dll\example\Makefile bin\example\
COPY lib\dll\example\fullbench-dll.* bin\example\ COPY lib\dll\example\fullbench-dll.* bin\example\
COPY lib\dll\example\README.md bin\ COPY lib\dll\example\README.md bin\
COPY lib\zstd.h bin\include\
COPY lib\common\zstd_errors.h bin\include\
COPY lib\dictBuilder\zdict.h bin\include\
COPY programs\zstd.exe bin\zstd.exe COPY programs\zstd.exe bin\zstd.exe
-87
View File
@@ -1,87 +0,0 @@
LIBRARY libzstd.dll
EXPORTS
ZDICT_getDictID
ZDICT_getErrorName
ZDICT_isError
ZDICT_trainFromBuffer
ZSTD_CStreamInSize
ZSTD_CStreamOutSize
ZSTD_DStreamInSize
ZSTD_DStreamOutSize
ZSTD_adjustCParams
ZSTD_checkCParams
ZSTD_compress
ZSTD_compressBegin
ZSTD_compressBegin_advanced
ZSTD_compressBegin_usingDict
ZSTD_compressBlock
ZSTD_compressBound
ZSTD_compressCCtx
ZSTD_compressContinue
ZSTD_compressEnd
ZSTD_compressStream
ZSTD_compress_advanced
ZSTD_compress_usingCDict
ZSTD_compress_usingDict
ZSTD_copyCCtx
ZSTD_copyDCtx
ZSTD_createCCtx
ZSTD_createCCtx_advanced
ZSTD_createCDict
ZSTD_createCDict_advanced
ZSTD_createCStream
ZSTD_createCStream_advanced
ZSTD_createDCtx
ZSTD_createDCtx_advanced
ZSTD_createDDict
ZSTD_createDStream
ZSTD_createDStream_advanced
ZSTD_decompress
ZSTD_decompressBegin
ZSTD_decompressBegin_usingDict
ZSTD_decompressBlock
ZSTD_decompressContinue
ZSTD_decompressDCtx
ZSTD_decompressStream
ZSTD_decompress_usingDDict
ZSTD_decompress_usingDict
ZSTD_endStream
ZSTD_estimateCCtxSize
ZSTD_estimateDCtxSize
ZSTD_flushStream
ZSTD_freeCCtx
ZSTD_freeCDict
ZSTD_freeCStream
ZSTD_freeDCtx
ZSTD_freeDDict
ZSTD_freeDStream
ZSTD_getBlockSizeMax
ZSTD_getCParams
ZSTD_getDecompressedSize
ZSTD_findDecompressedSize
ZSTD_getFrameContentSize
ZSTD_getErrorName
ZSTD_getFrameParams
ZSTD_getParams
ZSTD_initCStream
ZSTD_initCStream_advanced
ZSTD_initCStream_usingCDict
ZSTD_initCStream_usingDict
ZSTD_initDStream
ZSTD_initDStream_usingDDict
ZSTD_initDStream_usingDict
ZSTD_insertBlock
ZSTD_isError
ZSTD_isFrame
ZSTD_maxCLevel
ZSTD_nextInputType
ZSTD_nextSrcSizeToDecompress
ZSTD_resetCStream
ZSTD_resetDStream
ZSTD_sizeof_CCtx
ZSTD_sizeof_CDict
ZSTD_sizeof_CStream
ZSTD_sizeof_DCtx
ZSTD_sizeof_DDict
ZSTD_sizeof_DStream
ZSTD_versionNumber
+42 -12
View File
@@ -20,7 +20,7 @@ extern "C" {
***************************************/ ***************************************/
#include "mem.h" /* MEM_STATIC */ #include "mem.h" /* MEM_STATIC */
#include "error_private.h" /* ERROR */ #include "error_private.h" /* ERROR */
#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer */ #include "zstd_internal.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */
#if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0) #if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0)
# undef ZSTD_LEGACY_SUPPORT # undef ZSTD_LEGACY_SUPPORT
@@ -178,43 +178,73 @@ MEM_STATIC size_t ZSTD_decompressLegacy(
} }
} }
MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize)
size_t compressedSize)
{ {
U32 const version = ZSTD_isLegacy(src, compressedSize); ZSTD_frameSizeInfo frameSizeInfo;
U32 const version = ZSTD_isLegacy(src, srcSize);
switch(version) switch(version)
{ {
#if (ZSTD_LEGACY_SUPPORT <= 1) #if (ZSTD_LEGACY_SUPPORT <= 1)
case 1 : case 1 :
return ZSTDv01_findFrameCompressedSize(src, compressedSize); ZSTDv01_findFrameSizeInfoLegacy(src, srcSize,
&frameSizeInfo.compressedSize,
&frameSizeInfo.decompressedBound);
break;
#endif #endif
#if (ZSTD_LEGACY_SUPPORT <= 2) #if (ZSTD_LEGACY_SUPPORT <= 2)
case 2 : case 2 :
return ZSTDv02_findFrameCompressedSize(src, compressedSize); ZSTDv02_findFrameSizeInfoLegacy(src, srcSize,
&frameSizeInfo.compressedSize,
&frameSizeInfo.decompressedBound);
break;
#endif #endif
#if (ZSTD_LEGACY_SUPPORT <= 3) #if (ZSTD_LEGACY_SUPPORT <= 3)
case 3 : case 3 :
return ZSTDv03_findFrameCompressedSize(src, compressedSize); ZSTDv03_findFrameSizeInfoLegacy(src, srcSize,
&frameSizeInfo.compressedSize,
&frameSizeInfo.decompressedBound);
break;
#endif #endif
#if (ZSTD_LEGACY_SUPPORT <= 4) #if (ZSTD_LEGACY_SUPPORT <= 4)
case 4 : case 4 :
return ZSTDv04_findFrameCompressedSize(src, compressedSize); ZSTDv04_findFrameSizeInfoLegacy(src, srcSize,
&frameSizeInfo.compressedSize,
&frameSizeInfo.decompressedBound);
break;
#endif #endif
#if (ZSTD_LEGACY_SUPPORT <= 5) #if (ZSTD_LEGACY_SUPPORT <= 5)
case 5 : case 5 :
return ZSTDv05_findFrameCompressedSize(src, compressedSize); ZSTDv05_findFrameSizeInfoLegacy(src, srcSize,
&frameSizeInfo.compressedSize,
&frameSizeInfo.decompressedBound);
break;
#endif #endif
#if (ZSTD_LEGACY_SUPPORT <= 6) #if (ZSTD_LEGACY_SUPPORT <= 6)
case 6 : case 6 :
return ZSTDv06_findFrameCompressedSize(src, compressedSize); ZSTDv06_findFrameSizeInfoLegacy(src, srcSize,
&frameSizeInfo.compressedSize,
&frameSizeInfo.decompressedBound);
break;
#endif #endif
#if (ZSTD_LEGACY_SUPPORT <= 7) #if (ZSTD_LEGACY_SUPPORT <= 7)
case 7 : case 7 :
return ZSTDv07_findFrameCompressedSize(src, compressedSize); ZSTDv07_findFrameSizeInfoLegacy(src, srcSize,
&frameSizeInfo.compressedSize,
&frameSizeInfo.decompressedBound);
break;
#endif #endif
default : default :
return ERROR(prefix_unknown); frameSizeInfo.compressedSize = ERROR(prefix_unknown);
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
break;
} }
return frameSizeInfo;
}
MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize)
{
ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize);
return frameSizeInfo.compressedSize;
} }
MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version) MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)
+32 -7
View File
@@ -1336,6 +1336,8 @@ static const U32 ZSTD_magicNumber = 0xFD2FB51E; /* 3rd version : seqNb header
#define LITERAL_NOENTROPY 63 #define LITERAL_NOENTROPY 63
#define COMMAND_NOENTROPY 7 /* to remove */ #define COMMAND_NOENTROPY 7 /* to remove */
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
static const size_t ZSTD_blockHeaderSize = 3; static const size_t ZSTD_blockHeaderSize = 3;
static const size_t ZSTD_frameHeaderSize = 4; static const size_t ZSTD_frameHeaderSize = 4;
@@ -1757,7 +1759,7 @@ static size_t ZSTD_execSequence(BYTE* op,
BYTE* const base, BYTE* const oend) BYTE* const base, BYTE* const oend)
{ {
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */ static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */ static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
const BYTE* const ostart = op; const BYTE* const ostart = op;
const size_t litLength = sequence.litLength; const size_t litLength = sequence.litLength;
BYTE* const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */ BYTE* const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
@@ -1999,36 +2001,59 @@ size_t ZSTDv01_decompress(void* dst, size_t maxDstSize, const void* src, size_t
return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize); return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
} }
size_t ZSTDv01_findFrameCompressedSize(const void* src, size_t srcSize) /* ZSTD_errorFrameSizeInfoLegacy() :
assumes `cSize` and `dBound` are _not_ NULL */
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
{
*cSize = ret;
*dBound = ZSTD_CONTENTSIZE_ERROR;
}
void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
{ {
const BYTE* ip = (const BYTE*)src; const BYTE* ip = (const BYTE*)src;
size_t remainingSize = srcSize; size_t remainingSize = srcSize;
size_t nbBlocks = 0;
U32 magicNumber; U32 magicNumber;
blockProperties_t blockProperties; blockProperties_t blockProperties;
/* Frame Header */ /* Frame Header */
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
magicNumber = ZSTD_readBE32(src); magicNumber = ZSTD_readBE32(src);
if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown); if (magicNumber != ZSTD_magicNumber) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
return;
}
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize; ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
/* Loop on each block */ /* Loop on each block */
while (1) while (1)
{ {
size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties); size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTDv01_isError(blockSize)) return blockSize; if (ZSTDv01_isError(blockSize)) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, blockSize);
return;
}
ip += ZSTD_blockHeaderSize; ip += ZSTD_blockHeaderSize;
remainingSize -= ZSTD_blockHeaderSize; remainingSize -= ZSTD_blockHeaderSize;
if (blockSize > remainingSize) return ERROR(srcSize_wrong); if (blockSize > remainingSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
if (blockSize == 0) break; /* bt_end */ if (blockSize == 0) break; /* bt_end */
ip += blockSize; ip += blockSize;
remainingSize -= blockSize; remainingSize -= blockSize;
nbBlocks++;
} }
return ip - (const BYTE*)src; *cSize = ip - (const BYTE*)src;
*dBound = nbBlocks * BLOCKSIZE;
} }
/******************************* /*******************************
+12 -7
View File
@@ -35,13 +35,18 @@ ZSTDv01_decompress() : decompress ZSTD frames compliant with v0.1.x format
size_t ZSTDv01_decompress( void* dst, size_t maxOriginalSize, size_t ZSTDv01_decompress( void* dst, size_t maxOriginalSize,
const void* src, size_t compressedSize); const void* src, size_t compressedSize);
/** /**
ZSTDv01_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.1.x format ZSTDv01_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.1.x format
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
return : the number of bytes that would be read to decompress this frame cSize (output parameter) : the number of bytes that would be read to decompress this frame
or an errorCode if it fails (which can be tested using ZSTDv01_isError()) or an error code if it fails (which can be tested using ZSTDv01_isError())
*/ dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
size_t ZSTDv01_findFrameCompressedSize(const void* src, size_t compressedSize); or ZSTD_CONTENTSIZE_ERROR if an error occurs
note : assumes `cSize` and `dBound` are _not_ NULL.
*/
void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
size_t* cSize, unsigned long long* dBound);
/** /**
ZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error ZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error
+31 -12
View File
@@ -2728,6 +2728,8 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
#define LITERAL_NOENTROPY 63 #define LITERAL_NOENTROPY 63
#define COMMAND_NOENTROPY 7 /* to remove */ #define COMMAND_NOENTROPY 7 /* to remove */
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
static const size_t ZSTD_blockHeaderSize = 3; static const size_t ZSTD_blockHeaderSize = 3;
static const size_t ZSTD_frameHeaderSize = 4; static const size_t ZSTD_frameHeaderSize = 4;
@@ -3096,7 +3098,7 @@ static size_t ZSTD_execSequence(BYTE* op,
BYTE* const base, BYTE* const oend) BYTE* const base, BYTE* const oend)
{ {
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */ static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */ static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
const BYTE* const ostart = op; const BYTE* const ostart = op;
BYTE* const oLitEnd = op + sequence.litLength; BYTE* const oLitEnd = op + sequence.litLength;
BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */ BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
@@ -3312,37 +3314,59 @@ static size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, siz
return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize); return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
} }
static size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) /* ZSTD_errorFrameSizeInfoLegacy() :
assumes `cSize` and `dBound` are _not_ NULL */
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
{ {
*cSize = ret;
*dBound = ZSTD_CONTENTSIZE_ERROR;
}
void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
{
const BYTE* ip = (const BYTE*)src; const BYTE* ip = (const BYTE*)src;
size_t remainingSize = srcSize; size_t remainingSize = srcSize;
size_t nbBlocks = 0;
U32 magicNumber; U32 magicNumber;
blockProperties_t blockProperties; blockProperties_t blockProperties;
/* Frame Header */ /* Frame Header */
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
magicNumber = MEM_readLE32(src); magicNumber = MEM_readLE32(src);
if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown); if (magicNumber != ZSTD_magicNumber) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
return;
}
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize; ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
/* Loop on each block */ /* Loop on each block */
while (1) while (1)
{ {
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTD_isError(cBlockSize)) return cBlockSize; if (ZSTD_isError(cBlockSize)) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
return;
}
ip += ZSTD_blockHeaderSize; ip += ZSTD_blockHeaderSize;
remainingSize -= ZSTD_blockHeaderSize; remainingSize -= ZSTD_blockHeaderSize;
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); if (cBlockSize > remainingSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
if (cBlockSize == 0) break; /* bt_end */ if (cBlockSize == 0) break; /* bt_end */
ip += cBlockSize; ip += cBlockSize;
remainingSize -= cBlockSize; remainingSize -= cBlockSize;
nbBlocks++;
} }
return ip - (const BYTE*)src; *cSize = ip - (const BYTE*)src;
*dBound = nbBlocks * BLOCKSIZE;
} }
/******************************* /*******************************
@@ -3458,11 +3482,6 @@ size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize); return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
} }
size_t ZSTDv02_findFrameCompressedSize(const void *src, size_t compressedSize)
{
return ZSTD_findFrameCompressedSize(src, compressedSize);
}
ZSTDv02_Dctx* ZSTDv02_createDCtx(void) ZSTDv02_Dctx* ZSTDv02_createDCtx(void)
{ {
return (ZSTDv02_Dctx*)ZSTD_createDCtx(); return (ZSTDv02_Dctx*)ZSTD_createDCtx();
+12 -7
View File
@@ -35,13 +35,18 @@ ZSTDv02_decompress() : decompress ZSTD frames compliant with v0.2.x format
size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize, size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,
const void* src, size_t compressedSize); const void* src, size_t compressedSize);
/** /**
ZSTDv02_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.2.x format ZSTDv02_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.2.x format
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
return : the number of bytes that would be read to decompress this frame cSize (output parameter) : the number of bytes that would be read to decompress this frame
or an errorCode if it fails (which can be tested using ZSTDv02_isError()) or an error code if it fails (which can be tested using ZSTDv01_isError())
*/ dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
size_t ZSTDv02_findFrameCompressedSize(const void* src, size_t compressedSize); or ZSTD_CONTENTSIZE_ERROR if an error occurs
note : assumes `cSize` and `dBound` are _not_ NULL.
*/
void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
size_t* cSize, unsigned long long* dBound);
/** /**
ZSTDv02_isError() : tells if the result of ZSTDv02_decompress() is an error ZSTDv02_isError() : tells if the result of ZSTDv02_decompress() is an error
+32 -12
View File
@@ -2369,6 +2369,8 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
#define LITERAL_NOENTROPY 63 #define LITERAL_NOENTROPY 63
#define COMMAND_NOENTROPY 7 /* to remove */ #define COMMAND_NOENTROPY 7 /* to remove */
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
static const size_t ZSTD_blockHeaderSize = 3; static const size_t ZSTD_blockHeaderSize = 3;
static const size_t ZSTD_frameHeaderSize = 4; static const size_t ZSTD_frameHeaderSize = 4;
@@ -2737,7 +2739,7 @@ static size_t ZSTD_execSequence(BYTE* op,
BYTE* const base, BYTE* const oend) BYTE* const base, BYTE* const oend)
{ {
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */ static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */ static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
const BYTE* const ostart = op; const BYTE* const ostart = op;
BYTE* const oLitEnd = op + sequence.litLength; BYTE* const oLitEnd = op + sequence.litLength;
BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */ BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
@@ -2953,36 +2955,59 @@ static size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, siz
return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize); return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
} }
static size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize) /* ZSTD_errorFrameSizeInfoLegacy() :
assumes `cSize` and `dBound` are _not_ NULL */
MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
{
*cSize = ret;
*dBound = ZSTD_CONTENTSIZE_ERROR;
}
void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
{ {
const BYTE* ip = (const BYTE*)src; const BYTE* ip = (const BYTE*)src;
size_t remainingSize = srcSize; size_t remainingSize = srcSize;
size_t nbBlocks = 0;
U32 magicNumber; U32 magicNumber;
blockProperties_t blockProperties; blockProperties_t blockProperties;
/* Frame Header */ /* Frame Header */
if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
magicNumber = MEM_readLE32(src); magicNumber = MEM_readLE32(src);
if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown); if (magicNumber != ZSTD_magicNumber) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
return;
}
ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize; ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
/* Loop on each block */ /* Loop on each block */
while (1) while (1)
{ {
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTD_isError(cBlockSize)) return cBlockSize; if (ZSTD_isError(cBlockSize)) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
return;
}
ip += ZSTD_blockHeaderSize; ip += ZSTD_blockHeaderSize;
remainingSize -= ZSTD_blockHeaderSize; remainingSize -= ZSTD_blockHeaderSize;
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); if (cBlockSize > remainingSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
if (cBlockSize == 0) break; /* bt_end */ if (cBlockSize == 0) break; /* bt_end */
ip += cBlockSize; ip += cBlockSize;
remainingSize -= cBlockSize; remainingSize -= cBlockSize;
nbBlocks++;
} }
return ip - (const BYTE*)src; *cSize = ip - (const BYTE*)src;
*dBound = nbBlocks * BLOCKSIZE;
} }
@@ -3099,11 +3124,6 @@ size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize); return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
} }
size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t srcSize)
{
return ZSTD_findFrameCompressedSize(src, srcSize);
}
ZSTDv03_Dctx* ZSTDv03_createDCtx(void) ZSTDv03_Dctx* ZSTDv03_createDCtx(void)
{ {
return (ZSTDv03_Dctx*)ZSTD_createDCtx(); return (ZSTDv03_Dctx*)ZSTD_createDCtx();
+12 -7
View File
@@ -35,13 +35,18 @@ ZSTDv03_decompress() : decompress ZSTD frames compliant with v0.3.x format
size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize, size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,
const void* src, size_t compressedSize); const void* src, size_t compressedSize);
/** /**
ZSTDv03_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.3.x format ZSTDv03_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.3.x format
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
return : the number of bytes that would be read to decompress this frame cSize (output parameter) : the number of bytes that would be read to decompress this frame
or an errorCode if it fails (which can be tested using ZSTDv03_isError()) or an error code if it fails (which can be tested using ZSTDv01_isError())
*/ dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t compressedSize); or ZSTD_CONTENTSIZE_ERROR if an error occurs
note : assumes `cSize` and `dBound` are _not_ NULL.
*/
void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
size_t* cSize, unsigned long long* dBound);
/** /**
ZSTDv03_isError() : tells if the result of ZSTDv03_decompress() is an error ZSTDv03_isError() : tells if the result of ZSTDv03_decompress() is an error
+32 -12
View File
@@ -373,6 +373,8 @@ static const size_t ZSTD_frameHeaderSize_min = 5;
#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/) #define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)
#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE) #define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t; typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
@@ -2860,7 +2862,7 @@ static size_t ZSTD_execSequence(BYTE* op,
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd) const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
{ {
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
BYTE* const oLitEnd = op + sequence.litLength; BYTE* const oLitEnd = op + sequence.litLength;
const size_t sequenceLength = sequence.litLength + sequence.matchLength; const size_t sequenceLength = sequence.litLength + sequence.matchLength;
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
@@ -3119,34 +3121,57 @@ static size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx,
return op-ostart; return op-ostart;
} }
static size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize) /* ZSTD_errorFrameSizeInfoLegacy() :
assumes `cSize` and `dBound` are _not_ NULL */
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
{
*cSize = ret;
*dBound = ZSTD_CONTENTSIZE_ERROR;
}
void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
{ {
const BYTE* ip = (const BYTE*)src; const BYTE* ip = (const BYTE*)src;
size_t remainingSize = srcSize; size_t remainingSize = srcSize;
size_t nbBlocks = 0;
blockProperties_t blockProperties; blockProperties_t blockProperties;
/* Frame Header */ /* Frame Header */
if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); if (srcSize < ZSTD_frameHeaderSize_min) {
if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown); ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
return;
}
ip += ZSTD_frameHeaderSize_min; remainingSize -= ZSTD_frameHeaderSize_min; ip += ZSTD_frameHeaderSize_min; remainingSize -= ZSTD_frameHeaderSize_min;
/* Loop on each block */ /* Loop on each block */
while (1) while (1)
{ {
size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTD_isError(cBlockSize)) return cBlockSize; if (ZSTD_isError(cBlockSize)) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
return;
}
ip += ZSTD_blockHeaderSize; ip += ZSTD_blockHeaderSize;
remainingSize -= ZSTD_blockHeaderSize; remainingSize -= ZSTD_blockHeaderSize;
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); if (cBlockSize > remainingSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
if (cBlockSize == 0) break; /* bt_end */ if (cBlockSize == 0) break; /* bt_end */
ip += cBlockSize; ip += cBlockSize;
remainingSize -= cBlockSize; remainingSize -= cBlockSize;
nbBlocks++;
} }
return ip - (const BYTE*)src; *cSize = ip - (const BYTE*)src;
*dBound = nbBlocks * BLOCKSIZE;
} }
/* ****************************** /* ******************************
@@ -3578,11 +3603,6 @@ size_t ZSTDv04_decompress(void* dst, size_t maxDstSize, const void* src, size_t
#endif #endif
} }
size_t ZSTDv04_findFrameCompressedSize(const void* src, size_t srcSize)
{
return ZSTD_findFrameCompressedSize(src, srcSize);
}
size_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx) { return ZSTD_resetDCtx(dctx); } size_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx) { return ZSTD_resetDCtx(dctx); }
size_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx) size_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx)
+12 -7
View File
@@ -35,13 +35,18 @@ ZSTDv04_decompress() : decompress ZSTD frames compliant with v0.4.x format
size_t ZSTDv04_decompress( void* dst, size_t maxOriginalSize, size_t ZSTDv04_decompress( void* dst, size_t maxOriginalSize,
const void* src, size_t compressedSize); const void* src, size_t compressedSize);
/** /**
ZSTDv04_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.4.x format ZSTDv04_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.4.x format
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
return : the number of bytes that would be read to decompress this frame cSize (output parameter) : the number of bytes that would be read to decompress this frame
or an errorCode if it fails (which can be tested using ZSTDv04_isError()) or an error code if it fails (which can be tested using ZSTDv01_isError())
*/ dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
size_t ZSTDv04_findFrameCompressedSize(const void* src, size_t compressedSize); or ZSTD_CONTENTSIZE_ERROR if an error occurs
note : assumes `cSize` and `dBound` are _not_ NULL.
*/
void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
size_t* cSize, unsigned long long* dBound);
/** /**
ZSTDv04_isError() : tells if the result of ZSTDv04_decompress() is an error ZSTDv04_isError() : tells if the result of ZSTDv04_decompress() is an error
+32 -7
View File
@@ -491,6 +491,8 @@ static const size_t ZSTDv05_frameHeaderSize_min = 5;
#define WILDCOPY_OVERLENGTH 8 #define WILDCOPY_OVERLENGTH 8
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t; typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
@@ -3217,7 +3219,7 @@ static size_t ZSTDv05_execSequence(BYTE* op,
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd) const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
{ {
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
BYTE* const oLitEnd = op + sequence.litLength; BYTE* const oLitEnd = op + sequence.litLength;
const size_t sequenceLength = sequence.litLength + sequence.matchLength; const size_t sequenceLength = sequence.litLength + sequence.matchLength;
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
@@ -3508,34 +3510,57 @@ size_t ZSTDv05_decompress(void* dst, size_t maxDstSize, const void* src, size_t
#endif #endif
} }
size_t ZSTDv05_findFrameCompressedSize(const void *src, size_t srcSize) /* ZSTD_errorFrameSizeInfoLegacy() :
assumes `cSize` and `dBound` are _not_ NULL */
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
{
*cSize = ret;
*dBound = ZSTD_CONTENTSIZE_ERROR;
}
void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
{ {
const BYTE* ip = (const BYTE*)src; const BYTE* ip = (const BYTE*)src;
size_t remainingSize = srcSize; size_t remainingSize = srcSize;
size_t nbBlocks = 0;
blockProperties_t blockProperties; blockProperties_t blockProperties;
/* Frame Header */ /* Frame Header */
if (srcSize < ZSTDv05_frameHeaderSize_min) return ERROR(srcSize_wrong); if (srcSize < ZSTDv05_frameHeaderSize_min) {
if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown); ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
return;
}
ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min; ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min;
/* Loop on each block */ /* Loop on each block */
while (1) while (1)
{ {
size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties); size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTDv05_isError(cBlockSize)) return cBlockSize; if (ZSTDv05_isError(cBlockSize)) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
return;
}
ip += ZSTDv05_blockHeaderSize; ip += ZSTDv05_blockHeaderSize;
remainingSize -= ZSTDv05_blockHeaderSize; remainingSize -= ZSTDv05_blockHeaderSize;
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); if (cBlockSize > remainingSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
if (cBlockSize == 0) break; /* bt_end */ if (cBlockSize == 0) break; /* bt_end */
ip += cBlockSize; ip += cBlockSize;
remainingSize -= cBlockSize; remainingSize -= cBlockSize;
nbBlocks++;
} }
return ip - (const BYTE*)src; *cSize = ip - (const BYTE*)src;
*dBound = nbBlocks * BLOCKSIZE;
} }
/* ****************************** /* ******************************
+12 -7
View File
@@ -33,13 +33,18 @@ extern "C" {
size_t ZSTDv05_decompress( void* dst, size_t dstCapacity, size_t ZSTDv05_decompress( void* dst, size_t dstCapacity,
const void* src, size_t compressedSize); const void* src, size_t compressedSize);
/** /**
ZSTDv05_getFrameSrcSize() : get the source length of a ZSTD frame ZSTDv05_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.5.x format
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
return : the number of bytes that would be read to decompress this frame cSize (output parameter) : the number of bytes that would be read to decompress this frame
or an errorCode if it fails (which can be tested using ZSTDv05_isError()) or an error code if it fails (which can be tested using ZSTDv01_isError())
*/ dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
size_t ZSTDv05_findFrameCompressedSize(const void* src, size_t compressedSize); or ZSTD_CONTENTSIZE_ERROR if an error occurs
note : assumes `cSize` and `dBound` are _not_ NULL.
*/
void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
size_t* cSize, unsigned long long* dBound);
/* ************************************* /* *************************************
* Helper functions * Helper functions
+36 -8
View File
@@ -506,6 +506,8 @@ typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
#define FSEv06_ENCODING_STATIC 2 #define FSEv06_ENCODING_STATIC 2
#define FSEv06_ENCODING_DYNAMIC 3 #define FSEv06_ENCODING_DYNAMIC 3
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
13,14,15,16 }; 13,14,15,16 };
@@ -3406,7 +3408,7 @@ static size_t ZSTDv06_execSequence(BYTE* op,
if (sequence.offset < 8) { if (sequence.offset < 8) {
/* close range match, overlap */ /* close range match, overlap */
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
int const sub2 = dec64table[sequence.offset]; int const sub2 = dec64table[sequence.offset];
op[0] = match[0]; op[0] = match[0];
op[1] = match[1]; op[1] = match[1];
@@ -3654,36 +3656,62 @@ size_t ZSTDv06_decompress(void* dst, size_t dstCapacity, const void* src, size_t
#endif #endif
} }
size_t ZSTDv06_findFrameCompressedSize(const void* src, size_t srcSize) /* ZSTD_errorFrameSizeInfoLegacy() :
assumes `cSize` and `dBound` are _not_ NULL */
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
{
*cSize = ret;
*dBound = ZSTD_CONTENTSIZE_ERROR;
}
void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
{ {
const BYTE* ip = (const BYTE*)src; const BYTE* ip = (const BYTE*)src;
size_t remainingSize = srcSize; size_t remainingSize = srcSize;
size_t nbBlocks = 0;
blockProperties_t blockProperties = { bt_compressed, 0 }; blockProperties_t blockProperties = { bt_compressed, 0 };
/* Frame Header */ /* Frame Header */
{ size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min); { size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);
if (ZSTDv06_isError(frameHeaderSize)) return frameHeaderSize; if (ZSTDv06_isError(frameHeaderSize)) {
if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) return ERROR(prefix_unknown); ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);
if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong); return;
}
if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
return;
}
if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
ip += frameHeaderSize; remainingSize -= frameHeaderSize; ip += frameHeaderSize; remainingSize -= frameHeaderSize;
} }
/* Loop on each block */ /* Loop on each block */
while (1) { while (1) {
size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, remainingSize, &blockProperties); size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTDv06_isError(cBlockSize)) return cBlockSize; if (ZSTDv06_isError(cBlockSize)) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
return;
}
ip += ZSTDv06_blockHeaderSize; ip += ZSTDv06_blockHeaderSize;
remainingSize -= ZSTDv06_blockHeaderSize; remainingSize -= ZSTDv06_blockHeaderSize;
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); if (cBlockSize > remainingSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
if (cBlockSize == 0) break; /* bt_end */ if (cBlockSize == 0) break; /* bt_end */
ip += cBlockSize; ip += cBlockSize;
remainingSize -= cBlockSize; remainingSize -= cBlockSize;
nbBlocks++;
} }
return ip - (const BYTE*)src; *cSize = ip - (const BYTE*)src;
*dBound = nbBlocks * ZSTDv06_BLOCKSIZE_MAX;
} }
/*_****************************** /*_******************************
+10 -5
View File
@@ -43,12 +43,17 @@ ZSTDLIBv06_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity,
const void* src, size_t compressedSize); const void* src, size_t compressedSize);
/** /**
ZSTDv06_getFrameSrcSize() : get the source length of a ZSTD frame ZSTDv06_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.6.x format
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
return : the number of bytes that would be read to decompress this frame cSize (output parameter) : the number of bytes that would be read to decompress this frame
or an errorCode if it fails (which can be tested using ZSTDv06_isError()) or an error code if it fails (which can be tested using ZSTDv01_isError())
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
or ZSTD_CONTENTSIZE_ERROR if an error occurs
note : assumes `cSize` and `dBound` are _not_ NULL.
*/ */
size_t ZSTDv06_findFrameCompressedSize(const void* src, size_t compressedSize); void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
size_t* cSize, unsigned long long* dBound);
/* ************************************* /* *************************************
* Helper functions * Helper functions
+40 -9
View File
@@ -2740,6 +2740,8 @@ typedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t;
#define FSEv07_ENCODING_STATIC 2 #define FSEv07_ENCODING_STATIC 2
#define FSEv07_ENCODING_DYNAMIC 3 #define FSEv07_ENCODING_DYNAMIC 3
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
13,14,15,16 }; 13,14,15,16 };
@@ -3631,7 +3633,7 @@ size_t ZSTDv07_execSequence(BYTE* op,
if (sequence.offset < 8) { if (sequence.offset < 8) {
/* close range match, overlap */ /* close range match, overlap */
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
int const sub2 = dec64table[sequence.offset]; int const sub2 = dec64table[sequence.offset];
op[0] = match[0]; op[0] = match[0];
op[1] = match[1]; op[1] = match[1];
@@ -3895,19 +3897,40 @@ size_t ZSTDv07_decompress(void* dst, size_t dstCapacity, const void* src, size_t
#endif #endif
} }
size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t srcSize) /* ZSTD_errorFrameSizeInfoLegacy() :
assumes `cSize` and `dBound` are _not_ NULL */
static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
{
*cSize = ret;
*dBound = ZSTD_CONTENTSIZE_ERROR;
}
void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
{ {
const BYTE* ip = (const BYTE*)src; const BYTE* ip = (const BYTE*)src;
size_t remainingSize = srcSize; size_t remainingSize = srcSize;
size_t nbBlocks = 0;
/* check */ /* check */
if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong); if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
/* Frame Header */ /* Frame Header */
{ size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min); { size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);
if (ZSTDv07_isError(frameHeaderSize)) return frameHeaderSize; if (ZSTDv07_isError(frameHeaderSize)) {
if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) return ERROR(prefix_unknown); ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);
if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong); return;
}
if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
return;
}
if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
ip += frameHeaderSize; remainingSize -= frameHeaderSize; ip += frameHeaderSize; remainingSize -= frameHeaderSize;
} }
@@ -3915,20 +3938,28 @@ size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t srcSize)
while (1) { while (1) {
blockProperties_t blockProperties; blockProperties_t blockProperties;
size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties); size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTDv07_isError(cBlockSize)) return cBlockSize; if (ZSTDv07_isError(cBlockSize)) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
return;
}
ip += ZSTDv07_blockHeaderSize; ip += ZSTDv07_blockHeaderSize;
remainingSize -= ZSTDv07_blockHeaderSize; remainingSize -= ZSTDv07_blockHeaderSize;
if (blockProperties.blockType == bt_end) break; if (blockProperties.blockType == bt_end) break;
if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); if (cBlockSize > remainingSize) {
ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
return;
}
ip += cBlockSize; ip += cBlockSize;
remainingSize -= cBlockSize; remainingSize -= cBlockSize;
nbBlocks++;
} }
return ip - (const BYTE*)src; *cSize = ip - (const BYTE*)src;
*dBound = nbBlocks * ZSTDv07_BLOCKSIZE_ABSOLUTEMAX;
} }
/*_****************************** /*_******************************
+10 -5
View File
@@ -50,12 +50,17 @@ ZSTDLIBv07_API size_t ZSTDv07_decompress( void* dst, size_t dstCapacity,
const void* src, size_t compressedSize); const void* src, size_t compressedSize);
/** /**
ZSTDv07_getFrameSrcSize() : get the source length of a ZSTD frame ZSTDv07_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.7.x format
compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
return : the number of bytes that would be read to decompress this frame cSize (output parameter) : the number of bytes that would be read to decompress this frame
or an errorCode if it fails (which can be tested using ZSTDv07_isError()) or an error code if it fails (which can be tested using ZSTDv01_isError())
dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
or ZSTD_CONTENTSIZE_ERROR if an error occurs
note : assumes `cSize` and `dBound` are _not_ NULL.
*/ */
size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t compressedSize); void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
size_t* cSize, unsigned long long* dBound);
/*====== Helper functions ======*/ /*====== Helper functions ======*/
ZSTDLIBv07_API unsigned ZSTDv07_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ ZSTDLIBv07_API unsigned ZSTDv07_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
+616 -469
View File
@@ -70,8 +70,8 @@ extern "C" {
/*------ Version ------*/ /*------ Version ------*/
#define ZSTD_VERSION_MAJOR 1 #define ZSTD_VERSION_MAJOR 1
#define ZSTD_VERSION_MINOR 3 #define ZSTD_VERSION_MINOR 4
#define ZSTD_VERSION_RELEASE 8 #define ZSTD_VERSION_RELEASE 0
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */ ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */
@@ -89,6 +89,21 @@ ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */
# define ZSTD_CLEVEL_DEFAULT 3 # define ZSTD_CLEVEL_DEFAULT 3
#endif #endif
/***************************************
* Constants
***************************************/
/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */
#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */
#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */
#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0
#define ZSTD_BLOCKSIZELOG_MAX 17
#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX)
/*************************************** /***************************************
* Simple API * Simple API
***************************************/ ***************************************/
@@ -145,12 +160,21 @@ ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t
* @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */ * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */
ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
/*! ZSTD_findFrameCompressedSize() :
* `src` should point to the start of a ZSTD frame or skippable frame.
* `srcSize` must be >= first frame size
* @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 */
ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
/*====== Helper functions ======*/ /*====== Helper functions ======*/
#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */ #define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */ ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */
ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
@@ -195,279 +219,6 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
const void* src, size_t srcSize); const void* src, size_t srcSize);
/**************************
* Simple dictionary API
***************************/
/*! ZSTD_compress_usingDict() :
* Compression at an explicit compression level using a Dictionary.
* A dictionary can be any arbitrary data segment (also called a prefix),
* or a buffer with specified information (see dictBuilder/zdict.h).
* Note : This function loads the dictionary, resulting in significant startup delay.
* It's intended for a dictionary used only once.
* Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize,
int compressionLevel);
/*! ZSTD_decompress_usingDict() :
* Decompression using a known Dictionary.
* Dictionary must be identical to the one used during compression.
* Note : This function loads the dictionary, resulting in significant startup delay.
* It's intended for a dictionary used only once.
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize);
/***********************************
* Bulk processing dictionary API
**********************************/
typedef struct ZSTD_CDict_s ZSTD_CDict;
/*! ZSTD_createCDict() :
* When compressing multiple messages / blocks using the same dictionary, it's recommended to load it only once.
* ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup cost.
* ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
* `dictBuffer` can be released after ZSTD_CDict creation, because its content is copied within CDict.
* Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate `dictBuffer` content.
* Note : A ZSTD_CDict can be created from an empty dictBuffer, but it is inefficient when used to compress small data. */
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
int compressionLevel);
/*! ZSTD_freeCDict() :
* Function frees memory allocated by ZSTD_createCDict(). */
ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
/*! ZSTD_compress_usingCDict() :
* Compression using a digested Dictionary.
* Recommended when same dictionary is used multiple times.
* Note : compression level is _decided at dictionary creation time_,
* and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict);
typedef struct ZSTD_DDict_s ZSTD_DDict;
/*! ZSTD_createDDict() :
* Create a digested dictionary, ready to start decompression operation without startup delay.
* dictBuffer can be released after DDict creation, as its content is copied inside DDict. */
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
/*! ZSTD_freeDDict() :
* Function frees memory allocated with ZSTD_createDDict() */
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
/*! ZSTD_decompress_usingDDict() :
* Decompression using a digested Dictionary.
* Recommended when same dictionary is used multiple times. */
ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_DDict* ddict);
/****************************
* Streaming
****************************/
typedef struct ZSTD_inBuffer_s {
const void* src; /**< start of input buffer */
size_t size; /**< size of input buffer */
size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */
} ZSTD_inBuffer;
typedef struct ZSTD_outBuffer_s {
void* dst; /**< start of output buffer */
size_t size; /**< size of output buffer */
size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */
} ZSTD_outBuffer;
/*-***********************************************************************
* Streaming compression - HowTo
*
* A ZSTD_CStream object is required to track streaming operation.
* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
* ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
*
* For parallel execution, use one separate ZSTD_CStream per thread.
*
* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
*
* Parameters are sticky : when starting a new compression on the same context,
* it will re-use the same sticky parameters as previous compression session.
* When in doubt, it's recommended to fully initialize the context before usage.
* Use ZSTD_initCStream() to set the parameter to a selected compression level.
* Use advanced API (ZSTD_CCtx_setParameter(), etc.) to set more specific parameters.
*
* Use ZSTD_compressStream() as many times as necessary to consume input stream.
* The function will automatically update both `pos` fields within `input` and `output`.
* Note that the function may not consume the entire input,
* for example, because the output buffer is already full,
* in which case `input.pos < input.size`.
* The caller must check if input has been entirely consumed.
* If not, the caller must make some room to receive more compressed data,
* and then present again remaining input data.
* @return : a size hint, preferred nb of bytes to use as input for next function call
* or an error code, which can be tested using ZSTD_isError().
* Note 1 : it's just a hint, to help latency a little, any value will work fine.
* Note 2 : size hint is guaranteed to be <= ZSTD_CStreamInSize()
*
* At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
* using ZSTD_flushStream(). `output->pos` will be updated.
* Note that, if `output->size` is too small, a single invocation of ZSTD_flushStream() might not be enough (return code > 0).
* In which case, make some room to receive more compressed data, and call again ZSTD_flushStream().
* @return : 0 if internal buffers are entirely flushed,
* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
* or an error code, which can be tested using ZSTD_isError().
*
* ZSTD_endStream() instructs to finish a frame.
* It will perform a flush and write frame epilogue.
* The epilogue is required for decoders to consider a frame completed.
* flush() operation is the same, and follows same rules as ZSTD_flushStream().
* @return : 0 if frame fully completed and fully flushed,
* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
* or an error code, which can be tested using ZSTD_isError().
*
* *******************************************************************/
typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */
/* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
/*===== ZSTD_CStream management functions =====*/
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
/*===== Streaming compression functions =====*/
ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */
ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */
/*-***************************************************************************
* Streaming decompression - HowTo
*
* A ZSTD_DStream object is required to track streaming operations.
* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
* ZSTD_DStream objects can be re-used multiple times.
*
* Use ZSTD_initDStream() to start a new decompression operation.
* @return : recommended first input size
* Alternatively, use advanced API to set specific properties.
*
* Use ZSTD_decompressStream() repetitively to consume your input.
* The function will update both `pos` fields.
* If `input.pos < input.size`, some input has not been consumed.
* It's up to the caller to present again remaining data.
* The function tries to flush all data decoded immediately, respecting output buffer size.
* If `output.pos < output.size`, decoder has flushed everything it could.
* But if `output.pos == output.size`, there might be some data left within internal buffers.,
* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
* @return : 0 when a frame is completely decoded and fully flushed,
* or an error code, which can be tested using ZSTD_isError(),
* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
* the return value is a suggested next input size (just a hint for better latency)
* that will never request more than the remaining frame size.
* *******************************************************************************/
typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */
/* For compatibility with versions <= v1.2.0, prefer differentiating them. */
/*===== ZSTD_DStream management functions =====*/
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
/*===== Streaming decompression functions =====*/
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */
ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
#endif /* ZSTD_H_235446 */
/****************************************************************************************
* ADVANCED AND EXPERIMENTAL FUNCTIONS
****************************************************************************************
* The definitions in the following section are considered experimental.
* They are provided for advanced scenarios.
* They should never be used with a dynamic library, as prototypes may change in the future.
* Use them only in association with static linking.
* ***************************************************************************************/
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
/****************************************************************************************
* Candidate API for promotion to stable status
****************************************************************************************
* The following symbols and constants form the "staging area" :
* they are considered to join "stable API" by v1.4.0.
* The proposal is written so that it can be made stable "as is",
* though it's still possible to suggest improvements.
* Staging is in fact last chance for changes,
* the API is locked once reaching "stable" status.
* ***************************************************************************************/
/* === Constants === */
/* all magic numbers are supposed read/written to/from files/memory using little-endian convention */
#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */
#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */
#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0
#define ZSTD_BLOCKSIZELOG_MAX 17
#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX)
/* === query limits === */
ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */
/* === frame size === */
/*! ZSTD_findFrameCompressedSize() :
* `src` should point to the start of a ZSTD frame or skippable frame.
* `srcSize` must be >= first frame size
* @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 */
ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
/* === Memory management === */
/*! ZSTD_sizeof_*() :
* These functions give the _current_ memory usage of selected object.
* Note that object memory usage can evolve (increase or decrease) over time. */
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
/*************************************** /***************************************
* Advanced compression API * Advanced compression API
***************************************/ ***************************************/
@@ -503,7 +254,10 @@ typedef enum { ZSTD_fast=1,
typedef enum { typedef enum {
/* compression parameters */ /* compression parameters
* Note: When compressing with a ZSTD_CDict these parameters are superseded
* by the parameters used to construct the ZSTD_CDict. See ZSTD_CCtx_refCDict()
* for more info (superseded-by-cdict). */
ZSTD_c_compressionLevel=100, /* Update all compression parameters according to pre-defined cLevel table ZSTD_c_compressionLevel=100, /* Update all compression parameters according to pre-defined cLevel table
* Default level is ZSTD_CLEVEL_DEFAULT==3. * Default level is ZSTD_CLEVEL_DEFAULT==3.
* Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.
@@ -625,6 +379,7 @@ typedef enum {
* ZSTD_c_format * ZSTD_c_format
* ZSTD_c_forceMaxWindow * ZSTD_c_forceMaxWindow
* ZSTD_c_forceAttachDict * ZSTD_c_forceAttachDict
* ZSTD_c_literalCompressionMode
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly; * note : never ever use experimentalParam? names directly;
* also, the enums values themselves are unstable and can still change. * also, the enums values themselves are unstable and can still change.
@@ -632,10 +387,10 @@ typedef enum {
ZSTD_c_experimentalParam1=500, ZSTD_c_experimentalParam1=500,
ZSTD_c_experimentalParam2=10, ZSTD_c_experimentalParam2=10,
ZSTD_c_experimentalParam3=1000, ZSTD_c_experimentalParam3=1000,
ZSTD_c_experimentalParam4=1001 ZSTD_c_experimentalParam4=1001,
ZSTD_c_experimentalParam5=1002,
} ZSTD_cParameter; } ZSTD_cParameter;
typedef struct { typedef struct {
size_t error; size_t error;
int lowerBound; int lowerBound;
@@ -677,10 +432,427 @@ ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param
* Note 3 : Whenever all input data is provided and consumed in a single round, * Note 3 : Whenever all input data is provided and consumed in a single round,
* for example with ZSTD_compress2(), * for example with ZSTD_compress2(),
* or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end), * or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),
* this value is automatically overriden by srcSize instead. * this value is automatically overridden by srcSize instead.
*/ */
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize); ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);
typedef enum {
ZSTD_reset_session_only = 1,
ZSTD_reset_parameters = 2,
ZSTD_reset_session_and_parameters = 3
} ZSTD_ResetDirective;
/*! ZSTD_CCtx_reset() :
* There are 2 different things that can be reset, independently or jointly :
* - The session : will stop compressing current frame, and make CCtx ready to start a new one.
* Useful after an error, or to interrupt any ongoing compression.
* Any internal data not yet flushed is cancelled.
* Compression parameters and dictionary remain unchanged.
* They will be used to compress next frame.
* Resetting session never fails.
* - The parameters : changes all parameters back to "default".
* This removes any reference to any dictionary too.
* Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)
* otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())
* - Both : similar to resetting the session, followed by resetting parameters.
*/
ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);
/*! ZSTD_compress2() :
* Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.
* ZSTD_compress2() always starts a new frame.
* Should cctx hold data from a previously unfinished frame, everything about it is forgotten.
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
* - The function is always blocking, returns when compression is completed.
* Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
* @return : compressed size written into `dst` (<= `dstCapacity),
* or an error code if it fails (which can be tested using ZSTD_isError()).
*/
ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
/***************************************
* Advanced decompression API
***************************************/
/* The advanced API pushes parameters one by one into an existing DCtx context.
* Parameters are sticky, and remain valid for all following frames
* using the same DCtx context.
* It's possible to reset parameters to default values using ZSTD_DCtx_reset().
* Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream().
* Therefore, no new decompression function is necessary.
*/
typedef enum {
ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which
* the streaming API will refuse to allocate memory buffer
* in order to protect the host from unreasonable memory requirements.
* This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
* By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).
* Special: value 0 means "use default maximum windowLog". */
/* note : additional experimental parameters are also available
* within the experimental section of the API.
* At the time of this writing, they include :
* ZSTD_c_format
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly
*/
ZSTD_d_experimentalParam1=1000
} ZSTD_dParameter;
/*! ZSTD_dParam_getBounds() :
* All parameters must belong to an interval with lower and upper bounds,
* otherwise they will either trigger an error or be automatically clamped.
* @return : a structure, ZSTD_bounds, which contains
* - an error status field, which must be tested using ZSTD_isError()
* - both lower and upper bounds, inclusive
*/
ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);
/*! ZSTD_DCtx_setParameter() :
* Set one compression parameter, selected by enum ZSTD_dParameter.
* All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().
* Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
* Setting a parameter is only possible during frame initialization (before starting decompression).
* @return : 0, or an error code (which can be tested using ZSTD_isError()).
*/
ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);
/*! ZSTD_DCtx_reset() :
* Return a DCtx to clean state.
* Session and parameters can be reset jointly or separately.
* Parameters can only be reset when no active frame is being decompressed.
* @return : 0, or an error code, which can be tested with ZSTD_isError()
*/
ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
/****************************
* Streaming
****************************/
typedef struct ZSTD_inBuffer_s {
const void* src; /**< start of input buffer */
size_t size; /**< size of input buffer */
size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */
} ZSTD_inBuffer;
typedef struct ZSTD_outBuffer_s {
void* dst; /**< start of output buffer */
size_t size; /**< size of output buffer */
size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */
} ZSTD_outBuffer;
/*-***********************************************************************
* Streaming compression - HowTo
*
* A ZSTD_CStream object is required to track streaming operation.
* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
* ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
*
* For parallel execution, use one separate ZSTD_CStream per thread.
*
* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
*
* Parameters are sticky : when starting a new compression on the same context,
* it will re-use the same sticky parameters as previous compression session.
* When in doubt, it's recommended to fully initialize the context before usage.
* Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),
* ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to
* set more specific parameters, the pledged source size, or load a dictionary.
*
* Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to
* consume input stream. The function will automatically update both `pos`
* fields within `input` and `output`.
* Note that the function may not consume the entire input, for example, because
* the output buffer is already full, in which case `input.pos < input.size`.
* The caller must check if input has been entirely consumed.
* If not, the caller must make some room to receive more compressed data,
* and then present again remaining input data.
* note: ZSTD_e_continue is guaranteed to make some forward progress when called,
* but doesn't guarantee maximal forward progress. This is especially relevant
* when compressing with multiple threads. The call won't block if it can
* consume some input, but if it can't it will wait for some, but not all,
* output to be flushed.
* @return : provides a minimum amount of data remaining to be flushed from internal buffers
* or an error code, which can be tested using ZSTD_isError().
*
* At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
* using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.
* Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).
* In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.
* You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the
* operation.
* note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will
* block until the flush is complete or the output buffer is full.
* @return : 0 if internal buffers are entirely flushed,
* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
* or an error code, which can be tested using ZSTD_isError().
*
* Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.
* It will perform a flush and write frame epilogue.
* The epilogue is required for decoders to consider a frame completed.
* flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.
* You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to
* start a new frame.
* note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will
* block until the flush is complete or the output buffer is full.
* @return : 0 if frame fully completed and fully flushed,
* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
* or an error code, which can be tested using ZSTD_isError().
*
* *******************************************************************/
typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */
/* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
/*===== ZSTD_CStream management functions =====*/
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
/*===== Streaming compression functions =====*/
typedef enum {
ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */
ZSTD_e_flush=1, /* flush any data provided so far,
* it creates (at least) one new block, that can be decoded immediately on reception;
* frame will continue: any future data can still reference previously compressed data, improving compression.
* note : multithreaded compression will block to flush as much output as possible. */
ZSTD_e_end=2 /* flush any remaining data _and_ close current frame.
* note that frame is only closed after compressed data is fully flushed (return value == 0).
* After that point, any additional data starts a new frame.
* note : each frame is independent (does not reference any content from previous frame).
: note : multithreaded compression will block to flush as much output as possible. */
} ZSTD_EndDirective;
/*! ZSTD_compressStream2() :
* Behaves about the same as ZSTD_compressStream, with additional control on end directive.
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
* - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
* - output->pos must be <= dstCapacity, input->pos must be <= srcSize
* - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
* - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
* - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
* and then immediately returns, just indicating that there is some data remaining to be flushed.
* The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
* - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
* - @return provides a minimum amount of data remaining to be flushed from internal buffers
* or an error code, which can be tested using ZSTD_isError().
* if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
* This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
* For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
* - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
* only ZSTD_e_end or ZSTD_e_flush operations are allowed.
* Before starting a new compression job, or changing compression parameters,
* it is required to fully flush internal buffers.
*/
ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
ZSTD_outBuffer* output,
ZSTD_inBuffer* input,
ZSTD_EndDirective endOp);
ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */
ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */
/*******************************************************************************
* This is a legacy streaming API, and can be replaced by ZSTD_CCtx_reset() and
* ZSTD_compressStream2(). It is redundant, but is still fully supported.
* Advanced parameters and dictionary compression can only be used through the
* new API.
******************************************************************************/
/**
* Equivalent to:
*
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
*/
ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
/**
* Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).
* NOTE: The return value is different. ZSTD_compressStream() returns a hint for
* the next read size (if non-zero and not an error). ZSTD_compressStream2()
* returns the number of bytes left to flush (if non-zero and not an error).
*/
ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
/** Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */
ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
/** Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */
ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
/*-***************************************************************************
* Streaming decompression - HowTo
*
* A ZSTD_DStream object is required to track streaming operations.
* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
* ZSTD_DStream objects can be re-used multiple times.
*
* Use ZSTD_initDStream() to start a new decompression operation.
* @return : recommended first input size
* Alternatively, use advanced API to set specific properties.
*
* Use ZSTD_decompressStream() repetitively to consume your input.
* The function will update both `pos` fields.
* If `input.pos < input.size`, some input has not been consumed.
* It's up to the caller to present again remaining data.
* The function tries to flush all data decoded immediately, respecting output buffer size.
* If `output.pos < output.size`, decoder has flushed everything it could.
* But if `output.pos == output.size`, there might be some data left within internal buffers.,
* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
* @return : 0 when a frame is completely decoded and fully flushed,
* or an error code, which can be tested using ZSTD_isError(),
* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
* the return value is a suggested next input size (just a hint for better latency)
* that will never request more than the remaining frame size.
* *******************************************************************************/
typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */
/* For compatibility with versions <= v1.2.0, prefer differentiating them. */
/*===== ZSTD_DStream management functions =====*/
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
/*===== Streaming decompression functions =====*/
/* This function is redundant with the advanced API and equivalent to:
*
* ZSTD_DCtx_reset(zds);
* ZSTD_DCtx_refDDict(zds, NULL);
*/
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */
ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
/**************************
* Simple dictionary API
***************************/
/*! ZSTD_compress_usingDict() :
* Compression at an explicit compression level using a Dictionary.
* A dictionary can be any arbitrary data segment (also called a prefix),
* or a buffer with specified information (see dictBuilder/zdict.h).
* Note : This function loads the dictionary, resulting in significant startup delay.
* It's intended for a dictionary used only once.
* Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize,
int compressionLevel);
/*! ZSTD_decompress_usingDict() :
* Decompression using a known Dictionary.
* Dictionary must be identical to the one used during compression.
* Note : This function loads the dictionary, resulting in significant startup delay.
* It's intended for a dictionary used only once.
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize);
/***********************************
* Bulk processing dictionary API
**********************************/
typedef struct ZSTD_CDict_s ZSTD_CDict;
/*! ZSTD_createCDict() :
* When compressing multiple messages / blocks using the same dictionary, it's recommended to load it only once.
* ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup cost.
* ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
* `dictBuffer` can be released after ZSTD_CDict creation, because its content is copied within CDict.
* Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate `dictBuffer` content.
* Note : A ZSTD_CDict can be created from an empty dictBuffer, but it is inefficient when used to compress small data. */
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
int compressionLevel);
/*! ZSTD_freeCDict() :
* Function frees memory allocated by ZSTD_createCDict(). */
ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
/*! ZSTD_compress_usingCDict() :
* Compression using a digested Dictionary.
* Recommended when same dictionary is used multiple times.
* Note : compression level is _decided at dictionary creation time_,
* and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict);
typedef struct ZSTD_DDict_s ZSTD_DDict;
/*! ZSTD_createDDict() :
* Create a digested dictionary, ready to start decompression operation without startup delay.
* dictBuffer can be released after DDict creation, as its content is copied inside DDict. */
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
/*! ZSTD_freeDDict() :
* Function frees memory allocated with ZSTD_createDDict() */
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
/*! ZSTD_decompress_usingDDict() :
* Decompression using a digested Dictionary.
* Recommended when same dictionary is used multiple times. */
ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_DDict* ddict);
/********************************
* Dictionary helper functions
*******************************/
/*! ZSTD_getDictID_fromDict() :
* Provides the dictID stored within dictionary.
* if @return == 0, the dictionary is not conformant with Zstandard specification.
* It can still be loaded, but as a content-only dictionary. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
/*! ZSTD_getDictID_fromDDict() :
* Provides the dictID of the dictionary loaded into `ddict`.
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
/*! ZSTD_getDictID_fromFrame() :
* Provides the dictID required to decompressed the frame stored within `src`.
* If @return == 0, the dictID could not be decoded.
* This could for one of the following reasons :
* - The frame does not require a dictionary to be decoded (most common case).
* - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
* Note : this use case also happens when using a non-conformant dictionary.
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
* - This is not a Zstandard frame.
* When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
/*******************************************************************************
* Advanced dictionary and prefix API
*
* This API allows dictionaries to be used with ZSTD_compress2(),
* ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
* only reset with the context is reset with ZSTD_reset_parameters or
* ZSTD_reset_session_and_parameters. Prefixes are single-use.
******************************************************************************/
/*! ZSTD_CCtx_loadDictionary() : /*! ZSTD_CCtx_loadDictionary() :
* Create an internal CDict from `dict` buffer. * Create an internal CDict from `dict` buffer.
* Decompression will have to use same dictionary. * Decompression will have to use same dictionary.
@@ -703,7 +875,9 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
/*! ZSTD_CCtx_refCDict() : /*! ZSTD_CCtx_refCDict() :
* Reference a prepared dictionary, to be used for all next compressed frames. * Reference a prepared dictionary, to be used for all next compressed frames.
* Note that compression parameters are enforced from within CDict, * Note that compression parameters are enforced from within CDict,
* and supercede any compression parameter previously set within CCtx. * and supersede any compression parameter previously set within CCtx.
* The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
* The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
* The dictionary will remain valid for future compressed frames using same CCtx. * The dictionary will remain valid for future compressed frames using same CCtx.
* @result : 0, or an error code (which can be tested with ZSTD_isError()). * @result : 0, or an error code (which can be tested with ZSTD_isError()).
* Special : Referencing a NULL CDict means "return to no-dictionary mode". * Special : Referencing a NULL CDict means "return to no-dictionary mode".
@@ -733,136 +907,6 @@ ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
const void* prefix, size_t prefixSize); const void* prefix, size_t prefixSize);
typedef enum {
ZSTD_reset_session_only = 1,
ZSTD_reset_parameters = 2,
ZSTD_reset_session_and_parameters = 3
} ZSTD_ResetDirective;
/*! ZSTD_CCtx_reset() :
* There are 2 different things that can be reset, independently or jointly :
* - The session : will stop compressing current frame, and make CCtx ready to start a new one.
* Useful after an error, or to interrupt any ongoing compression.
* Any internal data not yet flushed is cancelled.
* Compression parameters and dictionary remain unchanged.
* They will be used to compress next frame.
* Resetting session never fails.
* - The parameters : changes all parameters back to "default".
* This removes any reference to any dictionary too.
* Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)
* otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())
* - Both : similar to resetting the session, followed by resetting parameters.
*/
ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);
/*! ZSTD_compress2() :
* Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.
* ZSTD_compress2() always starts a new frame.
* Should cctx hold data from a previously unfinished frame, everything about it is forgotten.
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
* - The function is always blocking, returns when compression is completed.
* Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
* @return : compressed size written into `dst` (<= `dstCapacity),
* or an error code if it fails (which can be tested using ZSTD_isError()).
*/
ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
typedef enum {
ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */
ZSTD_e_flush=1, /* flush any data provided so far,
* it creates (at least) one new block, that can be decoded immediately on reception;
* frame will continue: any future data can still reference previously compressed data, improving compression. */
ZSTD_e_end=2 /* flush any remaining data _and_ close current frame.
* note that frame is only closed after compressed data is fully flushed (return value == 0).
* After that point, any additional data starts a new frame.
* note : each frame is independent (does not reference any content from previous frame). */
} ZSTD_EndDirective;
/*! ZSTD_compressStream2() :
* Behaves about the same as ZSTD_compressStream, with additional control on end directive.
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
* - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
* - outpot->pos must be <= dstCapacity, input->pos must be <= srcSize
* - outpot->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
* - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
* - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
* and then immediately returns, just indicating that there is some data remaining to be flushed.
* The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
* - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
* - @return provides a minimum amount of data remaining to be flushed from internal buffers
* or an error code, which can be tested using ZSTD_isError().
* if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
* This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
* For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
* - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
* only ZSTD_e_end or ZSTD_e_flush operations are allowed.
* Before starting a new compression job, or changing compression parameters,
* it is required to fully flush internal buffers.
*/
ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
ZSTD_outBuffer* output,
ZSTD_inBuffer* input,
ZSTD_EndDirective endOp);
/* ============================== */
/* Advanced decompression API */
/* ============================== */
/* The advanced API pushes parameters one by one into an existing DCtx context.
* Parameters are sticky, and remain valid for all following frames
* using the same DCtx context.
* It's possible to reset parameters to default values using ZSTD_DCtx_reset().
* Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream().
* Therefore, no new decompression function is necessary.
*/
typedef enum {
ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which
* the streaming API will refuse to allocate memory buffer
* in order to protect the host from unreasonable memory requirements.
* This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
* By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) */
/* note : additional experimental parameters are also available
* within the experimental section of the API.
* At the time of this writing, they include :
* ZSTD_c_format
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly
*/
ZSTD_d_experimentalParam1=1000
} ZSTD_dParameter;
/*! ZSTD_dParam_getBounds() :
* All parameters must belong to an interval with lower and upper bounds,
* otherwise they will either trigger an error or be automatically clamped.
* @return : a structure, ZSTD_bounds, which contains
* - an error status field, which must be tested using ZSTD_isError()
* - both lower and upper bounds, inclusive
*/
ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);
/*! ZSTD_DCtx_setParameter() :
* Set one compression parameter, selected by enum ZSTD_dParameter.
* All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().
* Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
* Setting a parameter is only possible during frame initialization (before starting decompression).
* @return : 0, or an error code (which can be tested using ZSTD_isError()).
*/
ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);
/*! ZSTD_DCtx_loadDictionary() : /*! ZSTD_DCtx_loadDictionary() :
* Create an internal DDict from dict buffer, * Create an internal DDict from dict buffer,
* to be used to decompress next frames. * to be used to decompress next frames.
@@ -910,15 +954,32 @@ ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,
const void* prefix, size_t prefixSize); const void* prefix, size_t prefixSize);
/*! ZSTD_DCtx_reset() : /* === Memory management === */
* Return a DCtx to clean state.
* Session and parameters can be reset jointly or separately. /*! ZSTD_sizeof_*() :
* Parameters can only be reset when no active frame is being decompressed. * These functions give the _current_ memory usage of selected object.
* @return : 0, or an error code, which can be tested with ZSTD_isError() * Note that object memory usage can evolve (increase or decrease) over time. */
*/ ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset); ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
#endif /* ZSTD_H_235446 */
/****************************************************************************************
* ADVANCED AND EXPERIMENTAL FUNCTIONS
****************************************************************************************
* The definitions in the following section are considered experimental.
* They are provided for advanced scenarios.
* They should never be used with a dynamic library, as prototypes may change in the future.
* Use them only in association with static linking.
* ***************************************************************************************/
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
/**************************************************************************************** /****************************************************************************************
* experimental API (static linking only) * experimental API (static linking only)
@@ -962,7 +1023,7 @@ ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame #define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame
* requiring larger than (1<<ZSTD_WINDOWLOG_LIMIT_DEFAULT) window size, * requiring larger than (1<<ZSTD_WINDOWLOG_LIMIT_DEFAULT) window size,
* to preserve host's memory from unreasonable requirements. * to preserve host's memory from unreasonable requirements.
* This limit can be overriden using ZSTD_DCtx_setParameter(,ZSTD_d_windowLogMax,). * This limit can be overridden using ZSTD_DCtx_setParameter(,ZSTD_d_windowLogMax,).
* The limit does not apply for one-pass decoders (such as ZSTD_decompress()), since no additional memory is allocated */ * The limit does not apply for one-pass decoders (such as ZSTD_decompress()), since no additional memory is allocated */
@@ -1064,15 +1125,24 @@ typedef enum {
ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */ ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */
} ZSTD_dictAttachPref_e; } ZSTD_dictAttachPref_e;
typedef enum {
ZSTD_lcm_auto = 0, /**< Automatically determine the compression mode based on the compression level.
* Negative compression levels will be uncompressed, and positive compression
* levels will be compressed. */
ZSTD_lcm_huffman = 1, /**< Always attempt Huffman compression. Uncompressed literals will still be
* emitted if Huffman compression is not profitable. */
ZSTD_lcm_uncompressed = 2, /**< Always emit uncompressed literals. */
} ZSTD_literalCompressionMode_e;
/*************************************** /***************************************
* Frame size functions * Frame size functions
***************************************/ ***************************************/
/*! ZSTD_findDecompressedSize() : /*! ZSTD_findDecompressedSize() :
* `src` should point the start of a series of ZSTD encoded and/or skippable frames * `src` should point to the start of a series of ZSTD encoded and/or skippable frames
* `srcSize` must be the _exact_ size of this series * `srcSize` must be the _exact_ size of this series
* (i.e. there should be a frame boundary exactly at `srcSize` bytes after `src`) * (i.e. there should be a frame boundary at `src + srcSize`)
* @return : - decompressed size of all data in all successive frames * @return : - decompressed size of all data in all successive frames
* - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN
* - if an error occurred: ZSTD_CONTENTSIZE_ERROR * - if an error occurred: ZSTD_CONTENTSIZE_ERROR
@@ -1092,6 +1162,21 @@ typedef enum {
* however it does mean that all frame data must be present and valid. */ * however it does mean that all frame data must be present and valid. */
ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
/** ZSTD_decompressBound() :
* `src` should point to the start of a series of ZSTD encoded and/or skippable frames
* `srcSize` must be the _exact_ size of this series
* (i.e. there should be a frame boundary at `src + srcSize`)
* @return : - upper-bound for the decompressed size of all data in all successive frames
* - if an error occured: ZSTD_CONTENTSIZE_ERROR
*
* note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame.
* note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
* in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.
* note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:
* upper-bound = # blocks * min(128 KB, Window_Size)
*/
ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
/*! ZSTD_frameHeaderSize() : /*! ZSTD_frameHeaderSize() :
* srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
* @return : size of the Frame Header, * @return : size of the Frame Header,
@@ -1110,7 +1195,7 @@ ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
* It will also consider src size to be arbitrarily "large", which is worst case. * It will also consider src size to be arbitrarily "large", which is worst case.
* If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation. * If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation.
* ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. * ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
* ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1. * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
* Note : CCtx size estimation is only correct for single-threaded compression. */ * Note : CCtx size estimation is only correct for single-threaded compression. */
ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel); ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
@@ -1122,7 +1207,7 @@ ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
* It will also consider src size to be arbitrarily "large", which is worst case. * It will also consider src size to be arbitrarily "large", which is worst case.
* If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation. * If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
* ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. * ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
* ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1. * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
* Note : CStream size estimation is only correct for single-threaded compression. * Note : CStream size estimation is only correct for single-threaded compression.
* ZSTD_DStream memory budget depends on window Size. * ZSTD_DStream memory budget depends on window Size.
* This information can be passed manually, using ZSTD_estimateDStreamSize, * This information can be passed manually, using ZSTD_estimateDStreamSize,
@@ -1226,22 +1311,26 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictS
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
/*! ZSTD_getCParams() : /*! ZSTD_getCParams() :
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
* `estimatedSrcSize` value is optional, select 0 if not known */ * `estimatedSrcSize` value is optional, select 0 if not known */
ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
/*! ZSTD_getParams() : /*! ZSTD_getParams() :
* same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`. * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
* All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */ * All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */
ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
/*! ZSTD_checkCParams() : /*! ZSTD_checkCParams() :
* Ensure param values remain within authorized range */ * Ensure param values remain within authorized range.
* @return 0 on success, or an error code (can be checked with ZSTD_isError()) */
ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params); ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
/*! ZSTD_adjustCParams() : /*! ZSTD_adjustCParams() :
* optimize params for a given `srcSize` and `dictSize`. * optimize params for a given `srcSize` and `dictSize`.
* both values are optional, select `0` if unknown. */ * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.
* `dictSize` must be `0` when there is no dictionary.
* cPar can be invalid : all parameters will be clamped within valid range in the @return struct.
* This function never fails (wide contract) */
ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize); ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
/*! ZSTD_compress_advanced() : /*! ZSTD_compress_advanced() :
@@ -1314,6 +1403,12 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
* See the comments on that enum for an explanation of the feature. */ * See the comments on that enum for an explanation of the feature. */
#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4 #define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4
/* Controls how the literals are compressed (default is auto).
* The value must be of type ZSTD_literalCompressionMode_e.
* See ZSTD_literalCompressionMode_t enum definition for details.
*/
#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5
/*! ZSTD_CCtx_getParameter() : /*! ZSTD_CCtx_getParameter() :
* Get the requested compression parameter value, selected by enum ZSTD_cParameter, * Get the requested compression parameter value, selected by enum ZSTD_cParameter,
* and store it into int* value. * and store it into int* value.
@@ -1325,10 +1420,10 @@ ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param
/*! ZSTD_CCtx_params : /*! ZSTD_CCtx_params :
* Quick howto : * Quick howto :
* - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
* - ZSTD_CCtxParam_setParameter() : Push parameters one by one into * - ZSTD_CCtxParams_setParameter() : Push parameters one by one into
* an existing ZSTD_CCtx_params structure. * an existing ZSTD_CCtx_params structure.
* This is similar to * This is similar to
* ZSTD_CCtx_setParameter(). * ZSTD_CCtx_setParameter().
* - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to
* an existing CCtx. * an existing CCtx.
* These parameters will be applied to * These parameters will be applied to
@@ -1359,20 +1454,20 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compre
*/ */
ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params); ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
/*! ZSTD_CCtxParam_setParameter() : /*! ZSTD_CCtxParams_setParameter() :
* Similar to ZSTD_CCtx_setParameter. * Similar to ZSTD_CCtx_setParameter.
* Set one compression parameter, selected by enum ZSTD_cParameter. * Set one compression parameter, selected by enum ZSTD_cParameter.
* Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams(). * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
* @result : 0, or an error code (which can be tested with ZSTD_isError()). * @result : 0, or an error code (which can be tested with ZSTD_isError()).
*/ */
ZSTDLIB_API size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value); ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
/*! ZSTD_CCtxParam_getParameter() : /*! ZSTD_CCtxParams_getParameter() :
* Similar to ZSTD_CCtx_getParameter. * Similar to ZSTD_CCtx_getParameter.
* Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
* @result : 0, or an error code (which can be tested with ZSTD_isError()). * @result : 0, or an error code (which can be tested with ZSTD_isError()).
*/ */
ZSTDLIB_API size_t ZSTD_CCtxParam_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value); ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
/*! ZSTD_CCtx_setParametersUsingCCtxParams() : /*! ZSTD_CCtx_setParametersUsingCCtxParams() :
* Apply a set of ZSTD_CCtx_params to the compression context. * Apply a set of ZSTD_CCtx_params to the compression context.
@@ -1415,31 +1510,6 @@ ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
* it must remain read accessible throughout the lifetime of DDict */ * it must remain read accessible throughout the lifetime of DDict */
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize); ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
/*! ZSTD_getDictID_fromDict() :
* Provides the dictID stored within dictionary.
* if @return == 0, the dictionary is not conformant with Zstandard specification.
* It can still be loaded, but as a content-only dictionary. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
/*! ZSTD_getDictID_fromDDict() :
* Provides the dictID of the dictionary loaded into `ddict`.
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
/*! ZSTD_getDictID_fromFrame() :
* Provides the dictID required to decompressed the frame stored within `src`.
* If @return == 0, the dictID could not be decoded.
* This could for one of the following reasons :
* - The frame does not require a dictionary to be decoded (most common case).
* - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
* Note : this use case also happens when using a non-conformant dictionary.
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
* - This is not a Zstandard frame.
* When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
/*! ZSTD_DCtx_loadDictionary_byReference() : /*! ZSTD_DCtx_loadDictionary_byReference() :
* Same as ZSTD_DCtx_loadDictionary(), * Same as ZSTD_DCtx_loadDictionary(),
* but references `dict` content instead of copying it into `dctx`. * but references `dict` content instead of copying it into `dctx`.
@@ -1501,14 +1571,68 @@ ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
********************************************************************/ ********************************************************************/
/*===== Advanced Streaming compression functions =====*/ /*===== Advanced Streaming compression functions =====*/
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct. If it is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, "0" also disables frame content size field. It may be enabled in the future. */ /**! ZSTD_initCStream_srcSize() :
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.*/ * This function is deprecated, and equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
*
* pledgedSrcSize must be correct. If it is not known at init time, use
* ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
* "0" also disables frame content size field. It may be enabled in the future.
*/
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize);
/**! ZSTD_initCStream_usingDict() :
* This function is deprecated, and is equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
*
* Creates of an internal CDict (incompatible with static CCtx), except if
* dict == NULL or dictSize < 8, in which case no dict is used.
* Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if
* it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
*/
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel);
/**! ZSTD_initCStream_advanced() :
* This function is deprecated, and is approximately equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_setZstdParams(zcs, params); // Set the zstd params and leave the rest as-is
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
*
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
* value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy.
*/
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy. */ ZSTD_parameters params, unsigned long long pledgedSrcSize);
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */ /**! ZSTD_initCStream_usingCDict() :
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize); /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters. pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. */ * This function is deprecated, and equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_refCDict(zcs, cdict);
*
* note : cdict will just be referenced, and must outlive compression session
*/
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
/**! ZSTD_initCStream_usingCDict_advanced() :
* This function is deprecated, and is approximately equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_setZstdFrameParams(zcs, fParams); // Set the zstd frame params and leave the rest as-is
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
* ZSTD_CCtx_refCDict(zcs, cdict);
*
* same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
* value ZSTD_CONTENTSIZE_UNKNOWN.
*/
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize);
/*! ZSTD_resetCStream() : /*! ZSTD_resetCStream() :
* This function is deprecated, and is equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
*
* start a new frame, using same parameters from previous frame. * start a new frame, using same parameters from previous frame.
* This is typically useful to skip dictionary loading stage, since it will re-use it in-place. * This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
* Note that zcs must be init at least once before using ZSTD_resetCStream(). * Note that zcs must be init at least once before using ZSTD_resetCStream().
@@ -1555,9 +1679,32 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
/*===== Advanced Streaming decompression functions =====*/ /*===== Advanced Streaming decompression functions =====*/
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: no dictionary will be used if dict == NULL or dictSize < 8 */ /**
ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict is referenced, it must outlive decompression session */ * This function is deprecated, and is equivalent to:
ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */ *
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
* ZSTD_DCtx_loadDictionary(zds, dict, dictSize);
*
* note: no dictionary will be used if dict == NULL or dictSize < 8
*/
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
/**
* This function is deprecated, and is equivalent to:
*
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
* ZSTD_DCtx_refDDict(zds, ddict);
*
* note : ddict is referenced, it must outlive decompression session
*/
ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
/**
* This function is deprecated, and is equivalent to:
*
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
*
* re-use decompression parameters from previous init; saves dictionary loading
*/
ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
/********************************************************************* /*********************************************************************
+10 -10
View File
@@ -51,7 +51,7 @@ endif
CFLAGS ?= -O3 CFLAGS ?= -O3
DEBUGFLAGS+=-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ DEBUGFLAGS+=-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \ -Wstrict-prototypes -Wundef -Wpointer-arith \
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
-Wredundant-decls -Wmissing-prototypes -Wc++-compat -Wredundant-decls -Wmissing-prototypes -Wc++-compat
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
@@ -165,7 +165,7 @@ $(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP)
zstd : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) $(LZ4CPP) zstd : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) $(LZ4CPP)
zstd : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD) zstd : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD)
zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
zstd : $(ZSTDLIB_FILES) zstdcli.o util.o fileio.o benchfn.o benchzstd.o datagen.o dibio.o zstd : $(ZSTDLIB_FILES) zstdcli.o util.o timefn.o fileio.o benchfn.o benchzstd.o datagen.o dibio.o
@echo "$(THREAD_MSG)" @echo "$(THREAD_MSG)"
@echo "$(ZLIB_MSG)" @echo "$(ZLIB_MSG)"
@echo "$(LZMA_MSG)" @echo "$(LZMA_MSG)"
@@ -183,13 +183,13 @@ zstd-release: zstd
zstd32 : CPPFLAGS += $(THREAD_CPP) zstd32 : CPPFLAGS += $(THREAD_CPP)
zstd32 : LDFLAGS += $(THREAD_LD) zstd32 : LDFLAGS += $(THREAD_LD)
zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c timefn.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c
ifneq (,$(filter Windows%,$(OS))) ifneq (,$(filter Windows%,$(OS)))
windres/generate_res.bat windres/generate_res.bat
endif endif
$(CC) -m32 $(FLAGS) $^ $(RES32_FILE) -o $@$(EXT) $(CC) -m32 $(FLAGS) $^ $(RES32_FILE) -o $@$(EXT)
zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o util.o fileio.c benchfn.o benchzstd.o datagen.o dibio.o zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o util.o fileio.c benchfn.o benchzstd.o timefn.o datagen.o dibio.o
$(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS) $(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS)
zstd-nomt : THREAD_CPP := zstd-nomt : THREAD_CPP :=
@@ -222,13 +222,13 @@ zstd-pgo :
# minimal target, with only zstd compression and decompression. no bench. no legacy. # minimal target, with only zstd compression and decompression. no bench. no legacy.
zstd-small: CFLAGS = -Os -s zstd-small: CFLAGS = -Os -s
zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c util.c fileio.c zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c util.c timefn.c fileio.c
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o $@$(EXT) $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o $@$(EXT)
zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c util.c fileio.c zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c util.c timefn.c fileio.c
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o $@$(EXT) $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o $@$(EXT)
zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c util.c fileio.c zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c util.c timefn.c fileio.c
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT) $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT)
zstdmt: zstd zstdmt: zstd
@@ -265,9 +265,9 @@ man: zstd.1 zstdgrep.1 zstdless.1
.PHONY: clean-man .PHONY: clean-man
clean-man: clean-man:
rm zstd.1 $(RM) zstd.1
rm zstdgrep.1 $(RM) zstdgrep.1
rm zstdless.1 $(RM) zstdless.1
.PHONY: preview-man .PHONY: preview-man
preview-man: clean-man man preview-man: clean-man man
+39 -48
View File
@@ -13,25 +13,20 @@
/* ************************************* /* *************************************
* Includes * Includes
***************************************/ ***************************************/
#include "platform.h" /* Large Files support */
#include "util.h" /* UTIL_getFileSize, UTIL_sleep */
#include <stdlib.h> /* malloc, free */ #include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */ #include <string.h> /* memset */
#include <stdio.h> /* fprintf, fopen */
#undef NDEBUG /* assert must not be disabled */ #undef NDEBUG /* assert must not be disabled */
#include <assert.h> /* assert */ #include <assert.h> /* assert */
#include "mem.h" #include "timefn.h" /* UTIL_time_t, UTIL_getTime */
#include "benchfn.h" #include "benchfn.h"
/* ************************************* /* *************************************
* Constants * Constants
***************************************/ ***************************************/
#define TIMELOOP_MICROSEC (1*1000000ULL) /* 1 second */ #define TIMELOOP_MICROSEC SEC_TO_MICRO /* 1 second */
#define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */ #define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */
#define ACTIVEPERIOD_MICROSEC (70*TIMELOOP_MICROSEC) /* 70 seconds */
#define COOLPERIOD_SEC 10
#define KB *(1 <<10) #define KB *(1 <<10)
#define MB *(1 <<20) #define MB *(1 <<20)
@@ -39,14 +34,16 @@
/* ************************************* /* *************************************
* Errors * Debug errors
***************************************/ ***************************************/
#ifndef DEBUG #if defined(DEBUG) && (DEBUG >= 1)
# define DEBUG 0 # include <stdio.h> /* fprintf */
# define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
# define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }
#else
# define DEBUGOUTPUT(...)
#endif #endif
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
#define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }
/* error without displaying */ /* error without displaying */
#define RETURN_QUIET_ERROR(retValue, ...) { \ #define RETURN_QUIET_ERROR(retValue, ...) { \
@@ -116,15 +113,7 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
{ size_t i; { size_t i;
for(i = 0; i < p.blockCount; i++) { for(i = 0; i < p.blockCount; i++) {
memset(p.dstBuffers[i], 0xE5, p.dstCapacities[i]); /* warm up and erase result buffer */ memset(p.dstBuffers[i], 0xE5, p.dstCapacities[i]); /* warm up and erase result buffer */
} } }
#if 0
/* based on testing these seem to lower accuracy of multiple calls of 1 nbLoops vs 1 call of multiple nbLoops
* (Makes former slower)
*/
UTIL_sleepMilli(5); /* give processor time to other processes */
UTIL_waitForNextTick();
#endif
}
/* benchmark */ /* benchmark */
{ UTIL_time_t const clockStart = UTIL_getTime(); { UTIL_time_t const clockStart = UTIL_getTime();
@@ -146,9 +135,9 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
} } } }
} /* for (loopNb = 0; loopNb < nbLoops; loopNb++) */ } /* for (loopNb = 0; loopNb < nbLoops; loopNb++) */
{ U64 const totalTime = UTIL_clockSpanNano(clockStart); { PTime const totalTime = UTIL_clockSpanNano(clockStart);
BMK_runTime_t rt; BMK_runTime_t rt;
rt.nanoSecPerRun = totalTime / nbLoops; rt.nanoSecPerRun = (double)totalTime / nbLoops;
rt.sumOfReturn = dstSize; rt.sumOfReturn = dstSize;
return BMK_setValid_runTime(rt); return BMK_setValid_runTime(rt);
} } } }
@@ -158,9 +147,9 @@ BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,
/* ==== Benchmarking any function, providing intermediate results ==== */ /* ==== Benchmarking any function, providing intermediate results ==== */
struct BMK_timedFnState_s { struct BMK_timedFnState_s {
U64 timeSpent_ns; PTime timeSpent_ns;
U64 timeBudget_ns; PTime timeBudget_ns;
U64 runBudget_ns; PTime runBudget_ns;
BMK_runTime_t fastestRun; BMK_runTime_t fastestRun;
unsigned nbLoops; unsigned nbLoops;
UTIL_time_t coolTime; UTIL_time_t coolTime;
@@ -174,8 +163,20 @@ BMK_timedFnState_t* BMK_createTimedFnState(unsigned total_ms, unsigned run_ms)
return r; return r;
} }
void BMK_freeTimedFnState(BMK_timedFnState_t* state) { void BMK_freeTimedFnState(BMK_timedFnState_t* state) { free(state); }
free(state);
BMK_timedFnState_t*
BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms)
{
typedef char check_size[ 2 * (sizeof(BMK_timedFnState_shell) >= sizeof(struct BMK_timedFnState_s)) - 1]; /* static assert : a compilation failure indicates that BMK_timedFnState_shell is not large enough */
typedef struct { check_size c; BMK_timedFnState_t tfs; } tfs_align; /* force tfs to be aligned at its next best position */
size_t const tfs_alignment = offsetof(tfs_align, tfs); /* provides the minimal alignment restriction for BMK_timedFnState_t */
BMK_timedFnState_t* const r = (BMK_timedFnState_t*)buffer;
if (buffer == NULL) return NULL;
if (size < sizeof(struct BMK_timedFnState_s)) return NULL;
if ((size_t)buffer % tfs_alignment) return NULL; /* buffer must be properly aligned */
BMK_resetTimedFnState(r, total_ms, run_ms);
return r;
} }
void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms) void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms)
@@ -184,9 +185,9 @@ void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms,
if (!run_ms) run_ms = 1; if (!run_ms) run_ms = 1;
if (run_ms > total_ms) run_ms = total_ms; if (run_ms > total_ms) run_ms = total_ms;
timedFnState->timeSpent_ns = 0; timedFnState->timeSpent_ns = 0;
timedFnState->timeBudget_ns = (U64)total_ms * TIMELOOP_NANOSEC / 1000; timedFnState->timeBudget_ns = (PTime)total_ms * TIMELOOP_NANOSEC / 1000;
timedFnState->runBudget_ns = (U64)run_ms * TIMELOOP_NANOSEC / 1000; timedFnState->runBudget_ns = (PTime)run_ms * TIMELOOP_NANOSEC / 1000;
timedFnState->fastestRun.nanoSecPerRun = (U64)(-1LL); timedFnState->fastestRun.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000; /* hopefully large enough : must be larger than any potential measurement */
timedFnState->fastestRun.sumOfReturn = (size_t)(-1LL); timedFnState->fastestRun.sumOfReturn = (size_t)(-1LL);
timedFnState->nbLoops = 1; timedFnState->nbLoops = 1;
timedFnState->coolTime = UTIL_getTime(); timedFnState->coolTime = UTIL_getTime();
@@ -208,37 +209,27 @@ int BMK_isCompleted_TimedFn(const BMK_timedFnState_t* timedFnState)
BMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* cont, BMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* cont,
BMK_benchParams_t p) BMK_benchParams_t p)
{ {
U64 const runBudget_ns = cont->runBudget_ns; PTime const runBudget_ns = cont->runBudget_ns;
U64 const runTimeMin_ns = runBudget_ns / 2; PTime const runTimeMin_ns = runBudget_ns / 2;
int completed = 0; int completed = 0;
BMK_runTime_t bestRunTime = cont->fastestRun; BMK_runTime_t bestRunTime = cont->fastestRun;
while (!completed) { while (!completed) {
BMK_runOutcome_t runResult; BMK_runOutcome_t const runResult = BMK_benchFunction(p, cont->nbLoops);
/* Overheat protection */
if (UTIL_clockSpanMicro(cont->coolTime) > ACTIVEPERIOD_MICROSEC) {
DEBUGOUTPUT("\rcooling down ... \r");
UTIL_sleep(COOLPERIOD_SEC);
cont->coolTime = UTIL_getTime();
}
/* reinitialize capacity */
runResult = BMK_benchFunction(p, cont->nbLoops);
if(!BMK_isSuccessful_runOutcome(runResult)) { /* error : move out */ if(!BMK_isSuccessful_runOutcome(runResult)) { /* error : move out */
return runResult; return runResult;
} }
{ BMK_runTime_t const newRunTime = BMK_extract_runTime(runResult); { BMK_runTime_t const newRunTime = BMK_extract_runTime(runResult);
U64 const loopDuration_ns = newRunTime.nanoSecPerRun * cont->nbLoops; double const loopDuration_ns = newRunTime.nanoSecPerRun * cont->nbLoops;
cont->timeSpent_ns += loopDuration_ns; cont->timeSpent_ns += (unsigned long long)loopDuration_ns;
/* estimate nbLoops for next run to last approximately 1 second */ /* estimate nbLoops for next run to last approximately 1 second */
if (loopDuration_ns > (runBudget_ns / 50)) { if (loopDuration_ns > (runBudget_ns / 50)) {
U64 const fastestRun_ns = MIN(bestRunTime.nanoSecPerRun, newRunTime.nanoSecPerRun); double const fastestRun_ns = MIN(bestRunTime.nanoSecPerRun, newRunTime.nanoSecPerRun);
cont->nbLoops = (U32)(runBudget_ns / fastestRun_ns) + 1; cont->nbLoops = (unsigned)(runBudget_ns / fastestRun_ns) + 1;
} else { } else {
/* previous run was too short : blindly increase workload by x multiplier */ /* previous run was too short : blindly increase workload by x multiplier */
const unsigned multiplier = 10; const unsigned multiplier = 10;
+39 -23
View File
@@ -31,7 +31,7 @@ extern "C" {
/* BMK_runTime_t: valid result return type */ /* BMK_runTime_t: valid result return type */
typedef struct { typedef struct {
unsigned long long nanoSecPerRun; /* time per iteration (over all blocks) */ double nanoSecPerRun; /* time per iteration (over all blocks) */
size_t sumOfReturn; /* sum of return values */ size_t sumOfReturn; /* sum of return values */
} BMK_runTime_t; } BMK_runTime_t;
@@ -58,30 +58,31 @@ typedef size_t (*BMK_initFn_t)(void* initPayload);
typedef unsigned (*BMK_errorFn_t)(size_t); typedef unsigned (*BMK_errorFn_t)(size_t);
/* BMK_benchFunction() parameters are provided through following structure. /* BMK_benchFunction() parameters are provided via the following structure.
* This is preferable for readability, * A structure is preferable for readability,
* as the number of parameters required is pretty large. * as the number of parameters required is fairly large.
* No initializer is provided, because it doesn't make sense to provide some "default" : * No initializer is provided, because it doesn't make sense to provide some "default" :
* all parameters should be specified by the caller */ * all parameters must be specified by the caller.
* optional parameters are labelled explicitly, and accept value NULL when not used */
typedef struct { typedef struct {
BMK_benchFn_t benchFn; /* the function to benchmark, over the set of blocks */ BMK_benchFn_t benchFn; /* the function to benchmark, over the set of blocks */
void* benchPayload; /* pass custom parameters to benchFn : void* benchPayload; /* pass custom parameters to benchFn :
* (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload) */ * (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload) */
BMK_initFn_t initFn; /* (*initFn)(initPayload) is run once per run, at the beginning. */ BMK_initFn_t initFn; /* (*initFn)(initPayload) is run once per run, at the beginning. */
void* initPayload; /* Both arguments can be NULL, in which case nothing is run. */ void* initPayload; /* Both arguments can be NULL, in which case nothing is run. */
BMK_errorFn_t errorFn; /* errorFn will check each return value of benchFn over each block, to determine if it failed or not. BMK_errorFn_t errorFn; /* errorFn will check each return value of benchFn over each block, to determine if it failed or not.
* errorFn can be NULL, in which case no check is performed. * errorFn can be NULL, in which case no check is performed.
* errorFn must return 0 when benchFn was successful, and >= 1 if it detects an error. * errorFn must return 0 when benchFn was successful, and >= 1 if it detects an error.
* Execution is stopped as soon as an error is detected. * Execution is stopped as soon as an error is detected.
* the triggering return value can be retrieved using BMK_extract_errorResult(). */ * the triggering return value can be retrieved using BMK_extract_errorResult(). */
size_t blockCount; /* number of blocks to operate benchFn on. size_t blockCount; /* number of blocks to operate benchFn on.
* It's also the size of all array parameters : * It's also the size of all array parameters :
* srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults */ * srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults */
const void *const * srcBuffers; /* array of buffers to be operated on by benchFn */ const void *const * srcBuffers; /* read-only array of buffers to be operated on by benchFn */
const size_t* srcSizes; /* array of the sizes of srcBuffers buffers */ const size_t* srcSizes; /* read-only array containing sizes of srcBuffers */
void *const * dstBuffers;/* array of buffers to be written into by benchFn */ void *const * dstBuffers; /* array of buffers to be written into by benchFn. This array is not optional, it must be provided even if unused by benchfn. */
const size_t* dstCapacities; /* array of the capacities of dstBuffers buffers */ const size_t* dstCapacities; /* read-only array containing capacities of dstBuffers. This array must be present. */
size_t* blockResults; /* Optional: store the return value of benchFn for each block. Use NULL if this result is not requested. */ size_t* blockResults; /* Optional: store the return value of benchFn for each block. Use NULL if this result is not requested. */
} BMK_benchParams_t; } BMK_benchParams_t;
@@ -159,6 +160,21 @@ void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms,
void BMK_freeTimedFnState(BMK_timedFnState_t* state); void BMK_freeTimedFnState(BMK_timedFnState_t* state);
/* BMK_timedFnState_shell and BMK_initStatic_timedFnState() :
* Makes it possible to statically allocate a BMK_timedFnState_t on stack.
* BMK_timedFnState_shell is only there to allocate space,
* never ever access its members.
* BMK_timedFnState_t() actually accepts any buffer.
* It will check if provided buffer is large enough and is correctly aligned,
* and will return NULL if conditions are not respected.
*/
#define BMK_TIMEDFNSTATE_SIZE 64
typedef union {
char never_access_space[BMK_TIMEDFNSTATE_SIZE];
long long alignment_enforcer; /* must be aligned on 8-bytes boundaries */
} BMK_timedFnState_shell;
BMK_timedFnState_t* BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms);
#endif /* BENCH_FN_H_23876 */ #endif /* BENCH_FN_H_23876 */
+30 -19
View File
@@ -28,6 +28,7 @@
#include <errno.h> #include <errno.h>
#include <assert.h> /* assert */ #include <assert.h> /* assert */
#include "timefn.h" /* UTIL_time_t */
#include "benchfn.h" #include "benchfn.h"
#include "mem.h" #include "mem.h"
#define ZSTD_STATIC_LINKING_ONLY #define ZSTD_STATIC_LINKING_ONLY
@@ -135,7 +136,8 @@ BMK_advancedParams_t BMK_initAdvancedParams(void) {
0, /* ldmMinMatch */ 0, /* ldmMinMatch */
0, /* ldmHashLog */ 0, /* ldmHashLog */
0, /* ldmBuckSizeLog */ 0, /* ldmBuckSizeLog */
0 /* ldmHashRateLog */ 0, /* ldmHashRateLog */
ZSTD_lcm_auto /* literalCompressionMode */
}; };
return res; return res;
} }
@@ -159,9 +161,13 @@ typedef struct {
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b))
static void BMK_initCCtx(ZSTD_CCtx* ctx, static void
const void* dictBuffer, size_t dictBufferSize, int cLevel, BMK_initCCtx(ZSTD_CCtx* ctx,
const ZSTD_compressionParameters* comprParams, const BMK_advancedParams_t* adv) { const void* dictBuffer, size_t dictBufferSize,
int cLevel,
const ZSTD_compressionParameters* comprParams,
const BMK_advancedParams_t* adv)
{
ZSTD_CCtx_reset(ctx, ZSTD_reset_session_and_parameters); ZSTD_CCtx_reset(ctx, ZSTD_reset_session_and_parameters);
if (adv->nbWorkers==1) { if (adv->nbWorkers==1) {
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, 0)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, 0));
@@ -174,12 +180,13 @@ static void BMK_initCCtx(ZSTD_CCtx* ctx,
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashLog, adv->ldmHashLog)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashLog, adv->ldmHashLog));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmBucketSizeLog, adv->ldmBucketSizeLog)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmBucketSizeLog, adv->ldmBucketSizeLog));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashRateLog, adv->ldmHashRateLog)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashRateLog, adv->ldmHashRateLog));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_windowLog, comprParams->windowLog)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_windowLog, (int)comprParams->windowLog));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_hashLog, comprParams->hashLog)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_hashLog, (int)comprParams->hashLog));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_chainLog, comprParams->chainLog)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_chainLog, (int)comprParams->chainLog));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_searchLog, comprParams->searchLog)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_searchLog, (int)comprParams->searchLog));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_minMatch, comprParams->minMatch)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_minMatch, (int)comprParams->minMatch));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_targetLength, comprParams->targetLength)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_targetLength, (int)comprParams->targetLength));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_literalCompressionMode, (int)adv->literalCompressionMode));
CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_strategy, comprParams->strategy)); CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_strategy, comprParams->strategy));
CHECK_Z(ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize)); CHECK_Z(ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize));
} }
@@ -376,7 +383,7 @@ BMK_benchMemAdvancedNoAlloc(
} }
} }
/* warmimg up `compressedBuffer` */ /* warming up `compressedBuffer` */
if (adv->mode == BMK_decodeOnly) { if (adv->mode == BMK_decodeOnly) {
memcpy(compressedBuffer, srcBuffer, loadedCompressedSize); memcpy(compressedBuffer, srcBuffer, loadedCompressedSize);
} else { } else {
@@ -444,7 +451,7 @@ BMK_benchMemAdvancedNoAlloc(
cSize = cResult.sumOfReturn; cSize = cResult.sumOfReturn;
ratio = (double)srcSize / cSize; ratio = (double)srcSize / cSize;
{ BMK_benchResult_t newResult; { BMK_benchResult_t newResult;
newResult.cSpeed = ((U64)srcSize * TIMELOOP_NANOSEC / cResult.nanoSecPerRun); newResult.cSpeed = (U64)((double)srcSize * TIMELOOP_NANOSEC / cResult.nanoSecPerRun);
benchResult.cSize = cSize; benchResult.cSize = cSize;
if (newResult.cSpeed > benchResult.cSpeed) if (newResult.cSpeed > benchResult.cSpeed)
benchResult.cSpeed = newResult.cSpeed; benchResult.cSpeed = newResult.cSpeed;
@@ -468,7 +475,7 @@ BMK_benchMemAdvancedNoAlloc(
} }
{ BMK_runTime_t const dResult = BMK_extract_runTime(dOutcome); { BMK_runTime_t const dResult = BMK_extract_runTime(dOutcome);
U64 const newDSpeed = (srcSize * TIMELOOP_NANOSEC / dResult.nanoSecPerRun); U64 const newDSpeed = (U64)((double)srcSize * TIMELOOP_NANOSEC / dResult.nanoSecPerRun);
if (newDSpeed > benchResult.dSpeed) if (newDSpeed > benchResult.dSpeed)
benchResult.dSpeed = newDSpeed; benchResult.dSpeed = newDSpeed;
} }
@@ -505,17 +512,21 @@ BMK_benchMemAdvancedNoAlloc(
pos = (U32)(u - bacc); pos = (U32)(u - bacc);
bNb = pos / (128 KB); bNb = pos / (128 KB);
DISPLAY("(sample %u, block %u, pos %u) \n", segNb, bNb, pos); DISPLAY("(sample %u, block %u, pos %u) \n", segNb, bNb, pos);
if (u>5) { { size_t const lowest = (u>5) ? 5 : u;
int n; size_t n;
DISPLAY("origin: "); DISPLAY("origin: ");
for (n=-5; n<0; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]); for (n=lowest; n>0; n--)
DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u-n]);
DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]); DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]);
for (n=1; n<3; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]); for (n=1; n<3; n++)
DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]);
DISPLAY(" \n"); DISPLAY(" \n");
DISPLAY("decode: "); DISPLAY("decode: ");
for (n=-5; n<0; n++) DISPLAY("%02X ", resultBuffer[u+n]); for (n=lowest; n>0; n++)
DISPLAY("%02X ", resultBuffer[u-n]);
DISPLAY(" :%02X: ", resultBuffer[u]); DISPLAY(" :%02X: ", resultBuffer[u]);
for (n=1; n<3; n++) DISPLAY("%02X ", resultBuffer[u+n]); for (n=1; n<3; n++)
DISPLAY("%02X ", resultBuffer[u+n]);
DISPLAY(" \n"); DISPLAY(" \n");
} }
break; break;
+13 -12
View File
@@ -105,17 +105,18 @@ typedef enum {
} BMK_mode_t; } BMK_mode_t;
typedef struct { typedef struct {
BMK_mode_t mode; /* 0: all, 1: compress only 2: decode only */ BMK_mode_t mode; /* 0: all, 1: compress only 2: decode only */
unsigned nbSeconds; /* default timing is in nbSeconds */ unsigned nbSeconds; /* default timing is in nbSeconds */
size_t blockSize; /* Maximum size of each block*/ size_t blockSize; /* Maximum size of each block*/
unsigned nbWorkers; /* multithreading */ int nbWorkers; /* multithreading */
unsigned realTime; /* real time priority */ unsigned realTime; /* real time priority */
int additionalParam; /* used by python speed benchmark */ int additionalParam; /* used by python speed benchmark */
unsigned ldmFlag; /* enables long distance matching */ int ldmFlag; /* enables long distance matching */
unsigned ldmMinMatch; /* below: parameters for long distance matching, see zstd.1.md */ int ldmMinMatch; /* below: parameters for long distance matching, see zstd.1.md */
unsigned ldmHashLog; int ldmHashLog;
unsigned ldmBucketSizeLog; int ldmBucketSizeLog;
unsigned ldmHashRateLog; int ldmHashRateLog;
ZSTD_literalCompressionMode_e literalCompressionMode;
} BMK_advancedParams_t; } BMK_advancedParams_t;
/* returns default parameters used by nonAdvanced functions */ /* returns default parameters used by nonAdvanced functions */
@@ -169,7 +170,7 @@ BMK_benchOutcome_t BMK_syntheticTest(
* comprParams - basic compression parameters * comprParams - basic compression parameters
* dictBuffer - a dictionary if used, null otherwise * dictBuffer - a dictionary if used, null otherwise
* dictBufferSize - size of dictBuffer, 0 otherwise * dictBufferSize - size of dictBuffer, 0 otherwise
* diplayLevel - see BMK_benchFiles * displayLevel - see BMK_benchFiles
* displayName - name used by display * displayName - name used by display
* @return: * @return:
* a variant, which expresses either an error, or a valid result. * a variant, which expresses either an error, or a valid result.
+1
View File
@@ -29,6 +29,7 @@
#include <errno.h> /* errno */ #include <errno.h> /* errno */
#include <assert.h> #include <assert.h>
#include "timefn.h" /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */
#include "mem.h" /* read */ #include "mem.h" /* read */
#include "error_private.h" #include "error_private.h"
#include "dibio.h" #include "dibio.h"
+332 -205
View File
@@ -24,13 +24,14 @@
* Includes * Includes
***************************************/ ***************************************/
#include "platform.h" /* Large Files support, SET_BINARY_MODE */ #include "platform.h" /* Large Files support, SET_BINARY_MODE */
#include "util.h" /* UTIL_getFileSize, UTIL_isRegularFile */ #include "util.h" /* UTIL_getFileSize, UTIL_isRegularFile, UTIL_isSameFile */
#include <stdio.h> /* fprintf, fopen, fread, _fileno, stdin, stdout */ #include <stdio.h> /* fprintf, fopen, fread, _fileno, stdin, stdout */
#include <stdlib.h> /* malloc, free */ #include <stdlib.h> /* malloc, free */
#include <string.h> /* strcmp, strlen */ #include <string.h> /* strcmp, strlen */
#include <assert.h> #include <assert.h>
#include <errno.h> /* errno */ #include <errno.h> /* errno */
#include <signal.h> #include <signal.h>
#include "timefn.h" /* UTIL_getTime, UTIL_clockSpanMicro */
#if defined (_MSC_VER) #if defined (_MSC_VER)
# include <sys/stat.h> # include <sys/stat.h>
@@ -79,23 +80,29 @@
/*-************************************* /*-*************************************
* Macros * Macros
***************************************/ ***************************************/
struct FIO_display_prefs_s {
int displayLevel; /* 0 : no display; 1: errors; 2: + result + interaction + warnings; 3: + progression; 4: + information */
U32 noProgress;
};
static FIO_display_prefs_t g_display_prefs = {2, 0};
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
#define DISPLAYOUT(...) fprintf(stdout, __VA_ARGS__) #define DISPLAYOUT(...) fprintf(stdout, __VA_ARGS__)
#define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } } #define DISPLAYLEVEL(l, ...) { if (g_display_prefs.displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
static int g_displayLevel = 2; /* 0 : no display; 1: errors; 2: + result + interaction + warnings; 3: + progression; 4: + information */
void FIO_setNotificationLevel(unsigned level) { g_displayLevel=level; }
static const U64 g_refreshRate = SEC_TO_MICRO / 6; static const U64 g_refreshRate = SEC_TO_MICRO / 6;
static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
#define READY_FOR_UPDATE() (!g_noProgress && UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) #define READY_FOR_UPDATE() (!g_display_prefs.noProgress && UTIL_clockSpanMicro(g_displayClock) > g_refreshRate)
#define DELAY_NEXT_UPDATE() { g_displayClock = UTIL_getTime(); } #define DELAY_NEXT_UPDATE() { g_displayClock = UTIL_getTime(); }
#define DISPLAYUPDATE(l, ...) { \ #define DISPLAYUPDATE(l, ...) { \
if (g_displayLevel>=l && !g_noProgress) { \ if (g_display_prefs.displayLevel>=l && !g_display_prefs.noProgress) { \
if (READY_FOR_UPDATE() || (g_displayLevel>=4)) { \ if (READY_FOR_UPDATE() || (g_display_prefs.displayLevel>=4)) { \
DELAY_NEXT_UPDATE(); \ DELAY_NEXT_UPDATE(); \
DISPLAY(__VA_ARGS__); \ DISPLAY(__VA_ARGS__); \
if (g_displayLevel>=4) fflush(stderr); \ if (g_display_prefs.displayLevel>=4) fflush(stderr); \
} } } } } }
#undef MIN /* in case it would be already defined */ #undef MIN /* in case it would be already defined */
@@ -189,7 +196,7 @@ static void ABRThandler(int sig) {
const char* name; const char* name;
void* addrlist[MAX_STACK_FRAMES]; void* addrlist[MAX_STACK_FRAMES];
char** symbollist; char** symbollist;
U32 addrlen, i; int addrlen, i;
switch (sig) { switch (sig) {
case SIGABRT: name = "SIGABRT"; break; case SIGABRT: name = "SIGABRT"; break;
@@ -237,10 +244,13 @@ void FIO_addAbortHandler()
***************************************************************/ ***************************************************************/
#if defined(_MSC_VER) && _MSC_VER >= 1400 #if defined(_MSC_VER) && _MSC_VER >= 1400
# define LONG_SEEK _fseeki64 # define LONG_SEEK _fseeki64
# define LONG_TELL _ftelli64
#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ #elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */
# define LONG_SEEK fseeko # define LONG_SEEK fseeko
# define LONG_TELL ftello
#elif defined(__MINGW32__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) && defined(__MSVCRT__) #elif defined(__MINGW32__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) && defined(__MSVCRT__)
# define LONG_SEEK fseeko64 # define LONG_SEEK fseeko64
# define LONG_TELL ftello64
#elif defined(_WIN32) && !defined(__DJGPP__) #elif defined(_WIN32) && !defined(__DJGPP__)
# include <windows.h> # include <windows.h>
static int LONG_SEEK(FILE* file, __int64 offset, int origin) { static int LONG_SEEK(FILE* file, __int64 offset, int origin) {
@@ -261,100 +271,183 @@ void FIO_addAbortHandler()
} }
#else #else
# define LONG_SEEK fseek # define LONG_SEEK fseek
# define LONG_TELL ftell
#endif #endif
/*-************************************* /*-*************************************
* Local Parameters - Not thread safe * Parameters: Typedefs
***************************************/ ***************************************/
static FIO_compressionType_t g_compressionType = FIO_zstdCompression;
void FIO_setCompressionType(FIO_compressionType_t compressionType) { g_compressionType = compressionType; } struct FIO_prefs_s {
static U32 g_overwrite = 0;
void FIO_overwriteMode(void) { g_overwrite = 1; } /* Algorithm preferences */
static U32 g_sparseFileSupport = ZSTD_SPARSE_DEFAULT; /* 0: no sparse allowed; 1: auto (file yes, stdout no); 2: force sparse */ FIO_compressionType_t compressionType;
void FIO_setSparseWrite(unsigned sparse) { g_sparseFileSupport = sparse; } U32 sparseFileSupport; /* 0: no sparse allowed; 1: auto (file yes, stdout no); 2: force sparse */
static U32 g_dictIDFlag = 1; int dictIDFlag;
void FIO_setDictIDFlag(unsigned dictIDFlag) { g_dictIDFlag = dictIDFlag; } int checksumFlag;
static U32 g_checksumFlag = 1; int blockSize;
void FIO_setChecksumFlag(unsigned checksumFlag) { g_checksumFlag = checksumFlag; } int overlapLog;
static U32 g_removeSrcFile = 0; U32 adaptiveMode;
void FIO_setRemoveSrcFile(unsigned flag) { g_removeSrcFile = (flag>0); } int rsyncable;
static unsigned g_memLimit = 0; int minAdaptLevel;
void FIO_setMemLimit(unsigned memLimit) { g_memLimit = memLimit; } int maxAdaptLevel;
static unsigned g_nbWorkers = 1; int ldmFlag;
void FIO_setNbWorkers(unsigned nbWorkers) { int ldmHashLog;
int ldmMinMatch;
int ldmBucketSizeLog;
int ldmHashRateLog;
ZSTD_literalCompressionMode_e literalCompressionMode;
/* IO preferences */
U32 removeSrcFile;
U32 overwrite;
/* Computation resources preferences */
unsigned memLimit;
int nbWorkers;
};
/*-*************************************
* Parameters: Initialization
***************************************/
#define FIO_OVERLAP_LOG_NOTSET 9999
#define FIO_LDM_PARAM_NOTSET 9999
FIO_prefs_t* FIO_createPreferences(void)
{
FIO_prefs_t* const ret = (FIO_prefs_t*)malloc(sizeof(FIO_prefs_t));
if (!ret) EXM_THROW(21, "Allocation error : not enough memory");
ret->compressionType = FIO_zstdCompression;
ret->overwrite = 0;
ret->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
ret->dictIDFlag = 1;
ret->checksumFlag = 1;
ret->removeSrcFile = 0;
ret->memLimit = 0;
ret->nbWorkers = 1;
ret->blockSize = 0;
ret->overlapLog = FIO_OVERLAP_LOG_NOTSET;
ret->adaptiveMode = 0;
ret->rsyncable = 0;
ret->minAdaptLevel = -50; /* initializing this value requires a constant, so ZSTD_minCLevel() doesn't work */
ret->maxAdaptLevel = 22; /* initializing this value requires a constant, so ZSTD_maxCLevel() doesn't work */
ret->ldmFlag = 0;
ret->ldmHashLog = 0;
ret->ldmMinMatch = 0;
ret->ldmBucketSizeLog = FIO_LDM_PARAM_NOTSET;
ret->ldmHashRateLog = FIO_LDM_PARAM_NOTSET;
ret->literalCompressionMode = ZSTD_lcm_auto;
return ret;
}
void FIO_freePreferences(FIO_prefs_t* const prefs)
{
free(prefs);
}
/*-*************************************
* Parameters: Display Options
***************************************/
void FIO_setNotificationLevel(int level) { g_display_prefs.displayLevel=level; }
void FIO_setNoProgress(unsigned noProgress) { g_display_prefs.noProgress = noProgress; }
/*-*************************************
* Parameters: Setters
***************************************/
void FIO_setCompressionType(FIO_prefs_t* const prefs, FIO_compressionType_t compressionType) { prefs->compressionType = compressionType; }
void FIO_overwriteMode(FIO_prefs_t* const prefs) { prefs->overwrite = 1; }
void FIO_setSparseWrite(FIO_prefs_t* const prefs, unsigned sparse) { prefs->sparseFileSupport = sparse; }
void FIO_setDictIDFlag(FIO_prefs_t* const prefs, int dictIDFlag) { prefs->dictIDFlag = dictIDFlag; }
void FIO_setChecksumFlag(FIO_prefs_t* const prefs, int checksumFlag) { prefs->checksumFlag = checksumFlag; }
void FIO_setRemoveSrcFile(FIO_prefs_t* const prefs, unsigned flag) { prefs->removeSrcFile = (flag>0); }
void FIO_setMemLimit(FIO_prefs_t* const prefs, unsigned memLimit) { prefs->memLimit = memLimit; }
void FIO_setNbWorkers(FIO_prefs_t* const prefs, int nbWorkers) {
#ifndef ZSTD_MULTITHREAD #ifndef ZSTD_MULTITHREAD
if (nbWorkers > 0) DISPLAYLEVEL(2, "Note : multi-threading is disabled \n"); if (nbWorkers > 0) DISPLAYLEVEL(2, "Note : multi-threading is disabled \n");
#endif #endif
g_nbWorkers = nbWorkers; prefs->nbWorkers = nbWorkers;
} }
static U32 g_blockSize = 0;
void FIO_setBlockSize(unsigned blockSize) { void FIO_setBlockSize(FIO_prefs_t* const prefs, int blockSize) {
if (blockSize && g_nbWorkers==0) if (blockSize && prefs->nbWorkers==0)
DISPLAYLEVEL(2, "Setting block size is useless in single-thread mode \n"); DISPLAYLEVEL(2, "Setting block size is useless in single-thread mode \n");
g_blockSize = blockSize; prefs->blockSize = blockSize;
} }
#define FIO_OVERLAP_LOG_NOTSET 9999
static unsigned g_overlapLog = FIO_OVERLAP_LOG_NOTSET; void FIO_setOverlapLog(FIO_prefs_t* const prefs, int overlapLog){
void FIO_setOverlapLog(unsigned overlapLog){ if (overlapLog && prefs->nbWorkers==0)
if (overlapLog && g_nbWorkers==0)
DISPLAYLEVEL(2, "Setting overlapLog is useless in single-thread mode \n"); DISPLAYLEVEL(2, "Setting overlapLog is useless in single-thread mode \n");
g_overlapLog = overlapLog; prefs->overlapLog = overlapLog;
} }
static U32 g_adaptiveMode = 0;
void FIO_setAdaptiveMode(unsigned adapt) { void FIO_setAdaptiveMode(FIO_prefs_t* const prefs, unsigned adapt) {
if ((adapt>0) && (g_nbWorkers==0)) if ((adapt>0) && (prefs->nbWorkers==0))
EXM_THROW(1, "Adaptive mode is not compatible with single thread mode \n"); EXM_THROW(1, "Adaptive mode is not compatible with single thread mode \n");
g_adaptiveMode = adapt; prefs->adaptiveMode = adapt;
} }
static U32 g_rsyncable = 0;
void FIO_setRsyncable(unsigned rsyncable) { void FIO_setRsyncable(FIO_prefs_t* const prefs, int rsyncable) {
if ((rsyncable>0) && (g_nbWorkers==0)) if ((rsyncable>0) && (prefs->nbWorkers==0))
EXM_THROW(1, "Rsyncable mode is not compatible with single thread mode \n"); EXM_THROW(1, "Rsyncable mode is not compatible with single thread mode \n");
g_rsyncable = rsyncable; prefs->rsyncable = rsyncable;
} }
static int g_minAdaptLevel = -50; /* initializing this value requires a constant, so ZSTD_minCLevel() doesn't work */
void FIO_setAdaptMin(int minCLevel) void FIO_setLiteralCompressionMode(
FIO_prefs_t* const prefs,
ZSTD_literalCompressionMode_e mode) {
prefs->literalCompressionMode = mode;
}
void FIO_setAdaptMin(FIO_prefs_t* const prefs, int minCLevel)
{ {
#ifndef ZSTD_NOCOMPRESS #ifndef ZSTD_NOCOMPRESS
assert(minCLevel >= ZSTD_minCLevel()); assert(minCLevel >= ZSTD_minCLevel());
#endif #endif
g_minAdaptLevel = minCLevel; prefs->minAdaptLevel = minCLevel;
} }
static int g_maxAdaptLevel = 22; /* initializing this value requires a constant, so ZSTD_maxCLevel() doesn't work */
void FIO_setAdaptMax(int maxCLevel) void FIO_setAdaptMax(FIO_prefs_t* const prefs, int maxCLevel)
{ {
g_maxAdaptLevel = maxCLevel; prefs->maxAdaptLevel = maxCLevel;
} }
static U32 g_ldmFlag = 0; void FIO_setLdmFlag(FIO_prefs_t* const prefs, unsigned ldmFlag) {
void FIO_setLdmFlag(unsigned ldmFlag) { prefs->ldmFlag = (ldmFlag>0);
g_ldmFlag = (ldmFlag>0);
}
static U32 g_ldmHashLog = 0;
void FIO_setLdmHashLog(unsigned ldmHashLog) {
g_ldmHashLog = ldmHashLog;
}
static U32 g_ldmMinMatch = 0;
void FIO_setLdmMinMatch(unsigned ldmMinMatch) {
g_ldmMinMatch = ldmMinMatch;
} }
#define FIO_LDM_PARAM_NOTSET 9999 void FIO_setLdmHashLog(FIO_prefs_t* const prefs, int ldmHashLog) {
static U32 g_ldmBucketSizeLog = FIO_LDM_PARAM_NOTSET; prefs->ldmHashLog = ldmHashLog;
void FIO_setLdmBucketSizeLog(unsigned ldmBucketSizeLog) {
g_ldmBucketSizeLog = ldmBucketSizeLog;
} }
static U32 g_ldmHashRateLog = FIO_LDM_PARAM_NOTSET; void FIO_setLdmMinMatch(FIO_prefs_t* const prefs, int ldmMinMatch) {
void FIO_setLdmHashRateLog(unsigned ldmHashRateLog) { prefs->ldmMinMatch = ldmMinMatch;
g_ldmHashRateLog = ldmHashRateLog;
}
static U32 g_noProgress = 0;
void FIO_setNoProgress(unsigned noProgress) {
g_noProgress = noProgress;
} }
void FIO_setLdmBucketSizeLog(FIO_prefs_t* const prefs, int ldmBucketSizeLog) {
prefs->ldmBucketSizeLog = ldmBucketSizeLog;
}
void FIO_setLdmHashRateLog(FIO_prefs_t* const prefs, int ldmHashRateLog) {
prefs->ldmHashRateLog = ldmHashRateLog;
}
/*-************************************* /*-*************************************
@@ -410,45 +503,27 @@ static FILE* FIO_openSrcFile(const char* srcFileName)
/** FIO_openDstFile() : /** FIO_openDstFile() :
* condition : `dstFileName` must be non-NULL. * condition : `dstFileName` must be non-NULL.
* @result : FILE* to `dstFileName`, or NULL if it fails */ * @result : FILE* to `dstFileName`, or NULL if it fails */
static FILE* FIO_openDstFile(const char* srcFileName, const char* dstFileName) static FILE* FIO_openDstFile(FIO_prefs_t* const prefs, const char* srcFileName, const char* dstFileName)
{ {
assert(dstFileName != NULL); assert(dstFileName != NULL);
if (!strcmp (dstFileName, stdoutmark)) { if (!strcmp (dstFileName, stdoutmark)) {
DISPLAYLEVEL(4,"Using stdout for output \n"); DISPLAYLEVEL(4,"Using stdout for output \n");
SET_BINARY_MODE(stdout); SET_BINARY_MODE(stdout);
if (g_sparseFileSupport == 1) { if (prefs->sparseFileSupport == 1) {
g_sparseFileSupport = 0; prefs->sparseFileSupport = 0;
DISPLAYLEVEL(4, "Sparse File Support is automatically disabled on stdout ; try --sparse \n"); DISPLAYLEVEL(4, "Sparse File Support is automatically disabled on stdout ; try --sparse \n");
} }
return stdout; return stdout;
} }
/* ensure dst is not the same file as src */ /* ensure dst is not the same as src */
if (srcFileName != NULL) { if (srcFileName != NULL && UTIL_isSameFile(srcFileName, dstFileName)) {
#ifdef _MSC_VER DISPLAYLEVEL(1, "zstd: Refusing to open an output file which will overwrite the input file \n");
/* note : Visual does not support file identification by inode. return NULL;
* The following work-around is limited to detecting exact name repetition only,
* aka `filename` is considered different from `subdir/../filename` */
if (!strcmp(srcFileName, dstFileName)) {
DISPLAYLEVEL(1, "zstd: Refusing to open a output file which will overwrite the input file \n");
return NULL;
}
#else
stat_t srcStat;
stat_t dstStat;
if (UTIL_getFileStat(srcFileName, &srcStat)
&& UTIL_getFileStat(dstFileName, &dstStat)) {
if (srcStat.st_dev == dstStat.st_dev
&& srcStat.st_ino == dstStat.st_ino) {
DISPLAYLEVEL(1, "zstd: Refusing to open a output file which will overwrite the input file \n");
return NULL;
}
}
#endif
} }
if (g_sparseFileSupport == 1) { if (prefs->sparseFileSupport == 1) {
g_sparseFileSupport = ZSTD_SPARSE_DEFAULT; prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
} }
if (UTIL_isRegularFile(dstFileName)) { if (UTIL_isRegularFile(dstFileName)) {
@@ -460,8 +535,8 @@ static FILE* FIO_openDstFile(const char* srcFileName, const char* dstFileName)
} }
if (fCheck != NULL) { /* dst file exists, authorization prompt */ if (fCheck != NULL) { /* dst file exists, authorization prompt */
fclose(fCheck); fclose(fCheck);
if (!g_overwrite) { if (!prefs->overwrite) {
if (g_displayLevel <= 1) { if (g_display_prefs.displayLevel <= 1) {
/* No interaction possible */ /* No interaction possible */
DISPLAY("zstd: %s already exists; not overwritten \n", DISPLAY("zstd: %s already exists; not overwritten \n",
dstFileName); dstFileName);
@@ -536,10 +611,12 @@ typedef struct {
size_t srcBufferSize; size_t srcBufferSize;
void* dstBuffer; void* dstBuffer;
size_t dstBufferSize; size_t dstBufferSize;
const char* dictFileName;
ZSTD_CStream* cctx; ZSTD_CStream* cctx;
} cRess_t; } cRess_t;
static cRess_t FIO_createCResources(const char* dictFileName, int cLevel, static cRess_t FIO_createCResources(FIO_prefs_t* const prefs,
const char* dictFileName, int cLevel,
U64 srcSize, U64 srcSize,
ZSTD_compressionParameters comprParams) { ZSTD_compressionParameters comprParams) {
cRess_t ress; cRess_t ress;
@@ -562,43 +639,45 @@ static cRess_t FIO_createCResources(const char* dictFileName, int cLevel,
size_t const dictBuffSize = FIO_createDictBuffer(&dictBuffer, dictFileName); /* works with dictFileName==NULL */ size_t const dictBuffSize = FIO_createDictBuffer(&dictBuffer, dictFileName); /* works with dictFileName==NULL */
if (dictFileName && (dictBuffer==NULL)) if (dictFileName && (dictBuffer==NULL))
EXM_THROW(32, "allocation error : can't create dictBuffer"); EXM_THROW(32, "allocation error : can't create dictBuffer");
ress.dictFileName = dictFileName;
if (g_adaptiveMode && !g_ldmFlag && !comprParams.windowLog) if (prefs->adaptiveMode && !prefs->ldmFlag && !comprParams.windowLog)
comprParams.windowLog = ADAPT_WINDOWLOG_DEFAULT; comprParams.windowLog = ADAPT_WINDOWLOG_DEFAULT;
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, 1) ); /* always enable content size when available (note: supposed to be default) */ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, 1) ); /* always enable content size when available (note: supposed to be default) */
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, g_dictIDFlag) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, prefs->dictIDFlag) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, g_checksumFlag) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, prefs->checksumFlag) );
/* compression level */ /* compression level */
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) );
/* long distance matching */ /* long distance matching */
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableLongDistanceMatching, g_ldmFlag) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableLongDistanceMatching, prefs->ldmFlag) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashLog, g_ldmHashLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashLog, prefs->ldmHashLog) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmMinMatch, g_ldmMinMatch) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmMinMatch, prefs->ldmMinMatch) );
if (g_ldmBucketSizeLog != FIO_LDM_PARAM_NOTSET) { if (prefs->ldmBucketSizeLog != FIO_LDM_PARAM_NOTSET) {
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmBucketSizeLog, g_ldmBucketSizeLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmBucketSizeLog, prefs->ldmBucketSizeLog) );
} }
if (g_ldmHashRateLog != FIO_LDM_PARAM_NOTSET) { if (prefs->ldmHashRateLog != FIO_LDM_PARAM_NOTSET) {
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashRateLog, g_ldmHashRateLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashRateLog, prefs->ldmHashRateLog) );
} }
/* compression parameters */ /* compression parameters */
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowLog, comprParams.windowLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowLog, (int)comprParams.windowLog) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_chainLog, comprParams.chainLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_chainLog, (int)comprParams.chainLog) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_hashLog, comprParams.hashLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_hashLog, (int)comprParams.hashLog) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_searchLog, comprParams.searchLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_searchLog, (int)comprParams.searchLog) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_minMatch, comprParams.minMatch) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_minMatch, (int)comprParams.minMatch) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetLength, comprParams.targetLength) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetLength, (int)comprParams.targetLength) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_strategy, comprParams.strategy) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_strategy, comprParams.strategy) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_literalCompressionMode, (int)prefs->literalCompressionMode) );
/* multi-threading */ /* multi-threading */
#ifdef ZSTD_MULTITHREAD #ifdef ZSTD_MULTITHREAD
DISPLAYLEVEL(5,"set nb workers = %u \n", g_nbWorkers); DISPLAYLEVEL(5,"set nb workers = %u \n", prefs->nbWorkers);
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_nbWorkers, g_nbWorkers) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_nbWorkers, prefs->nbWorkers) );
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, g_blockSize) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, prefs->blockSize) );
if (g_overlapLog != FIO_OVERLAP_LOG_NOTSET) { if (prefs->overlapLog != FIO_OVERLAP_LOG_NOTSET) {
DISPLAYLEVEL(3,"set overlapLog = %u \n", g_overlapLog); DISPLAYLEVEL(3,"set overlapLog = %u \n", prefs->overlapLog);
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_overlapLog, g_overlapLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_overlapLog, prefs->overlapLog) );
} }
CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_rsyncable, g_rsyncable) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_rsyncable, prefs->rsyncable) );
#endif #endif
/* dictionary */ /* dictionary */
CHECK( ZSTD_CCtx_setPledgedSrcSize(ress.cctx, srcSize) ); /* set the value temporarily for dictionary loading, to adapt compression parameters */ CHECK( ZSTD_CCtx_setPledgedSrcSize(ress.cctx, srcSize) ); /* set the value temporarily for dictionary loading, to adapt compression parameters */
@@ -774,15 +853,19 @@ FIO_compressLzmaFrame(cRess_t* ress,
#endif #endif
#ifdef ZSTD_LZ4COMPRESS #ifdef ZSTD_LZ4COMPRESS
#if LZ4_VERSION_NUMBER <= 10600 #if LZ4_VERSION_NUMBER <= 10600
#define LZ4F_blockLinked blockLinked #define LZ4F_blockLinked blockLinked
#define LZ4F_max64KB max64KB #define LZ4F_max64KB max64KB
#endif #endif
static int FIO_LZ4_GetBlockSize_FromBlockId (int id) { return (1 << (8 + (2 * id))); } static int FIO_LZ4_GetBlockSize_FromBlockId (int id) { return (1 << (8 + (2 * id))); }
static unsigned long long static unsigned long long
FIO_compressLz4Frame(cRess_t* ress, FIO_compressLz4Frame(cRess_t* ress,
const char* srcFileName, U64 const srcFileSize, const char* srcFileName, U64 const srcFileSize,
int compressionLevel, U64* readsize) int compressionLevel, int checksumFlag,
U64* readsize)
{ {
const size_t blockSize = FIO_LZ4_GetBlockSize_FromBlockId(LZ4F_max64KB); const size_t blockSize = FIO_LZ4_GetBlockSize_FromBlockId(LZ4F_max64KB);
unsigned long long inFileSize = 0, outFileSize = 0; unsigned long long inFileSize = 0, outFileSize = 0;
@@ -802,7 +885,7 @@ FIO_compressLz4Frame(cRess_t* ress,
prefs.compressionLevel = compressionLevel; prefs.compressionLevel = compressionLevel;
prefs.frameInfo.blockMode = LZ4F_blockLinked; prefs.frameInfo.blockMode = LZ4F_blockLinked;
prefs.frameInfo.blockSizeID = LZ4F_max64KB; prefs.frameInfo.blockSizeID = LZ4F_max64KB;
prefs.frameInfo.contentChecksumFlag = (contentChecksum_t)g_checksumFlag; prefs.frameInfo.contentChecksumFlag = (contentChecksum_t)checksumFlag;
#if LZ4_VERSION_NUMBER >= 10600 #if LZ4_VERSION_NUMBER >= 10600
prefs.frameInfo.contentSize = (srcFileSize==UTIL_FILESIZE_UNKNOWN) ? 0 : srcFileSize; prefs.frameInfo.contentSize = (srcFileSize==UTIL_FILESIZE_UNKNOWN) ? 0 : srcFileSize;
#endif #endif
@@ -876,7 +959,8 @@ FIO_compressLz4Frame(cRess_t* ress,
static unsigned long long static unsigned long long
FIO_compressZstdFrame(const cRess_t* ressPtr, FIO_compressZstdFrame(FIO_prefs_t* const prefs,
const cRess_t* ressPtr,
const char* srcFileName, U64 fileSize, const char* srcFileName, U64 fileSize,
int compressionLevel, U64* readsize) int compressionLevel, U64* readsize)
{ {
@@ -947,7 +1031,7 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
double const cShare = (double)zfp.produced / (zfp.consumed + !zfp.consumed/*avoid div0*/) * 100; double const cShare = (double)zfp.produced / (zfp.consumed + !zfp.consumed/*avoid div0*/) * 100;
/* display progress notifications */ /* display progress notifications */
if (g_displayLevel >= 3) { if (g_display_prefs.displayLevel >= 3) {
DISPLAYUPDATE(3, "\r(L%i) Buffered :%4u MB - Consumed :%4u MB - Compressed :%4u MB => %.2f%% ", DISPLAYUPDATE(3, "\r(L%i) Buffered :%4u MB - Consumed :%4u MB - Compressed :%4u MB => %.2f%% ",
compressionLevel, compressionLevel,
(unsigned)((zfp.ingested - zfp.consumed) >> 20), (unsigned)((zfp.ingested - zfp.consumed) >> 20),
@@ -963,7 +1047,7 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
} }
/* adaptive mode : statistics measurement and speed correction */ /* adaptive mode : statistics measurement and speed correction */
if (g_adaptiveMode) { if (prefs->adaptiveMode) {
/* check output speed */ /* check output speed */
if (zfp.currentJobID > 1) { /* only possible if nbWorkers >= 1 */ if (zfp.currentJobID > 1) { /* only possible if nbWorkers >= 1 */
@@ -971,12 +1055,12 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
unsigned long long newlyProduced = zfp.produced - previous_zfp_update.produced; unsigned long long newlyProduced = zfp.produced - previous_zfp_update.produced;
unsigned long long newlyFlushed = zfp.flushed - previous_zfp_update.flushed; unsigned long long newlyFlushed = zfp.flushed - previous_zfp_update.flushed;
assert(zfp.produced >= previous_zfp_update.produced); assert(zfp.produced >= previous_zfp_update.produced);
assert(g_nbWorkers >= 1); assert(prefs->nbWorkers >= 1);
/* test if compression is blocked /* test if compression is blocked
* either because output is slow and all buffers are full * either because output is slow and all buffers are full
* or because input is slow and no job can start while waiting for at least one buffer to be filled. * or because input is slow and no job can start while waiting for at least one buffer to be filled.
* note : excluse starting part, since currentJobID > 1 */ * note : exclude starting part, since currentJobID > 1 */
if ( (zfp.consumed == previous_zfp_update.consumed) /* no data compressed : no data available, or no more buffer to compress to, OR compression is really slow (compression of a single block is slower than update rate)*/ if ( (zfp.consumed == previous_zfp_update.consumed) /* no data compressed : no data available, or no more buffer to compress to, OR compression is really slow (compression of a single block is slower than update rate)*/
&& (zfp.nbActiveWorkers == 0) /* confirmed : no compression ongoing */ && (zfp.nbActiveWorkers == 0) /* confirmed : no compression ongoing */
) { ) {
@@ -1000,7 +1084,7 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
DISPLAYLEVEL(6, "compression level adaptation check \n") DISPLAYLEVEL(6, "compression level adaptation check \n")
/* check input speed */ /* check input speed */
if (zfp.currentJobID > g_nbWorkers+1) { /* warm up period, to fill all workers */ if (zfp.currentJobID > (unsigned)(prefs->nbWorkers+1)) { /* warm up period, to fill all workers */
if (inputBlocked <= 0) { if (inputBlocked <= 0) {
DISPLAYLEVEL(6, "input is never blocked => input is slower than ingestion \n"); DISPLAYLEVEL(6, "input is never blocked => input is slower than ingestion \n");
speedChange = slower; speedChange = slower;
@@ -1032,14 +1116,14 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
DISPLAYLEVEL(6, "slower speed , higher compression \n") DISPLAYLEVEL(6, "slower speed , higher compression \n")
compressionLevel ++; compressionLevel ++;
if (compressionLevel > ZSTD_maxCLevel()) compressionLevel = ZSTD_maxCLevel(); if (compressionLevel > ZSTD_maxCLevel()) compressionLevel = ZSTD_maxCLevel();
if (compressionLevel > g_maxAdaptLevel) compressionLevel = g_maxAdaptLevel; if (compressionLevel > prefs->maxAdaptLevel) compressionLevel = prefs->maxAdaptLevel;
compressionLevel += (compressionLevel == 0); /* skip 0 */ 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) { if (speedChange == faster) {
DISPLAYLEVEL(6, "faster speed , lighter compression \n") DISPLAYLEVEL(6, "faster speed , lighter compression \n")
compressionLevel --; compressionLevel --;
if (compressionLevel < g_minAdaptLevel) compressionLevel = g_minAdaptLevel; if (compressionLevel < prefs->minAdaptLevel) compressionLevel = prefs->minAdaptLevel;
compressionLevel -= (compressionLevel == 0); /* skip 0 */ compressionLevel -= (compressionLevel == 0); /* skip 0 */
ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, compressionLevel); ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, compressionLevel);
} }
@@ -1069,7 +1153,8 @@ FIO_compressZstdFrame(const cRess_t* ressPtr,
* 1 : missing or pb opening srcFileName * 1 : missing or pb opening srcFileName
*/ */
static int static int
FIO_compressFilename_internal(cRess_t ress, FIO_compressFilename_internal(FIO_prefs_t* const prefs,
cRess_t ress,
const char* dstFileName, const char* srcFileName, const char* dstFileName, const char* srcFileName,
int compressionLevel) int compressionLevel)
{ {
@@ -1079,10 +1164,10 @@ FIO_compressFilename_internal(cRess_t ress,
DISPLAYLEVEL(5, "%s: %u bytes \n", srcFileName, (unsigned)fileSize); DISPLAYLEVEL(5, "%s: %u bytes \n", srcFileName, (unsigned)fileSize);
/* compression format selection */ /* compression format selection */
switch (g_compressionType) { switch (prefs->compressionType) {
default: default:
case FIO_zstdCompression: case FIO_zstdCompression:
compressedfilesize = FIO_compressZstdFrame(&ress, srcFileName, fileSize, compressionLevel, &readsize); compressedfilesize = FIO_compressZstdFrame(prefs, &ress, srcFileName, fileSize, compressionLevel, &readsize);
break; break;
case FIO_gzipCompression: case FIO_gzipCompression:
@@ -1098,7 +1183,7 @@ FIO_compressFilename_internal(cRess_t ress,
case FIO_xzCompression: case FIO_xzCompression:
case FIO_lzmaCompression: case FIO_lzmaCompression:
#ifdef ZSTD_LZMACOMPRESS #ifdef ZSTD_LZMACOMPRESS
compressedfilesize = FIO_compressLzmaFrame(&ress, srcFileName, fileSize, compressionLevel, &readsize, g_compressionType==FIO_lzmaCompression); compressedfilesize = FIO_compressLzmaFrame(&ress, srcFileName, fileSize, compressionLevel, &readsize, prefs->compressionType==FIO_lzmaCompression);
#else #else
(void)compressionLevel; (void)compressionLevel;
EXM_THROW(20, "zstd: %s: file cannot be compressed as xz/lzma (zstd compiled without ZSTD_LZMACOMPRESS) -- ignored \n", EXM_THROW(20, "zstd: %s: file cannot be compressed as xz/lzma (zstd compiled without ZSTD_LZMACOMPRESS) -- ignored \n",
@@ -1108,7 +1193,7 @@ FIO_compressFilename_internal(cRess_t ress,
case FIO_lz4Compression: case FIO_lz4Compression:
#ifdef ZSTD_LZ4COMPRESS #ifdef ZSTD_LZ4COMPRESS
compressedfilesize = FIO_compressLz4Frame(&ress, srcFileName, fileSize, compressionLevel, &readsize); compressedfilesize = FIO_compressLz4Frame(&ress, srcFileName, fileSize, compressionLevel, prefs->checksumFlag, &readsize);
#else #else
(void)compressionLevel; (void)compressionLevel;
EXM_THROW(20, "zstd: %s: file cannot be compressed as lz4 (zstd compiled without ZSTD_LZ4COMPRESS) -- ignored \n", EXM_THROW(20, "zstd: %s: file cannot be compressed as lz4 (zstd compiled without ZSTD_LZ4COMPRESS) -- ignored \n",
@@ -1138,7 +1223,8 @@ FIO_compressFilename_internal(cRess_t ress,
* @return : 0 : compression completed correctly, * @return : 0 : compression completed correctly,
* 1 : pb * 1 : pb
*/ */
static int FIO_compressFilename_dstFile(cRess_t ress, static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs,
cRess_t ress,
const char* dstFileName, const char* dstFileName,
const char* srcFileName, const char* srcFileName,
int compressionLevel) int compressionLevel)
@@ -1153,7 +1239,7 @@ static int FIO_compressFilename_dstFile(cRess_t ress,
if (ress.dstFile == NULL) { if (ress.dstFile == NULL) {
closeDstFile = 1; closeDstFile = 1;
DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s", dstFileName); DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s", dstFileName);
ress.dstFile = FIO_openDstFile(srcFileName, dstFileName); ress.dstFile = FIO_openDstFile(prefs, srcFileName, dstFileName);
if (ress.dstFile==NULL) return 1; /* could not open dstFileName */ if (ress.dstFile==NULL) return 1; /* could not open dstFileName */
/* Must only be added after FIO_openDstFile() succeeds. /* Must only be added after FIO_openDstFile() succeeds.
* Otherwise we may delete the destination file if it already exists, * Otherwise we may delete the destination file if it already exists,
@@ -1166,7 +1252,7 @@ static int FIO_compressFilename_dstFile(cRess_t ress,
transfer_permissions = 1; transfer_permissions = 1;
} }
result = FIO_compressFilename_internal(ress, dstFileName, srcFileName, compressionLevel); result = FIO_compressFilename_internal(prefs, ress, dstFileName, srcFileName, compressionLevel);
if (closeDstFile) { if (closeDstFile) {
FILE* const dstFile = ress.dstFile; FILE* const dstFile = ress.dstFile;
@@ -1199,27 +1285,34 @@ static int FIO_compressFilename_dstFile(cRess_t ress,
* 1 : missing or pb opening srcFileName * 1 : missing or pb opening srcFileName
*/ */
static int static int
FIO_compressFilename_srcFile(cRess_t ress, FIO_compressFilename_srcFile(FIO_prefs_t* const prefs,
cRess_t ress,
const char* dstFileName, const char* dstFileName,
const char* srcFileName, const char* srcFileName,
int compressionLevel) int compressionLevel)
{ {
int result; int result;
/* File check */ /* ensure src is not a directory */
if (UTIL_isDirectory(srcFileName)) { if (UTIL_isDirectory(srcFileName)) {
DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName); DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
return 1; return 1;
} }
/* ensure src is not the same as dict (if present) */
if (ress.dictFileName != NULL && UTIL_isSameFile(srcFileName, ress.dictFileName)) {
DISPLAYLEVEL(1, "zstd: cannot use %s as an input file and dictionary \n", srcFileName);
return 1;
}
ress.srcFile = FIO_openSrcFile(srcFileName); ress.srcFile = FIO_openSrcFile(srcFileName);
if (ress.srcFile == NULL) return 1; /* srcFile could not be opened */ if (ress.srcFile == NULL) return 1; /* srcFile could not be opened */
result = FIO_compressFilename_dstFile(ress, dstFileName, srcFileName, compressionLevel); result = FIO_compressFilename_dstFile(prefs, ress, dstFileName, srcFileName, compressionLevel);
fclose(ress.srcFile); fclose(ress.srcFile);
ress.srcFile = NULL; ress.srcFile = NULL;
if ( g_removeSrcFile /* --rm */ if ( prefs->removeSrcFile /* --rm */
&& result == 0 /* success */ && result == 0 /* success */
&& strcmp(srcFileName, stdinmark) /* exception : don't erase stdin */ && strcmp(srcFileName, stdinmark) /* exception : don't erase stdin */
) { ) {
@@ -1234,7 +1327,8 @@ FIO_compressFilename_srcFile(cRess_t ress,
} }
int FIO_compressFilename(const char* dstFileName, const char* srcFileName, int FIO_compressFilename(FIO_prefs_t* const prefs,
const char* dstFileName, const char* srcFileName,
const char* dictFileName, int compressionLevel, const char* dictFileName, int compressionLevel,
ZSTD_compressionParameters comprParams) ZSTD_compressionParameters comprParams)
{ {
@@ -1242,8 +1336,8 @@ int FIO_compressFilename(const char* dstFileName, const char* srcFileName,
U64 const fileSize = UTIL_getFileSize(srcFileName); U64 const fileSize = UTIL_getFileSize(srcFileName);
U64 const srcSize = (fileSize == UTIL_FILESIZE_UNKNOWN) ? ZSTD_CONTENTSIZE_UNKNOWN : fileSize; U64 const srcSize = (fileSize == UTIL_FILESIZE_UNKNOWN) ? ZSTD_CONTENTSIZE_UNKNOWN : fileSize;
cRess_t const ress = FIO_createCResources(dictFileName, compressionLevel, srcSize, comprParams); cRess_t const ress = FIO_createCResources(prefs, dictFileName, compressionLevel, srcSize, comprParams);
int const result = FIO_compressFilename_srcFile(ress, dstFileName, srcFileName, compressionLevel); int const result = FIO_compressFilename_srcFile(prefs, ress, dstFileName, srcFileName, compressionLevel);
double const seconds = (double)(clock() - start) / CLOCKS_PER_SEC; double const seconds = (double)(clock() - start) / CLOCKS_PER_SEC;
DISPLAYLEVEL(4, "Completed in %.2f sec \n", seconds); DISPLAYLEVEL(4, "Completed in %.2f sec \n", seconds);
@@ -1288,7 +1382,8 @@ FIO_determineCompressedName(const char* srcFileName, const char* suffix)
* into one destination (outFileName) * into one destination (outFileName)
* or into one file each (outFileName == NULL, but suffix != NULL). * or into one file each (outFileName == NULL, but suffix != NULL).
*/ */
int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFiles, int FIO_compressMultipleFilenames(FIO_prefs_t* const prefs,
const char** inFileNamesTable, unsigned nbFiles,
const char* outFileName, const char* suffix, const char* outFileName, const char* suffix,
const char* dictFileName, int compressionLevel, const char* dictFileName, int compressionLevel,
ZSTD_compressionParameters comprParams) ZSTD_compressionParameters comprParams)
@@ -1297,19 +1392,19 @@ int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFile
U64 const firstFileSize = UTIL_getFileSize(inFileNamesTable[0]); U64 const firstFileSize = UTIL_getFileSize(inFileNamesTable[0]);
U64 const firstSrcSize = (firstFileSize == UTIL_FILESIZE_UNKNOWN) ? ZSTD_CONTENTSIZE_UNKNOWN : firstFileSize; U64 const firstSrcSize = (firstFileSize == UTIL_FILESIZE_UNKNOWN) ? ZSTD_CONTENTSIZE_UNKNOWN : firstFileSize;
U64 const srcSize = (nbFiles != 1) ? ZSTD_CONTENTSIZE_UNKNOWN : firstSrcSize ; U64 const srcSize = (nbFiles != 1) ? ZSTD_CONTENTSIZE_UNKNOWN : firstSrcSize ;
cRess_t ress = FIO_createCResources(dictFileName, compressionLevel, srcSize, comprParams); cRess_t ress = FIO_createCResources(prefs, dictFileName, compressionLevel, srcSize, comprParams);
/* init */ /* init */
assert(outFileName != NULL || suffix != NULL); assert(outFileName != NULL || suffix != NULL);
if (outFileName != NULL) { /* output into a single destination (stdout typically) */ if (outFileName != NULL) { /* output into a single destination (stdout typically) */
ress.dstFile = FIO_openDstFile(NULL, outFileName); ress.dstFile = FIO_openDstFile(prefs, NULL, outFileName);
if (ress.dstFile == NULL) { /* could not open outFileName */ if (ress.dstFile == NULL) { /* could not open outFileName */
error = 1; error = 1;
} else { } else {
unsigned u; unsigned u;
for (u=0; u<nbFiles; u++) for (u=0; u<nbFiles; u++)
error |= FIO_compressFilename_srcFile(ress, outFileName, inFileNamesTable[u], compressionLevel); error |= FIO_compressFilename_srcFile(prefs, ress, outFileName, inFileNamesTable[u], compressionLevel);
if (fclose(ress.dstFile)) if (fclose(ress.dstFile))
EXM_THROW(29, "Write error (%s) : cannot properly close %s", EXM_THROW(29, "Write error (%s) : cannot properly close %s",
strerror(errno), outFileName); strerror(errno), outFileName);
@@ -1320,7 +1415,7 @@ int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFile
for (u=0; u<nbFiles; u++) { for (u=0; u<nbFiles; u++) {
const char* const srcFileName = inFileNamesTable[u]; const char* const srcFileName = inFileNamesTable[u];
const char* const dstFileName = FIO_determineCompressedName(srcFileName, suffix); /* cannot fail */ const char* const dstFileName = FIO_determineCompressedName(srcFileName, suffix); /* cannot fail */
error |= FIO_compressFilename_srcFile(ress, dstFileName, srcFileName, compressionLevel); error |= FIO_compressFilename_srcFile(prefs, ress, dstFileName, srcFileName, compressionLevel);
} } } }
FIO_freeCResources(ress); FIO_freeCResources(ress);
@@ -1346,7 +1441,7 @@ typedef struct {
FILE* dstFile; FILE* dstFile;
} dRess_t; } dRess_t;
static dRess_t FIO_createDResources(const char* dictFileName) static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFileName)
{ {
dRess_t ress; dRess_t ress;
memset(&ress, 0, sizeof(ress)); memset(&ress, 0, sizeof(ress));
@@ -1355,7 +1450,7 @@ static dRess_t FIO_createDResources(const char* dictFileName)
ress.dctx = ZSTD_createDStream(); ress.dctx = ZSTD_createDStream();
if (ress.dctx==NULL) if (ress.dctx==NULL)
EXM_THROW(60, "Error: %s : can't create ZSTD_DStream", strerror(errno)); EXM_THROW(60, "Error: %s : can't create ZSTD_DStream", strerror(errno));
CHECK( ZSTD_DCtx_setMaxWindowSize(ress.dctx, g_memLimit) ); CHECK( ZSTD_DCtx_setMaxWindowSize(ress.dctx, prefs->memLimit) );
ress.srcBufferSize = ZSTD_DStreamInSize(); ress.srcBufferSize = ZSTD_DStreamInSize();
ress.srcBuffer = malloc(ress.srcBufferSize); ress.srcBuffer = malloc(ress.srcBufferSize);
ress.dstBufferSize = ZSTD_DStreamOutSize(); ress.dstBufferSize = ZSTD_DStreamOutSize();
@@ -1383,7 +1478,7 @@ static void FIO_freeDResources(dRess_t ress)
/** FIO_fwriteSparse() : /** FIO_fwriteSparse() :
* @return : storedSkips, to be provided to next call to FIO_fwriteSparse() of LZ4IO_fwriteSparseEnd() */ * @return : storedSkips, to be provided to next call to FIO_fwriteSparse() of LZ4IO_fwriteSparseEnd() */
static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSize, unsigned storedSkips) static unsigned FIO_fwriteSparse(FIO_prefs_t* const prefs, FILE* file, const void* buffer, size_t bufferSize, unsigned storedSkips)
{ {
const size_t* const bufferT = (const size_t*)buffer; /* Buffer is supposed malloc'ed, hence aligned on size_t */ 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); size_t bufferSizeT = bufferSize / sizeof(size_t);
@@ -1391,7 +1486,7 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
const size_t* ptrT = bufferT; const size_t* ptrT = bufferT;
static const size_t segmentSizeT = (32 KB) / sizeof(size_t); /* 0-test re-attempted every 32 KB */ static const size_t segmentSizeT = (32 KB) / sizeof(size_t); /* 0-test re-attempted every 32 KB */
if (!g_sparseFileSupport) { /* normal write */ if (!prefs->sparseFileSupport) { /* normal write */
size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file); size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file);
if (sizeCheck != bufferSize) if (sizeCheck != bufferSize)
EXM_THROW(70, "Write error : %s (cannot write decoded block)", EXM_THROW(70, "Write error : %s (cannot write decoded block)",
@@ -1444,7 +1539,7 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
if (seekResult) if (seekResult)
EXM_THROW(74, "Sparse skip error ; try --no-sparse"); EXM_THROW(74, "Sparse skip error ; try --no-sparse");
storedSkips = 0; storedSkips = 0;
{ size_t const sizeCheck = fwrite(restPtr, 1, restEnd - restPtr, file); { size_t const sizeCheck = fwrite(restPtr, 1, (size_t)(restEnd - restPtr), file);
if (sizeCheck != (size_t)(restEnd - restPtr)) if (sizeCheck != (size_t)(restEnd - restPtr))
EXM_THROW(75, "Write error : cannot write decoded end of block"); EXM_THROW(75, "Write error : cannot write decoded end of block");
} } } } } } } }
@@ -1452,10 +1547,12 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
return storedSkips; return storedSkips;
} }
static void FIO_fwriteSparseEnd(FILE* file, unsigned storedSkips) static void
FIO_fwriteSparseEnd(FIO_prefs_t* const prefs, FILE* file, unsigned storedSkips)
{ {
if (storedSkips>0) { if (storedSkips>0) {
assert(g_sparseFileSupport > 0); /* storedSkips>0 implies sparse support is enabled */ assert(prefs->sparseFileSupport > 0); /* storedSkips>0 implies sparse support is enabled */
(void)prefs; /* assert can be disabled, in which case prefs becomes unused */
if (LONG_SEEK(file, storedSkips-1, SEEK_CUR) != 0) if (LONG_SEEK(file, storedSkips-1, SEEK_CUR) != 0)
EXM_THROW(69, "Final skip error (sparse file support)"); EXM_THROW(69, "Final skip error (sparse file support)");
/* last zero must be explicitly written, /* last zero must be explicitly written,
@@ -1469,7 +1566,10 @@ static void FIO_fwriteSparseEnd(FILE* file, unsigned storedSkips)
/** FIO_passThrough() : just copy input into output, for compatibility with gzip -df mode /** FIO_passThrough() : just copy input into output, for compatibility with gzip -df mode
@return : 0 (no error) */ @return : 0 (no error) */
static unsigned FIO_passThrough(FILE* foutput, FILE* finput, void* buffer, size_t bufferSize, size_t alreadyLoaded) static int FIO_passThrough(FIO_prefs_t* const prefs,
FILE* foutput, FILE* finput,
void* buffer, size_t bufferSize,
size_t alreadyLoaded)
{ {
size_t const blockSize = MIN(64 KB, bufferSize); size_t const blockSize = MIN(64 KB, bufferSize);
size_t readFromInput = 1; size_t readFromInput = 1;
@@ -1484,10 +1584,10 @@ static unsigned FIO_passThrough(FILE* foutput, FILE* finput, void* buffer, size_
while (readFromInput) { while (readFromInput) {
readFromInput = fread(buffer, 1, blockSize, finput); readFromInput = fread(buffer, 1, blockSize, finput);
storedSkips = FIO_fwriteSparse(foutput, buffer, readFromInput, storedSkips); storedSkips = FIO_fwriteSparse(prefs, foutput, buffer, readFromInput, storedSkips);
} }
FIO_fwriteSparseEnd(foutput, storedSkips); FIO_fwriteSparseEnd(prefs, foutput, storedSkips);
return 0; return 0;
} }
@@ -1506,7 +1606,7 @@ static unsigned FIO_highbit64(unsigned long long v)
/* FIO_zstdErrorHelp() : /* FIO_zstdErrorHelp() :
* detailed error message when requested window size is too large */ * detailed error message when requested window size is too large */
static void FIO_zstdErrorHelp(dRess_t* ress, size_t err, char const* srcFileName) static void FIO_zstdErrorHelp(FIO_prefs_t* const prefs, dRess_t* ress, size_t err, char const* srcFileName)
{ {
ZSTD_frameHeader header; ZSTD_frameHeader header;
@@ -1519,9 +1619,9 @@ static void FIO_zstdErrorHelp(dRess_t* ress, size_t err, char const* srcFileName
if (err == 0) { if (err == 0) {
unsigned long long const windowSize = header.windowSize; unsigned long long const windowSize = header.windowSize;
unsigned const windowLog = FIO_highbit64(windowSize) + ((windowSize & (windowSize - 1)) != 0); unsigned const windowLog = FIO_highbit64(windowSize) + ((windowSize & (windowSize - 1)) != 0);
assert(g_memLimit > 0); assert(prefs->memLimit > 0);
DISPLAYLEVEL(1, "%s : Window size larger than maximum : %llu > %u\n", DISPLAYLEVEL(1, "%s : Window size larger than maximum : %llu > %u\n",
srcFileName, windowSize, g_memLimit); srcFileName, windowSize, prefs->memLimit);
if (windowLog <= ZSTD_WINDOWLOG_MAX) { if (windowLog <= ZSTD_WINDOWLOG_MAX) {
unsigned const windowMB = (unsigned)((windowSize >> 20) + ((windowSize & ((1 MB) - 1)) != 0)); unsigned const windowMB = (unsigned)((windowSize >> 20) + ((windowSize & ((1 MB) - 1)) != 0));
assert(windowSize < (U64)(1ULL << 52)); /* ensure now overflow for windowMB */ assert(windowSize < (U64)(1ULL << 52)); /* ensure now overflow for windowMB */
@@ -1538,7 +1638,9 @@ static void FIO_zstdErrorHelp(dRess_t* ress, size_t err, char const* srcFileName
* @return : size of decoded zstd frame, or an error code * @return : size of decoded zstd frame, or an error code
*/ */
#define FIO_ERROR_FRAME_DECODING ((unsigned long long)(-2)) #define FIO_ERROR_FRAME_DECODING ((unsigned long long)(-2))
static unsigned long long FIO_decompressZstdFrame(dRess_t* ress, static unsigned long long FIO_decompressZstdFrame(
FIO_prefs_t* const prefs,
dRess_t* ress,
FILE* finput, FILE* finput,
const char* srcFileName, const char* srcFileName,
U64 alreadyDecoded) U64 alreadyDecoded)
@@ -1567,12 +1669,12 @@ static unsigned long long FIO_decompressZstdFrame(dRess_t* ress,
if (ZSTD_isError(readSizeHint)) { if (ZSTD_isError(readSizeHint)) {
DISPLAYLEVEL(1, "%s : Decoding error (36) : %s \n", DISPLAYLEVEL(1, "%s : Decoding error (36) : %s \n",
srcFileName, ZSTD_getErrorName(readSizeHint)); srcFileName, ZSTD_getErrorName(readSizeHint));
FIO_zstdErrorHelp(ress, readSizeHint, srcFileName); FIO_zstdErrorHelp(prefs, ress, readSizeHint, srcFileName);
return FIO_ERROR_FRAME_DECODING; return FIO_ERROR_FRAME_DECODING;
} }
/* Write block */ /* Write block */
storedSkips = FIO_fwriteSparse(ress->dstFile, ress->dstBuffer, outBuff.pos, storedSkips); storedSkips = FIO_fwriteSparse(prefs, ress->dstFile, ress->dstBuffer, outBuff.pos, storedSkips);
frameSize += outBuff.pos; frameSize += outBuff.pos;
DISPLAYUPDATE(2, "\r%-20.20s : %u MB... ", DISPLAYUPDATE(2, "\r%-20.20s : %u MB... ",
srcFileName, (unsigned)((alreadyDecoded+frameSize)>>20) ); srcFileName, (unsigned)((alreadyDecoded+frameSize)>>20) );
@@ -1603,7 +1705,7 @@ static unsigned long long FIO_decompressZstdFrame(dRess_t* ress,
ress->srcBufferLoaded += readSize; ress->srcBufferLoaded += readSize;
} } } } } }
FIO_fwriteSparseEnd(ress->dstFile, storedSkips); FIO_fwriteSparseEnd(prefs, ress->dstFile, storedSkips);
return frameSize; return frameSize;
} }
@@ -1834,7 +1936,7 @@ static unsigned long long FIO_decompressLz4Frame(dRess_t* ress,
* @return : 0 : OK * @return : 0 : OK
* 1 : error * 1 : error
*/ */
static int FIO_decompressFrames(dRess_t ress, FILE* srcFile, static int FIO_decompressFrames(FIO_prefs_t* const prefs, dRess_t ress, FILE* srcFile,
const char* dstFileName, const char* srcFileName) const char* dstFileName, const char* srcFileName)
{ {
unsigned readSomething = 0; unsigned readSomething = 0;
@@ -1862,7 +1964,7 @@ static int FIO_decompressFrames(dRess_t ress, FILE* srcFile,
return 1; return 1;
} }
if (ZSTD_isFrame(buf, ress.srcBufferLoaded)) { if (ZSTD_isFrame(buf, ress.srcBufferLoaded)) {
unsigned long long const frameSize = FIO_decompressZstdFrame(&ress, srcFile, srcFileName, filesize); unsigned long long const frameSize = FIO_decompressZstdFrame(prefs, &ress, srcFile, srcFileName, filesize);
if (frameSize == FIO_ERROR_FRAME_DECODING) return 1; if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;
filesize += frameSize; filesize += frameSize;
} else if (buf[0] == 31 && buf[1] == 139) { /* gz magic number */ } else if (buf[0] == 31 && buf[1] == 139) { /* gz magic number */
@@ -1893,9 +1995,11 @@ static int FIO_decompressFrames(dRess_t ress, FILE* srcFile,
DISPLAYLEVEL(1, "zstd: %s: lz4 file cannot be uncompressed (zstd compiled without HAVE_LZ4) -- ignored \n", srcFileName); DISPLAYLEVEL(1, "zstd: %s: lz4 file cannot be uncompressed (zstd compiled without HAVE_LZ4) -- ignored \n", srcFileName);
return 1; return 1;
#endif #endif
} else if ((g_overwrite) && !strcmp (dstFileName, stdoutmark)) { /* pass-through mode */ } else if ((prefs->overwrite) && !strcmp (dstFileName, stdoutmark)) { /* pass-through mode */
return FIO_passThrough(ress.dstFile, srcFile, return FIO_passThrough(prefs,
ress.srcBuffer, ress.srcBufferSize, ress.srcBufferLoaded); ress.dstFile, srcFile,
ress.srcBuffer, ress.srcBufferSize,
ress.srcBufferLoaded);
} else { } else {
DISPLAYLEVEL(1, "zstd: %s: unsupported format \n", srcFileName); DISPLAYLEVEL(1, "zstd: %s: unsupported format \n", srcFileName);
return 1; return 1;
@@ -1915,7 +2019,8 @@ static int FIO_decompressFrames(dRess_t ress, FILE* srcFile,
@return : 0 : OK @return : 0 : OK
1 : operation aborted 1 : operation aborted
*/ */
static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile, static int FIO_decompressDstFile(FIO_prefs_t* const prefs,
dRess_t ress, FILE* srcFile,
const char* dstFileName, const char* srcFileName) const char* dstFileName, const char* srcFileName)
{ {
int result; int result;
@@ -1926,7 +2031,7 @@ static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile,
if (ress.dstFile == NULL) { if (ress.dstFile == NULL) {
releaseDstFile = 1; releaseDstFile = 1;
ress.dstFile = FIO_openDstFile(srcFileName, dstFileName); ress.dstFile = FIO_openDstFile(prefs, srcFileName, dstFileName);
if (ress.dstFile==0) return 1; if (ress.dstFile==0) return 1;
/* Must only be added after FIO_openDstFile() succeeds. /* Must only be added after FIO_openDstFile() succeeds.
@@ -1941,7 +2046,7 @@ static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile,
} }
result = FIO_decompressFrames(ress, srcFile, dstFileName, srcFileName); result = FIO_decompressFrames(prefs, ress, srcFile, dstFileName, srcFileName);
if (releaseDstFile) { if (releaseDstFile) {
FILE* const dstFile = ress.dstFile; FILE* const dstFile = ress.dstFile;
@@ -1974,7 +2079,7 @@ static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile,
@return : 0 : OK @return : 0 : OK
1 : error 1 : error
*/ */
static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const char* srcFileName) static int FIO_decompressSrcFile(FIO_prefs_t* const prefs, dRess_t ress, const char* dstFileName, const char* srcFileName)
{ {
FILE* srcFile; FILE* srcFile;
int result; int result;
@@ -1988,14 +2093,14 @@ static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const ch
if (srcFile==NULL) return 1; if (srcFile==NULL) return 1;
ress.srcBufferLoaded = 0; ress.srcBufferLoaded = 0;
result = FIO_decompressDstFile(ress, srcFile, dstFileName, srcFileName); result = FIO_decompressDstFile(prefs, ress, srcFile, dstFileName, srcFileName);
/* Close file */ /* Close file */
if (fclose(srcFile)) { if (fclose(srcFile)) {
DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno)); /* error should not happen */ DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno)); /* error should not happen */
return 1; return 1;
} }
if ( g_removeSrcFile /* --rm */ if ( prefs->removeSrcFile /* --rm */
&& (result==0) /* decompression successful */ && (result==0) /* decompression successful */
&& strcmp(srcFileName, stdinmark) ) /* not stdin */ { && strcmp(srcFileName, stdinmark) ) /* not stdin */ {
/* We must clear the handler, since after this point calling it would /* We must clear the handler, since after this point calling it would
@@ -2012,12 +2117,13 @@ static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const ch
int FIO_decompressFilename(const char* dstFileName, const char* srcFileName, int FIO_decompressFilename(FIO_prefs_t* const prefs,
const char* dstFileName, const char* srcFileName,
const char* dictFileName) const char* dictFileName)
{ {
dRess_t const ress = FIO_createDResources(dictFileName); dRess_t const ress = FIO_createDResources(prefs, dictFileName);
int const decodingError = FIO_decompressSrcFile(ress, dstFileName, srcFileName); int const decodingError = FIO_decompressSrcFile(prefs, ress, dstFileName, srcFileName);
FIO_freeDResources(ress); FIO_freeDResources(ress);
return decodingError; return decodingError;
@@ -2094,19 +2200,20 @@ FIO_determineDstName(const char* srcFileName)
int int
FIO_decompressMultipleFilenames(const char* srcNamesTable[], unsigned nbFiles, FIO_decompressMultipleFilenames(FIO_prefs_t* const prefs,
const char* srcNamesTable[], unsigned nbFiles,
const char* outFileName, const char* outFileName,
const char* dictFileName) const char* dictFileName)
{ {
int error = 0; int error = 0;
dRess_t ress = FIO_createDResources(dictFileName); dRess_t ress = FIO_createDResources(prefs, dictFileName);
if (outFileName) { if (outFileName) {
unsigned u; unsigned u;
ress.dstFile = FIO_openDstFile(NULL, outFileName); ress.dstFile = FIO_openDstFile(prefs, NULL, outFileName);
if (ress.dstFile == 0) EXM_THROW(71, "cannot open %s", outFileName); if (ress.dstFile == 0) EXM_THROW(71, "cannot open %s", outFileName);
for (u=0; u<nbFiles; u++) for (u=0; u<nbFiles; u++)
error |= FIO_decompressSrcFile(ress, outFileName, srcNamesTable[u]); error |= FIO_decompressSrcFile(prefs, ress, outFileName, srcNamesTable[u]);
if (fclose(ress.dstFile)) if (fclose(ress.dstFile))
EXM_THROW(72, "Write error : %s : cannot properly close output file", EXM_THROW(72, "Write error : %s : cannot properly close output file",
strerror(errno)); strerror(errno));
@@ -2117,7 +2224,7 @@ FIO_decompressMultipleFilenames(const char* srcNamesTable[], unsigned nbFiles,
const char* const dstFileName = FIO_determineDstName(srcFileName); const char* const dstFileName = FIO_determineDstName(srcFileName);
if (dstFileName == NULL) { error=1; continue; } if (dstFileName == NULL) { error=1; continue; }
error |= FIO_decompressSrcFile(ress, dstFileName, srcFileName); error |= FIO_decompressSrcFile(prefs, ress, dstFileName, srcFileName);
} }
} }
@@ -2142,7 +2249,13 @@ typedef struct {
U32 nbFiles; U32 nbFiles;
} fileInfo_t; } fileInfo_t;
typedef enum { info_success=0, info_frame_error=1, info_not_zstd=2, info_file_error=3 } InfoError; typedef enum {
info_success=0,
info_frame_error=1,
info_not_zstd=2,
info_file_error=3,
info_truncated_input=4,
} InfoError;
#define ERROR_IF(c,n,...) { \ #define ERROR_IF(c,n,...) { \
if (c) { \ if (c) { \
@@ -2164,6 +2277,12 @@ FIO_analyzeFrames(fileInfo_t* info, FILE* const srcFile)
&& (numBytesRead == 0) && (numBytesRead == 0)
&& (info->compressedSize > 0) && (info->compressedSize > 0)
&& (info->compressedSize != UTIL_FILESIZE_UNKNOWN) ) { && (info->compressedSize != UTIL_FILESIZE_UNKNOWN) ) {
unsigned long long file_position = (unsigned long long) LONG_TELL(srcFile);
unsigned long long file_size = (unsigned long long) info->compressedSize;
ERROR_IF(file_position != file_size, info_truncated_input,
"Error: seeked to position %llu, which is beyond file size of %llu\n",
file_position,
file_size);
break; /* correct end of file => success */ break; /* correct end of file => success */
} }
ERROR_IF(feof(srcFile), info_not_zstd, "Error: reached end of file with incomplete frame"); ERROR_IF(feof(srcFile), info_not_zstd, "Error: reached end of file with incomplete frame");
@@ -2332,20 +2451,28 @@ FIO_listFile(fileInfo_t* total, const char* inFileName, int displayLevel)
fileInfo_t info; fileInfo_t info;
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
{ InfoError const error = getFileInfo(&info, inFileName); { InfoError const error = getFileInfo(&info, inFileName);
if (error == info_frame_error) { switch (error) {
/* display error, but provide output */ case info_frame_error:
DISPLAYLEVEL(1, "Error while parsing %s \n", inFileName); /* display error, but provide output */
} DISPLAYLEVEL(1, "Error while parsing \"%s\" \n", inFileName);
else if (error == info_not_zstd) { break;
DISPLAYOUT("File %s not compressed by zstd \n", inFileName); case info_not_zstd:
if (displayLevel > 2) DISPLAYOUT("\n"); DISPLAYOUT("File \"%s\" not compressed by zstd \n", inFileName);
return 1; if (displayLevel > 2) DISPLAYOUT("\n");
} return 1;
else if (error == info_file_error) { case info_file_error:
/* error occurred while opening the file */ /* error occurred while opening the file */
if (displayLevel > 2) DISPLAYOUT("\n"); if (displayLevel > 2) DISPLAYOUT("\n");
return 1; return 1;
case info_truncated_input:
DISPLAYOUT("File \"%s\" is truncated \n", inFileName);
if (displayLevel > 2) DISPLAYOUT("\n");
return 1;
case info_success:
default:
break;
} }
displayInfo(inFileName, &info, displayLevel); displayInfo(inFileName, &info, displayLevel);
*total = FIO_addFInfo(*total, info); *total = FIO_addFInfo(*total, info);
assert(error == info_success || error == info_frame_error); assert(error == info_success || error == info_frame_error);
+38 -25
View File
@@ -42,44 +42,55 @@ extern "C" {
***************************************/ ***************************************/
typedef enum { FIO_zstdCompression, FIO_gzipCompression, FIO_xzCompression, FIO_lzmaCompression, FIO_lz4Compression } FIO_compressionType_t; typedef enum { FIO_zstdCompression, FIO_gzipCompression, FIO_xzCompression, FIO_lzmaCompression, FIO_lz4Compression } FIO_compressionType_t;
typedef struct FIO_prefs_s FIO_prefs_t;
FIO_prefs_t* FIO_createPreferences(void);
void FIO_freePreferences(FIO_prefs_t* const prefs);
typedef struct FIO_display_prefs_s FIO_display_prefs_t;
/*-************************************* /*-*************************************
* Parameters * Parameters
***************************************/ ***************************************/
void FIO_setCompressionType(FIO_compressionType_t compressionType); void FIO_setCompressionType(FIO_prefs_t* const prefs, FIO_compressionType_t compressionType);
void FIO_overwriteMode(void); void FIO_overwriteMode(FIO_prefs_t* const prefs);
void FIO_setAdaptiveMode(unsigned adapt); void FIO_setAdaptiveMode(FIO_prefs_t* const prefs, unsigned adapt);
void FIO_setAdaptMin(int minCLevel); void FIO_setAdaptMin(FIO_prefs_t* const prefs, int minCLevel);
void FIO_setAdaptMax(int maxCLevel); void FIO_setAdaptMax(FIO_prefs_t* const prefs, int maxCLevel);
void FIO_setBlockSize(unsigned blockSize); void FIO_setBlockSize(FIO_prefs_t* const prefs, int blockSize);
void FIO_setChecksumFlag(unsigned checksumFlag); void FIO_setChecksumFlag(FIO_prefs_t* const prefs, int checksumFlag);
void FIO_setDictIDFlag(unsigned dictIDFlag); void FIO_setDictIDFlag(FIO_prefs_t* const prefs, int dictIDFlag);
void FIO_setLdmBucketSizeLog(unsigned ldmBucketSizeLog); void FIO_setLdmBucketSizeLog(FIO_prefs_t* const prefs, int ldmBucketSizeLog);
void FIO_setLdmFlag(unsigned ldmFlag); void FIO_setLdmFlag(FIO_prefs_t* const prefs, unsigned ldmFlag);
void FIO_setLdmHashRateLog(unsigned ldmHashRateLog); void FIO_setLdmHashRateLog(FIO_prefs_t* const prefs, int ldmHashRateLog);
void FIO_setLdmHashLog(unsigned ldmHashLog); void FIO_setLdmHashLog(FIO_prefs_t* const prefs, int ldmHashLog);
void FIO_setLdmMinMatch(unsigned ldmMinMatch); void FIO_setLdmMinMatch(FIO_prefs_t* const prefs, int ldmMinMatch);
void FIO_setMemLimit(unsigned memLimit); void FIO_setMemLimit(FIO_prefs_t* const prefs, unsigned memLimit);
void FIO_setNbWorkers(unsigned nbWorkers); void FIO_setNbWorkers(FIO_prefs_t* const prefs, int nbWorkers);
void FIO_setNotificationLevel(unsigned level); void FIO_setOverlapLog(FIO_prefs_t* const prefs, int overlapLog);
void FIO_setOverlapLog(unsigned overlapLog); void FIO_setRemoveSrcFile(FIO_prefs_t* const prefs, unsigned flag);
void FIO_setRemoveSrcFile(unsigned flag); void FIO_setSparseWrite(FIO_prefs_t* const prefs, unsigned sparse); /**< 0: no sparse; 1: disable on stdout; 2: always enabled */
void FIO_setSparseWrite(unsigned sparse); /**< 0: no sparse; 1: disable on stdout; 2: always enabled */ void FIO_setRsyncable(FIO_prefs_t* const prefs, int rsyncable);
void FIO_setRsyncable(unsigned rsyncable); void FIO_setLiteralCompressionMode(
void FIO_setNoProgress(unsigned noProgress); FIO_prefs_t* const prefs,
ZSTD_literalCompressionMode_e mode);
void FIO_setNoProgress(unsigned noProgress);
void FIO_setNotificationLevel(int level);
/*-************************************* /*-*************************************
* Single File functions * Single File functions
***************************************/ ***************************************/
/** FIO_compressFilename() : /** FIO_compressFilename() :
@return : 0 == ok; 1 == pb with src file. */ @return : 0 == ok; 1 == pb with src file. */
int FIO_compressFilename (const char* outfilename, const char* infilename, const char* dictFileName, int FIO_compressFilename (FIO_prefs_t* const prefs,
const char* outfilename, const char* infilename, const char* dictFileName,
int compressionLevel, ZSTD_compressionParameters comprParams); int compressionLevel, ZSTD_compressionParameters comprParams);
/** FIO_decompressFilename() : /** FIO_decompressFilename() :
@return : 0 == ok; 1 == pb with src file. */ @return : 0 == ok; 1 == pb with src file. */
int FIO_decompressFilename (const char* outfilename, const char* infilename, const char* dictFileName); int FIO_decompressFilename (FIO_prefs_t* const prefs,
const char* outfilename, const char* infilename, const char* dictFileName);
int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel); int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel);
@@ -89,14 +100,16 @@ int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int dis
***************************************/ ***************************************/
/** FIO_compressMultipleFilenames() : /** FIO_compressMultipleFilenames() :
@return : nb of missing files */ @return : nb of missing files */
int FIO_compressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles, int FIO_compressMultipleFilenames(FIO_prefs_t* const prefs,
const char** srcNamesTable, unsigned nbFiles,
const char* outFileName, const char* suffix, const char* outFileName, const char* suffix,
const char* dictFileName, int compressionLevel, const char* dictFileName, int compressionLevel,
ZSTD_compressionParameters comprParams); ZSTD_compressionParameters comprParams);
/** FIO_decompressMultipleFilenames() : /** FIO_decompressMultipleFilenames() :
@return : nb of missing or skipped files */ @return : nb of missing or skipped files */
int FIO_decompressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles, int FIO_decompressMultipleFilenames(FIO_prefs_t* const prefs,
const char** srcNamesTable, unsigned nbFiles,
const char* outFileName, const char* outFileName,
const char* dictFileName); const char* dictFileName);
+3 -2
View File
@@ -87,8 +87,8 @@ extern "C" {
* The following list of build macros tries to "guess" if target OS is likely unix-like, and therefore can #include <unistd.h> * The following list of build macros tries to "guess" if target OS is likely unix-like, and therefore can #include <unistd.h>
*/ */
# elif !defined(_WIN32) \ # elif !defined(_WIN32) \
&& (defined(__unix__) || defined(__unix) \ && ( defined(__unix__) || defined(__unix) \
|| defined(__midipix__) || defined(__VMS) || defined(__HAIKU__)) || defined(__midipix__) || defined(__VMS) || defined(__HAIKU__) )
# if defined(__linux__) || defined(__linux) # if defined(__linux__) || defined(__linux)
# ifndef _POSIX_C_SOURCE # ifndef _POSIX_C_SOURCE
@@ -108,6 +108,7 @@ extern "C" {
#endif /* PLATFORM_POSIX_VERSION */ #endif /* PLATFORM_POSIX_VERSION */
/*-********************************************* /*-*********************************************
* Detect if isatty() and fileno() are available * Detect if isatty() and fileno() are available
************************************************/ ************************************************/
+168
View File
@@ -0,0 +1,168 @@
/*
* Copyright (c) 2019-present, Yann Collet, Facebook, Inc.
* 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.
*/
/* === Dependencies === */
#include "timefn.h"
/*-****************************************
* Time functions
******************************************/
#if defined(_WIN32) /* Windows */
#include <stdlib.h> /* abort */
#include <stdio.h> /* perror */
UTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; }
PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static LARGE_INTEGER ticksPerSecond;
static int init = 0;
if (!init) {
if (!QueryPerformanceFrequency(&ticksPerSecond)) {
perror("timefn::QueryPerformanceFrequency");
abort();
}
init = 1;
}
return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
}
PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static LARGE_INTEGER ticksPerSecond;
static int init = 0;
if (!init) {
if (!QueryPerformanceFrequency(&ticksPerSecond)) {
perror("timefn::QueryPerformanceFrequency");
abort();
}
init = 1;
}
return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
}
#elif defined(__APPLE__) && defined(__MACH__)
UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); }
PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static mach_timebase_info_data_t rate;
static int init = 0;
if (!init) {
mach_timebase_info(&rate);
init = 1;
}
return (((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom))/1000ULL;
}
PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static mach_timebase_info_data_t rate;
static int init = 0;
if (!init) {
mach_timebase_info(&rate);
init = 1;
}
return ((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom);
}
#elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \
&& defined(TIME_UTC) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */
#include <stdlib.h> /* abort */
#include <stdio.h> /* perror */
UTIL_time_t UTIL_getTime(void)
{
/* time must be initialized, othersize it may fail msan test.
* No good reason, likely a limitation of timespec_get() for some target */
UTIL_time_t time = UTIL_TIME_INITIALIZER;
if (timespec_get(&time, TIME_UTC) != TIME_UTC) {
perror("timefn::timespec_get");
abort();
}
return time;
}
static UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end)
{
UTIL_time_t diff;
if (end.tv_nsec < begin.tv_nsec) {
diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec;
diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec;
} else {
diff.tv_sec = end.tv_sec - begin.tv_sec;
diff.tv_nsec = end.tv_nsec - begin.tv_nsec;
}
return diff;
}
PTime UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end)
{
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
PTime micro = 0;
micro += 1000000ULL * diff.tv_sec;
micro += diff.tv_nsec / 1000ULL;
return micro;
}
PTime UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end)
{
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
PTime nano = 0;
nano += 1000000000ULL * diff.tv_sec;
nano += diff.tv_nsec;
return nano;
}
#else /* relies on standard C90 (note : clock_t measurements can be wrong when using multi-threading) */
UTIL_time_t UTIL_getTime(void) { return clock(); }
PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
#endif
/* returns time span in microseconds */
PTime UTIL_clockSpanMicro(UTIL_time_t clockStart )
{
UTIL_time_t const clockEnd = UTIL_getTime();
return UTIL_getSpanTimeMicro(clockStart, clockEnd);
}
/* returns time span in microseconds */
PTime UTIL_clockSpanNano(UTIL_time_t clockStart )
{
UTIL_time_t const clockEnd = UTIL_getTime();
return UTIL_getSpanTimeNano(clockStart, clockEnd);
}
void UTIL_waitForNextTick(void)
{
UTIL_time_t const clockStart = UTIL_getTime();
UTIL_time_t clockEnd;
do {
clockEnd = UTIL_getTime();
} while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0);
}
+89
View File
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
* 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.
*/
#ifndef TIME_FN_H_MODULE_287987
#define TIME_FN_H_MODULE_287987
#if defined (__cplusplus)
extern "C" {
#endif
/*-****************************************
* Dependencies
******************************************/
#include <sys/types.h> /* utime */
#if defined(_MSC_VER)
# include <sys/utime.h> /* utime */
#else
# include <utime.h> /* utime */
#endif
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
/*-****************************************
* Local Types
******************************************/
#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
# include <stdint.h>
typedef uint64_t PTime; /* Precise Time */
#else
typedef unsigned long long PTime; /* does not support compilers without long long support */
#endif
/*-****************************************
* Time functions
******************************************/
#if defined(_WIN32) /* Windows */
#include <Windows.h> /* LARGE_INTEGER */
typedef LARGE_INTEGER UTIL_time_t;
#define UTIL_TIME_INITIALIZER { { 0, 0 } }
#elif defined(__APPLE__) && defined(__MACH__)
#include <mach/mach_time.h>
typedef PTime UTIL_time_t;
#define UTIL_TIME_INITIALIZER 0
#elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \
&& defined(TIME_UTC) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */
typedef struct timespec UTIL_time_t;
#define UTIL_TIME_INITIALIZER { 0, 0 }
#else /* relies on standard C90 (note : clock_t measurements can be wrong when using multi-threading) */
typedef clock_t UTIL_time_t;
#define UTIL_TIME_INITIALIZER 0
#endif
UTIL_time_t UTIL_getTime(void);
PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd);
PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd);
#define SEC_TO_MICRO ((PTime)1000000)
PTime UTIL_clockSpanMicro(UTIL_time_t clockStart);
PTime UTIL_clockSpanNano(UTIL_time_t clockStart);
void UTIL_waitForNextTick(void);
#if defined (__cplusplus)
}
#endif
#endif /* TIME_FN_H_MODULE_287987 */
+58 -135
View File
@@ -87,6 +87,23 @@ U32 UTIL_isDirectory(const char* infilename)
return 0; return 0;
} }
int UTIL_isSameFile(const char* file1, const char* file2)
{
#if defined(_MSC_VER)
/* note : Visual does not support file identification by inode.
* The following work-around is limited to detecting exact name repetition only,
* aka `filename` is considered different from `subdir/../filename` */
return !strcmp(file1, file2);
#else
stat_t file1Stat;
stat_t file2Stat;
return UTIL_getFileStat(file1, &file1Stat)
&& UTIL_getFileStat(file2, &file2Stat)
&& (file1Stat.st_dev == file2Stat.st_dev)
&& (file1Stat.st_ino == file2Stat.st_ino);
#endif
}
U32 UTIL_isLink(const char* infilename) U32 UTIL_isLink(const char* infilename)
{ {
/* macro guards, as defined in : https://linux.die.net/man/2/lstat */ /* macro guards, as defined in : https://linux.die.net/man/2/lstat */
@@ -95,7 +112,9 @@ U32 UTIL_isLink(const char* infilename)
|| (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \ || (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|| (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) \ || (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) \
|| (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \ || (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \
|| (defined(__APPLE__) && defined(__MACH__)) || (defined(__APPLE__) && defined(__MACH__)) \
|| defined(__OpenBSD__) \
|| defined(__FreeBSD__)
int r; int r;
stat_t statbuf; stat_t statbuf;
r = lstat(infilename, &statbuf); r = lstat(infilename, &statbuf);
@@ -333,146 +352,18 @@ UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
return fileTable; return fileTable;
} }
/*-**************************************** /*-****************************************
* Console log * Console log
******************************************/ ******************************************/
int g_utilDisplayLevel; int g_utilDisplayLevel;
/*-**************************************** /*-****************************************
* Time functions * count the number of physical cores
******************************************/ ******************************************/
#if defined(_WIN32) /* Windows */
UTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; }
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static LARGE_INTEGER ticksPerSecond;
static int init = 0;
if (!init) {
if (!QueryPerformanceFrequency(&ticksPerSecond))
UTIL_DISPLAYLEVEL(1, "ERROR: QueryPerformanceFrequency() failure\n");
init = 1;
}
return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
}
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static LARGE_INTEGER ticksPerSecond;
static int init = 0;
if (!init) {
if (!QueryPerformanceFrequency(&ticksPerSecond))
UTIL_DISPLAYLEVEL(1, "ERROR: QueryPerformanceFrequency() failure\n");
init = 1;
}
return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
}
#elif defined(__APPLE__) && defined(__MACH__)
UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); }
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static mach_timebase_info_data_t rate;
static int init = 0;
if (!init) {
mach_timebase_info(&rate);
init = 1;
}
return (((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom))/1000ULL;
}
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static mach_timebase_info_data_t rate;
static int init = 0;
if (!init) {
mach_timebase_info(&rate);
init = 1;
}
return ((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom);
}
#elif (PLATFORM_POSIX_VERSION >= 200112L) \
&& (defined(__UCLIBC__) \
|| (defined(__GLIBC__) \
&& ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) \
|| (__GLIBC__ > 2))))
UTIL_time_t UTIL_getTime(void)
{
UTIL_time_t time;
if (clock_gettime(CLOCK_MONOTONIC, &time))
UTIL_DISPLAYLEVEL(1, "ERROR: Failed to get time\n"); /* we could also exit() */
return time;
}
UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end)
{
UTIL_time_t diff;
if (end.tv_nsec < begin.tv_nsec) {
diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec;
diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec;
} else {
diff.tv_sec = end.tv_sec - begin.tv_sec;
diff.tv_nsec = end.tv_nsec - begin.tv_nsec;
}
return diff;
}
U64 UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end)
{
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
U64 micro = 0;
micro += 1000000ULL * diff.tv_sec;
micro += diff.tv_nsec / 1000ULL;
return micro;
}
U64 UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end)
{
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
U64 nano = 0;
nano += 1000000000ULL * diff.tv_sec;
nano += diff.tv_nsec;
return nano;
}
#else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */
UTIL_time_t UTIL_getTime(void) { return clock(); }
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
#endif
/* returns time span in microseconds */
U64 UTIL_clockSpanMicro(UTIL_time_t clockStart )
{
UTIL_time_t const clockEnd = UTIL_getTime();
return UTIL_getSpanTimeMicro(clockStart, clockEnd);
}
/* returns time span in microseconds */
U64 UTIL_clockSpanNano(UTIL_time_t clockStart )
{
UTIL_time_t const clockEnd = UTIL_getTime();
return UTIL_getSpanTimeNano(clockStart, clockEnd);
}
void UTIL_waitForNextTick(void)
{
UTIL_time_t const clockStart = UTIL_getTime();
UTIL_time_t clockEnd;
do {
clockEnd = UTIL_getTime();
} while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0);
}
/* count the number of physical cores */
#if defined(_WIN32) || defined(WIN32) #if defined(_WIN32) || defined(WIN32)
#include <windows.h> #include <windows.h>
@@ -640,10 +531,42 @@ failed:
} }
} }
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) #elif defined(__FreeBSD__)
/* Use apple-provided syscall #include <sys/param.h>
* see: man 3 sysctl */ #include <sys/sysctl.h>
/* Use physical core sysctl when available
* see: man 4 smp, man 3 sysctl */
int UTIL_countPhysicalCores(void)
{
static int numPhysicalCores = 0; /* freebsd sysctl is native int sized */
if (numPhysicalCores != 0) return numPhysicalCores;
#if __FreeBSD_version >= 1300008
{ size_t size = sizeof(numPhysicalCores);
int ret = sysctlbyname("kern.smp.cores", &numPhysicalCores, &size, NULL, 0);
if (ret == 0) return numPhysicalCores;
if (errno != ENOENT) {
perror("zstd: can't get number of physical cpus");
exit(1);
}
/* sysctl not present, fall through to older sysconf method */
}
#endif
numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
if (numPhysicalCores == -1) {
/* value not queryable, fall back on 1 */
numPhysicalCores = 1;
}
return numPhysicalCores;
}
#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
/* Use POSIX sysconf
* see: man 3 sysconf */
int UTIL_countPhysicalCores(void) int UTIL_countPhysicalCores(void)
{ {
static int numPhysicalCores = 0; static int numPhysicalCores = 0;
+1 -46
View File
@@ -112,52 +112,6 @@ extern int g_utilDisplayLevel;
#define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } } #define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } }
/*-****************************************
* Time functions
******************************************/
#if defined(_WIN32) /* Windows */
#define UTIL_TIME_INITIALIZER { { 0, 0 } }
typedef LARGE_INTEGER UTIL_time_t;
#elif defined(__APPLE__) && defined(__MACH__)
#include <mach/mach_time.h>
#define UTIL_TIME_INITIALIZER 0
typedef U64 UTIL_time_t;
#elif (PLATFORM_POSIX_VERSION >= 200112L) \
&& (defined(__UCLIBC__) \
|| (defined(__GLIBC__) \
&& ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) \
|| (__GLIBC__ > 2))))
#define UTIL_TIME_INITIALIZER { 0, 0 }
typedef struct timespec UTIL_freq_t;
typedef struct timespec UTIL_time_t;
UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end);
#else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */
typedef clock_t UTIL_time_t;
#define UTIL_TIME_INITIALIZER 0
#endif
UTIL_time_t UTIL_getTime(void);
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd);
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd);
#define SEC_TO_MICRO 1000000
/* returns time span in microseconds */
U64 UTIL_clockSpanMicro(UTIL_time_t clockStart);
/* returns time span in microseconds */
U64 UTIL_clockSpanNano(UTIL_time_t clockStart);
void UTIL_waitForNextTick(void);
/*-**************************************** /*-****************************************
* File functions * File functions
******************************************/ ******************************************/
@@ -174,6 +128,7 @@ int UTIL_isRegularFile(const char* infilename);
int UTIL_setFileStat(const char* filename, stat_t* statbuf); int UTIL_setFileStat(const char* filename, stat_t* statbuf);
U32 UTIL_isDirectory(const char* infilename); U32 UTIL_isDirectory(const char* infilename);
int UTIL_getFileStat(const char* infilename, stat_t* statbuf); int UTIL_getFileStat(const char* infilename, stat_t* statbuf);
int UTIL_isSameFile(const char* file1, const char* file2);
U32 UTIL_isLink(const char* infilename); U32 UTIL_isLink(const char* infilename);
#define UTIL_FILESIZE_UNKNOWN ((U64)(-1)) #define UTIL_FILESIZE_UNKNOWN ((U64)(-1))
+1 -1
View File
@@ -164,7 +164,7 @@ keep source file(s) after successful compression or decompression\. This is the
. .
.TP .TP
\fB\-r\fR \fB\-r\fR
operate recursively on dictionaries operate recursively on directories
. .
.TP .TP
\fB\-\-format=FORMAT\fR \fB\-\-format=FORMAT\fR
+1 -1
View File
@@ -178,7 +178,7 @@ the last one takes effect.
keep source file(s) after successful compression or decompression. keep source file(s) after successful compression or decompression.
This is the default behavior. This is the default behavior.
* `-r`: * `-r`:
operate recursively on dictionaries operate recursively on directories
* `--format=FORMAT`: * `--format=FORMAT`:
compress and decompress in other formats. If compiled with compress and decompress in other formats. If compiled with
support, zstd can compress to or decompress from other compression algorithm support, zstd can compress to or decompress from other compression algorithm
+67 -53
View File
@@ -148,6 +148,7 @@ static int usage_advanced(const char* programName)
#endif #endif
DISPLAY( "--no-dictID : don't write dictID into header (dictionary compression)\n"); DISPLAY( "--no-dictID : don't write dictID into header (dictionary compression)\n");
DISPLAY( "--[no-]check : integrity check (default: enabled) \n"); DISPLAY( "--[no-]check : integrity check (default: enabled) \n");
DISPLAY( "--[no-]compress-literals : force (un)compressed literals \n");
#endif #endif
#ifdef UTIL_HAS_CREATEFILELIST #ifdef UTIL_HAS_CREATEFILELIST
DISPLAY( " -r : operate recursively on directories \n"); DISPLAY( " -r : operate recursively on directories \n");
@@ -241,18 +242,20 @@ static void errorOut(const char* msg)
* @return 1 if an overflow error occurs */ * @return 1 if an overflow error occurs */
static int readU32FromCharChecked(const char** stringPtr, unsigned* value) static int readU32FromCharChecked(const char** stringPtr, unsigned* value)
{ {
static unsigned const max = (((unsigned)(-1)) / 10) - 1;
unsigned result = 0; unsigned result = 0;
while ((**stringPtr >='0') && (**stringPtr <='9')) { while ((**stringPtr >='0') && (**stringPtr <='9')) {
if (result > max) return 1; // overflow error unsigned const max = (((unsigned)(-1)) / 10) - 1;
result *= 10, result += **stringPtr - '0', (*stringPtr)++ ; if (result > max) return 1; /* overflow error */
result *= 10;
result += (unsigned)(**stringPtr - '0');
(*stringPtr)++ ;
} }
if ((**stringPtr=='K') || (**stringPtr=='M')) { if ((**stringPtr=='K') || (**stringPtr=='M')) {
unsigned const maxK = ((unsigned)(-1)) >> 10; unsigned const maxK = ((unsigned)(-1)) >> 10;
if (result > maxK) return 1; // overflow error if (result > maxK) return 1; /* overflow error */
result <<= 10; result <<= 10;
if (**stringPtr=='M') { if (**stringPtr=='M') {
if (result > maxK) return 1; // overflow error if (result > maxK) return 1; /* overflow error */
result <<= 10; result <<= 10;
} }
(*stringPtr)++; /* skip `K` or `M` */ (*stringPtr)++; /* skip `K` or `M` */
@@ -344,7 +347,7 @@ static unsigned parseFastCoverParameters(const char* stringPtr, ZDICT_fastCover_
/** /**
* parseLegacyParameters() : * parseLegacyParameters() :
* reads legacy dictioanry builter parameters from *stringPtr (e.g. "--train-legacy=selectivity=8") into *selectivity * reads legacy dictionary builder parameters from *stringPtr (e.g. "--train-legacy=selectivity=8") into *selectivity
* @return 1 means that legacy dictionary builder parameters were correct * @return 1 means that legacy dictionary builder parameters were correct
* @return 0 in case of malformed parameters * @return 0 in case of malformed parameters
*/ */
@@ -483,7 +486,7 @@ static int init_cLevel(void) {
if ((*ptr>='0') && (*ptr<='9')) { if ((*ptr>='0') && (*ptr<='9')) {
unsigned absLevel; unsigned absLevel;
if (readU32FromCharChecked(&ptr, &absLevel)) { if (readU32FromCharChecked(&ptr, &absLevel)) {
DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: numeric value too large\n", ENV_CLEVEL, env); DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: numeric value too large\n", ENV_CLEVEL, env);
return ZSTDCLI_CLEVEL_DEFAULT; return ZSTDCLI_CLEVEL_DEFAULT;
} else if (*ptr == 0) { } else if (*ptr == 0) {
@@ -536,6 +539,8 @@ int main(int argCount, const char* argv[])
double compressibility = 0.5; double compressibility = 0.5;
unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */ unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */
size_t blockSize = 0; size_t blockSize = 0;
FIO_prefs_t* const prefs = FIO_createPreferences();
zstd_operation_mode operation = zom_compress; zstd_operation_mode operation = zom_compress;
ZSTD_compressionParameters compressionParams; ZSTD_compressionParameters compressionParams;
int cLevel; int cLevel;
@@ -565,6 +570,7 @@ int main(int argCount, const char* argv[])
#ifndef ZSTD_NOBENCH #ifndef ZSTD_NOBENCH
BMK_advancedParams_t benchParams = BMK_initAdvancedParams(); BMK_advancedParams_t benchParams = BMK_initAdvancedParams();
#endif #endif
ZSTD_literalCompressionMode_e literalCompressionMode = ZSTD_lcm_auto;
/* init */ /* init */
@@ -582,17 +588,17 @@ int main(int argCount, const char* argv[])
/* preset behaviors */ /* preset behaviors */
if (exeNameMatch(programName, ZSTD_ZSTDMT)) nbWorkers=0, singleThread=0; if (exeNameMatch(programName, ZSTD_ZSTDMT)) nbWorkers=0, singleThread=0;
if (exeNameMatch(programName, ZSTD_UNZSTD)) operation=zom_decompress; if (exeNameMatch(programName, ZSTD_UNZSTD)) operation=zom_decompress;
if (exeNameMatch(programName, ZSTD_CAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; } /* supports multiple formats */ if (exeNameMatch(programName, ZSTD_CAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(prefs); outFileName=stdoutmark; g_displayLevel=1; } /* supports multiple formats */
if (exeNameMatch(programName, ZSTD_ZCAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; } /* behave like zcat, also supports multiple formats */ if (exeNameMatch(programName, ZSTD_ZCAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(prefs); outFileName=stdoutmark; g_displayLevel=1; } /* behave like zcat, also supports multiple formats */
if (exeNameMatch(programName, ZSTD_GZ)) { suffix = GZ_EXTENSION; FIO_setCompressionType(FIO_gzipCompression); FIO_setRemoveSrcFile(1); } /* behave like gzip */ if (exeNameMatch(programName, ZSTD_GZ)) { suffix = GZ_EXTENSION; FIO_setCompressionType(prefs, FIO_gzipCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like gzip */
if (exeNameMatch(programName, ZSTD_GUNZIP)) { operation=zom_decompress; FIO_setRemoveSrcFile(1); } /* behave like gunzip, also supports multiple formats */ if (exeNameMatch(programName, ZSTD_GUNZIP)) { operation=zom_decompress; FIO_setRemoveSrcFile(prefs, 1); } /* behave like gunzip, also supports multiple formats */
if (exeNameMatch(programName, ZSTD_GZCAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; } /* behave like gzcat, also supports multiple formats */ if (exeNameMatch(programName, ZSTD_GZCAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(prefs); outFileName=stdoutmark; g_displayLevel=1; } /* behave like gzcat, also supports multiple formats */
if (exeNameMatch(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; FIO_setCompressionType(FIO_lzmaCompression); FIO_setRemoveSrcFile(1); } /* behave like lzma */ if (exeNameMatch(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; FIO_setCompressionType(prefs, FIO_lzmaCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like lzma */
if (exeNameMatch(programName, ZSTD_UNLZMA)) { operation=zom_decompress; FIO_setCompressionType(FIO_lzmaCompression); FIO_setRemoveSrcFile(1); } /* behave like unlzma, also supports multiple formats */ if (exeNameMatch(programName, ZSTD_UNLZMA)) { operation=zom_decompress; FIO_setCompressionType(prefs, FIO_lzmaCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like unlzma, also supports multiple formats */
if (exeNameMatch(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; FIO_setCompressionType(FIO_xzCompression); FIO_setRemoveSrcFile(1); } /* behave like xz */ if (exeNameMatch(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; FIO_setCompressionType(prefs, FIO_xzCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like xz */
if (exeNameMatch(programName, ZSTD_UNXZ)) { operation=zom_decompress; FIO_setCompressionType(FIO_xzCompression); FIO_setRemoveSrcFile(1); } /* behave like unxz, also supports multiple formats */ if (exeNameMatch(programName, ZSTD_UNXZ)) { operation=zom_decompress; FIO_setCompressionType(prefs, FIO_xzCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like unxz, also supports multiple formats */
if (exeNameMatch(programName, ZSTD_LZ4)) { suffix = LZ4_EXTENSION; FIO_setCompressionType(FIO_lz4Compression); } /* behave like lz4 */ if (exeNameMatch(programName, ZSTD_LZ4)) { suffix = LZ4_EXTENSION; FIO_setCompressionType(prefs, FIO_lz4Compression); } /* behave like lz4 */
if (exeNameMatch(programName, ZSTD_UNLZ4)) { operation=zom_decompress; FIO_setCompressionType(FIO_lz4Compression); } /* behave like unlz4, also supports multiple formats */ if (exeNameMatch(programName, ZSTD_UNLZ4)) { operation=zom_decompress; FIO_setCompressionType(prefs, FIO_lz4Compression); } /* behave like unlz4, also supports multiple formats */
memset(&compressionParams, 0, sizeof(compressionParams)); memset(&compressionParams, 0, sizeof(compressionParams));
/* init crash handler */ /* init crash handler */
@@ -623,40 +629,42 @@ int main(int argCount, const char* argv[])
if (!strcmp(argument, "--compress")) { operation=zom_compress; continue; } if (!strcmp(argument, "--compress")) { operation=zom_compress; continue; }
if (!strcmp(argument, "--decompress")) { operation=zom_decompress; continue; } if (!strcmp(argument, "--decompress")) { operation=zom_decompress; continue; }
if (!strcmp(argument, "--uncompress")) { operation=zom_decompress; continue; } if (!strcmp(argument, "--uncompress")) { operation=zom_decompress; continue; }
if (!strcmp(argument, "--force")) { FIO_overwriteMode(); forceStdout=1; followLinks=1; continue; } if (!strcmp(argument, "--force")) { FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; continue; }
if (!strcmp(argument, "--version")) { g_displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); } if (!strcmp(argument, "--version")) { g_displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); }
if (!strcmp(argument, "--help")) { g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); } if (!strcmp(argument, "--help")) { g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); }
if (!strcmp(argument, "--verbose")) { g_displayLevel++; continue; } if (!strcmp(argument, "--verbose")) { g_displayLevel++; continue; }
if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; } if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; }
if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; g_displayLevel-=(g_displayLevel==2); continue; } if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; g_displayLevel-=(g_displayLevel==2); continue; }
if (!strcmp(argument, "--ultra")) { ultra=1; continue; } if (!strcmp(argument, "--ultra")) { ultra=1; continue; }
if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(2); continue; } if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(prefs, 2); continue; }
if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(0); continue; } if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(prefs, 0); continue; }
if (!strcmp(argument, "--sparse")) { FIO_setSparseWrite(2); continue; } if (!strcmp(argument, "--sparse")) { FIO_setSparseWrite(prefs, 2); continue; }
if (!strcmp(argument, "--no-sparse")) { FIO_setSparseWrite(0); continue; } if (!strcmp(argument, "--no-sparse")) { FIO_setSparseWrite(prefs, 0); continue; }
if (!strcmp(argument, "--test")) { operation=zom_test; continue; } if (!strcmp(argument, "--test")) { operation=zom_test; continue; }
if (!strcmp(argument, "--train")) { operation=zom_train; if (outFileName==NULL) outFileName=g_defaultDictName; continue; } if (!strcmp(argument, "--train")) { operation=zom_train; if (outFileName==NULL) outFileName=g_defaultDictName; continue; }
if (!strcmp(argument, "--maxdict")) { nextArgumentIsMaxDict=1; lastCommand=1; continue; } /* kept available for compatibility with old syntax ; will be removed one day */ if (!strcmp(argument, "--maxdict")) { nextArgumentIsMaxDict=1; lastCommand=1; continue; } /* kept available for compatibility with old syntax ; will be removed one day */
if (!strcmp(argument, "--dictID")) { nextArgumentIsDictID=1; lastCommand=1; continue; } /* kept available for compatibility with old syntax ; will be removed one day */ if (!strcmp(argument, "--dictID")) { nextArgumentIsDictID=1; lastCommand=1; continue; } /* kept available for compatibility with old syntax ; will be removed one day */
if (!strcmp(argument, "--no-dictID")) { FIO_setDictIDFlag(0); continue; } if (!strcmp(argument, "--no-dictID")) { FIO_setDictIDFlag(prefs, 0); continue; }
if (!strcmp(argument, "--keep")) { FIO_setRemoveSrcFile(0); continue; } if (!strcmp(argument, "--keep")) { FIO_setRemoveSrcFile(prefs, 0); continue; }
if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(1); continue; } if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(prefs, 1); continue; }
if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; } if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; }
if (!strcmp(argument, "--adapt")) { adapt = 1; continue; } if (!strcmp(argument, "--adapt")) { adapt = 1; continue; }
if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) CLEAN_RETURN(badusage(programName)); continue; } if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) CLEAN_RETURN(badusage(programName)); continue; }
if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; } if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; }
if (!strcmp(argument, "--format=zstd")) { suffix = ZSTD_EXTENSION; FIO_setCompressionType(FIO_zstdCompression); continue; } if (!strcmp(argument, "--format=zstd")) { suffix = ZSTD_EXTENSION; FIO_setCompressionType(prefs, FIO_zstdCompression); continue; }
#ifdef ZSTD_GZCOMPRESS #ifdef ZSTD_GZCOMPRESS
if (!strcmp(argument, "--format=gzip")) { suffix = GZ_EXTENSION; FIO_setCompressionType(FIO_gzipCompression); continue; } if (!strcmp(argument, "--format=gzip")) { suffix = GZ_EXTENSION; FIO_setCompressionType(prefs, FIO_gzipCompression); continue; }
#endif #endif
#ifdef ZSTD_LZMACOMPRESS #ifdef ZSTD_LZMACOMPRESS
if (!strcmp(argument, "--format=lzma")) { suffix = LZMA_EXTENSION; FIO_setCompressionType(FIO_lzmaCompression); continue; } if (!strcmp(argument, "--format=lzma")) { suffix = LZMA_EXTENSION; FIO_setCompressionType(prefs, FIO_lzmaCompression); continue; }
if (!strcmp(argument, "--format=xz")) { suffix = XZ_EXTENSION; FIO_setCompressionType(FIO_xzCompression); continue; } if (!strcmp(argument, "--format=xz")) { suffix = XZ_EXTENSION; FIO_setCompressionType(prefs, FIO_xzCompression); continue; }
#endif #endif
#ifdef ZSTD_LZ4COMPRESS #ifdef ZSTD_LZ4COMPRESS
if (!strcmp(argument, "--format=lz4")) { suffix = LZ4_EXTENSION; FIO_setCompressionType(FIO_lz4Compression); continue; } if (!strcmp(argument, "--format=lz4")) { suffix = LZ4_EXTENSION; FIO_setCompressionType(prefs, FIO_lz4Compression); continue; }
#endif #endif
if (!strcmp(argument, "--rsyncable")) { rsyncable = 1; continue; } if (!strcmp(argument, "--rsyncable")) { rsyncable = 1; continue; }
if (!strcmp(argument, "--compress-literals")) { literalCompressionMode = ZSTD_lcm_huffman; continue; }
if (!strcmp(argument, "--no-compress-literals")) { literalCompressionMode = ZSTD_lcm_uncompressed; continue; }
if (!strcmp(argument, "--no-progress")) { FIO_setNoProgress(1); continue; } if (!strcmp(argument, "--no-progress")) { FIO_setNoProgress(1); continue; }
/* long commands with arguments */ /* long commands with arguments */
@@ -784,7 +792,7 @@ int main(int argCount, const char* argv[])
case 'D': nextEntryIsDictionary = 1; lastCommand = 1; argument++; break; case 'D': nextEntryIsDictionary = 1; lastCommand = 1; argument++; break;
/* Overwrite */ /* Overwrite */
case 'f': FIO_overwriteMode(); forceStdout=1; followLinks=1; argument++; break; case 'f': FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; argument++; break;
/* Verbose mode */ /* Verbose mode */
case 'v': g_displayLevel++; argument++; break; case 'v': g_displayLevel++; argument++; break;
@@ -793,10 +801,10 @@ int main(int argCount, const char* argv[])
case 'q': g_displayLevel--; argument++; break; case 'q': g_displayLevel--; argument++; break;
/* keep source file (default) */ /* keep source file (default) */
case 'k': FIO_setRemoveSrcFile(0); argument++; break; case 'k': FIO_setRemoveSrcFile(prefs, 0); argument++; break;
/* Checksum */ /* Checksum */
case 'C': FIO_setChecksumFlag(2); argument++; break; case 'C': FIO_setChecksumFlag(prefs, 2); argument++; break;
/* test compressed file */ /* test compressed file */
case 't': operation=zom_test; argument++; break; case 't': operation=zom_test; argument++; break;
@@ -949,6 +957,8 @@ int main(int argCount, const char* argv[])
filenameTable[fileNamesNb++] = filenameTable[u]; filenameTable[fileNamesNb++] = filenameTable[u];
} }
} }
if (fileNamesNb == 0 && filenameIdx > 0)
CLEAN_RETURN(1);
filenameIdx = fileNamesNb; filenameIdx = fileNamesNb;
} }
if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */ if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
@@ -991,6 +1001,7 @@ int main(int argCount, const char* argv[])
if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) { if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) {
benchParams.ldmHashRateLog = g_ldmHashRateLog; benchParams.ldmHashRateLog = g_ldmHashRateLog;
} }
benchParams.literalCompressionMode = literalCompressionMode;
if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel(); if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
if (cLevelLast > ZSTD_maxCLevel()) cLevelLast = ZSTD_maxCLevel(); if (cLevelLast > ZSTD_maxCLevel()) cLevelLast = ZSTD_maxCLevel();
@@ -1057,7 +1068,7 @@ int main(int argCount, const char* argv[])
} }
#ifndef ZSTD_NODECOMPRESS #ifndef ZSTD_NODECOMPRESS
if (operation==zom_test) { outFileName=nulmark; FIO_setRemoveSrcFile(0); } /* test mode */ if (operation==zom_test) { outFileName=nulmark; FIO_setRemoveSrcFile(prefs, 0); } /* test mode */
#endif #endif
/* No input filename ==> use stdin and stdout */ /* No input filename ==> use stdin and stdout */
@@ -1092,27 +1103,28 @@ int main(int argCount, const char* argv[])
FIO_setNotificationLevel(g_displayLevel); FIO_setNotificationLevel(g_displayLevel);
if (operation==zom_compress) { if (operation==zom_compress) {
#ifndef ZSTD_NOCOMPRESS #ifndef ZSTD_NOCOMPRESS
FIO_setNbWorkers(nbWorkers); FIO_setNbWorkers(prefs, nbWorkers);
FIO_setBlockSize((U32)blockSize); FIO_setBlockSize(prefs, (U32)blockSize);
if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(g_overlapLog); if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(prefs, g_overlapLog);
FIO_setLdmFlag(ldmFlag); FIO_setLdmFlag(prefs, ldmFlag);
FIO_setLdmHashLog(g_ldmHashLog); FIO_setLdmHashLog(prefs, g_ldmHashLog);
FIO_setLdmMinMatch(g_ldmMinMatch); FIO_setLdmMinMatch(prefs, g_ldmMinMatch);
if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) FIO_setLdmBucketSizeLog(g_ldmBucketSizeLog); if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) FIO_setLdmBucketSizeLog(prefs, g_ldmBucketSizeLog);
if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) FIO_setLdmHashRateLog(g_ldmHashRateLog); if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) FIO_setLdmHashRateLog(prefs, g_ldmHashRateLog);
FIO_setAdaptiveMode(adapt); FIO_setAdaptiveMode(prefs, adapt);
FIO_setAdaptMin(adaptMin); FIO_setAdaptMin(prefs, adaptMin);
FIO_setAdaptMax(adaptMax); FIO_setAdaptMax(prefs, adaptMax);
FIO_setRsyncable(rsyncable); FIO_setRsyncable(prefs, rsyncable);
FIO_setLiteralCompressionMode(prefs, literalCompressionMode);
if (adaptMin > cLevel) cLevel = adaptMin; if (adaptMin > cLevel) cLevel = adaptMin;
if (adaptMax < cLevel) cLevel = adaptMax; if (adaptMax < cLevel) cLevel = adaptMax;
if ((filenameIdx==1) && outFileName) if ((filenameIdx==1) && outFileName)
operationResult = FIO_compressFilename(outFileName, filenameTable[0], dictFileName, cLevel, compressionParams); operationResult = FIO_compressFilename(prefs, outFileName, filenameTable[0], dictFileName, cLevel, compressionParams);
else else
operationResult = FIO_compressMultipleFilenames(filenameTable, filenameIdx, outFileName, suffix, dictFileName, cLevel, compressionParams); operationResult = FIO_compressMultipleFilenames(prefs, filenameTable, filenameIdx, outFileName, suffix, dictFileName, cLevel, compressionParams);
#else #else
(void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; /* not used when ZSTD_NOCOMPRESS set */ (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; /* not used when ZSTD_NOCOMPRESS set */
DISPLAY("Compression not supported \n"); DISPLAY("Compression not supported \n");
#endif #endif
} else { /* decompression or test */ } else { /* decompression or test */
@@ -1124,17 +1136,19 @@ int main(int argCount, const char* argv[])
memLimit = (U32)1 << (compressionParams.windowLog & 31); memLimit = (U32)1 << (compressionParams.windowLog & 31);
} }
} }
FIO_setMemLimit(memLimit); FIO_setMemLimit(prefs, memLimit);
if (filenameIdx==1 && outFileName) if (filenameIdx==1 && outFileName)
operationResult = FIO_decompressFilename(outFileName, filenameTable[0], dictFileName); operationResult = FIO_decompressFilename(prefs, outFileName, filenameTable[0], dictFileName);
else else
operationResult = FIO_decompressMultipleFilenames(filenameTable, filenameIdx, outFileName, dictFileName); operationResult = FIO_decompressMultipleFilenames(prefs, filenameTable, filenameIdx, outFileName, dictFileName);
#else #else
DISPLAY("Decompression not supported \n"); DISPLAY("Decompression not supported \n");
#endif #endif
} }
_end: _end:
FIO_freePreferences(prefs);
if (main_pause) waitEnter(); if (main_pause) waitEnter();
#ifdef UTIL_HAS_CREATEFILELIST #ifdef UTIL_HAS_CREATEFILELIST
if (extendedFileList) if (extendedFileList)
+10 -14
View File
@@ -22,8 +22,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
grep=grep grep=${GREP:-grep}
zcat=zstdcat zcat=${ZCAT:-zstdcat}
endofopts=0 endofopts=0
pattern_found=0 pattern_found=0
@@ -31,12 +31,13 @@ grep_args=""
hyphen=0 hyphen=0
silent=0 silent=0
prg=$(basename "$0") prog=${0##*/}
# handle being called 'zegrep' or 'zfgrep' # handle being called 'zegrep' or 'zfgrep'
case "${prg}" in case $prog in
*zegrep) grep_args="-E";; *egrep*) prog=zegrep; grep_args='-E';;
*zfgrep) grep_args="-F";; *fgrep*) prog=zfgrep; grep_args='-F';;
*) prog=zstdgrep;;
esac esac
# skip all options and pass them on to grep taking care of options # skip all options and pass them on to grep taking care of options
@@ -47,7 +48,7 @@ while [ "$#" -gt 0 ] && [ "${endofopts}" -eq 0 ]; do
# from GNU grep-2.5.1 -- keep in sync! # from GNU grep-2.5.1 -- keep in sync!
-[ABCDXdefm]) -[ABCDXdefm])
if [ "$#" -lt 2 ]; then if [ "$#" -lt 2 ]; then
printf '%s: missing argument for %s flag\n' "${prg}" "$1" >&2 printf '%s: missing argument for %s flag\n' "${prog}" "$1" >&2
exit 1 exit 1
fi fi
case "$1" in case "$1" in
@@ -94,7 +95,7 @@ if [ "${pattern_found}" -lt 1 ]; then
elif [ "${hyphen}" -gt 0 ]; then elif [ "${hyphen}" -gt 0 ]; then
pattern="-" pattern="-"
else else
printf '%s: missing pattern\n' "${prg}" >&2 printf '%s: missing pattern\n' "${prog}" >&2
exit 1 exit 1
fi fi
fi fi
@@ -113,16 +114,11 @@ else
if [ "${silent}" -lt 1 ] && [ "$#" -gt 1 ]; then if [ "${silent}" -lt 1 ] && [ "$#" -gt 1 ]; then
grep_args="-H ${grep_args}" grep_args="-H ${grep_args}"
fi fi
CUR_EXIT_CODE=0
EXIT_CODE=1
set -f set -f
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
# shellcheck disable=SC2086 # shellcheck disable=SC2086
"${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" - "${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" -
CUR_EXIT_CODE=$? [ "$?" -ne 0 ] && EXIT_CODE=1
if [ "${CUR_EXIT_CODE}" -eq 0 ] && [ "${EXIT_CODE}" -ne 1 ]; then
EXIT_CODE=0
fi
shift shift
done done
set +f set +f
+20 -16
View File
@@ -33,7 +33,7 @@ endif
CFLAGS ?= -O3 CFLAGS ?= -O3
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
-Wstrict-prototypes -Wundef -Wformat-security \ -Wstrict-prototypes -Wundef \
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
-Wredundant-decls -Wmissing-prototypes -Wredundant-decls -Wmissing-prototypes
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
@@ -82,7 +82,7 @@ default: fullbench
@echo $(ZSTDMT_OBJECTS) @echo $(ZSTDMT_OBJECTS)
all: fullbench fuzzer zstreamtest paramgrill datagen decodecorpus roundTripCrash \ all: fullbench fuzzer zstreamtest paramgrill datagen decodecorpus roundTripCrash \
fullbench-lib fullbench-lib poolTests
all32: fullbench32 fuzzer32 zstreamtest32 all32: fullbench32 fuzzer32 zstreamtest32
@@ -132,18 +132,18 @@ fullbench fullbench32 : CPPFLAGS += $(MULTITHREAD_CPP)
fullbench fullbench32 : LDFLAGS += $(MULTITHREAD_LD) fullbench fullbench32 : LDFLAGS += $(MULTITHREAD_LD)
fullbench fullbench32 : DEBUGFLAGS = -DNDEBUG # turn off assert() for speed measurements fullbench fullbench32 : DEBUGFLAGS = -DNDEBUG # turn off assert() for speed measurements
fullbench fullbench32 : $(ZSTD_FILES) fullbench fullbench32 : $(ZSTD_FILES)
fullbench fullbench32 : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c fullbench.c fullbench fullbench32 : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c
$(CC) $(FLAGS) $^ -o $@$(EXT) $(CC) $(FLAGS) $^ -o $@$(EXT)
fullbench-lib : CPPFLAGS += -DXXH_NAMESPACE=ZSTD_ fullbench-lib : CPPFLAGS += -DXXH_NAMESPACE=ZSTD_
fullbench-lib : zstd-staticLib fullbench-lib : zstd-staticLib
fullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c fullbench.c fullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c
$(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) $(ZSTDDIR)/libzstd.a $(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) $(ZSTDDIR)/libzstd.a
# note : broken : requires unavailable symbols # note : broken : requires unavailable symbols
fullbench-dll : zstd-dll fullbench-dll : zstd-dll
fullbench-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd fullbench-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd
fullbench-dll: $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c fullbench.c fullbench-dll: $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c $(PRGDIR)/timefn.c fullbench.c
# $(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) -DZSTD_DLL_IMPORT=1 $(ZSTDDIR)/dll/libzstd.dll # $(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) -DZSTD_DLL_IMPORT=1 $(ZSTDDIR)/dll/libzstd.dll
$(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) $(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT)
@@ -152,32 +152,32 @@ fuzzer : LDFLAGS += $(MULTITHREAD_LD)
fuzzer32: CFLAGS += -m32 fuzzer32: CFLAGS += -m32
fuzzer : $(ZSTDMT_OBJECTS) fuzzer : $(ZSTDMT_OBJECTS)
fuzzer32: $(ZSTD_FILES) fuzzer32: $(ZSTD_FILES)
fuzzer fuzzer32 : $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/datagen.c fuzzer.c fuzzer fuzzer32 : $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c
$(CC) $(FLAGS) $^ -o $@$(EXT) $(CC) $(FLAGS) $^ -o $@$(EXT)
fuzzer-dll : zstd-dll fuzzer-dll : zstd-dll
fuzzer-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd fuzzer-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd
fuzzer-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/datagen.c fuzzer.c fuzzer-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT) $(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)
zbufftest : CPPFLAGS += -I$(ZSTDDIR)/deprecated zbufftest : CPPFLAGS += -I$(ZSTDDIR)/deprecated
zbufftest : CFLAGS += -Wno-deprecated-declarations # required to silence deprecation warnings zbufftest : CFLAGS += -Wno-deprecated-declarations # required to silence deprecation warnings
zbufftest : $(ZSTD_OBJECTS) $(ZBUFF_FILES) $(PRGDIR)/util.c $(PRGDIR)/datagen.c zbufftest.c zbufftest : $(ZSTD_OBJECTS) $(ZBUFF_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c zbufftest.c
$(CC) $(FLAGS) $^ -o $@$(EXT) $(CC) $(FLAGS) $^ -o $@$(EXT)
zbufftest32 : CPPFLAGS += -I$(ZSTDDIR)/deprecated zbufftest32 : CPPFLAGS += -I$(ZSTDDIR)/deprecated
zbufftest32 : CFLAGS += -Wno-deprecated-declarations -m32 zbufftest32 : CFLAGS += -Wno-deprecated-declarations -m32
zbufftest32 : $(ZSTD_FILES) $(ZBUFF_FILES) $(PRGDIR)/util.c $(PRGDIR)/datagen.c zbufftest.c zbufftest32 : $(ZSTD_FILES) $(ZBUFF_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c zbufftest.c
$(CC) $(FLAGS) $^ -o $@$(EXT) $(CC) $(FLAGS) $^ -o $@$(EXT)
zbufftest-dll : zstd-dll zbufftest-dll : zstd-dll
zbufftest-dll : CPPFLAGS += -I$(ZSTDDIR)/deprecated zbufftest-dll : CPPFLAGS += -I$(ZSTDDIR)/deprecated
zbufftest-dll : CFLAGS += -Wno-deprecated-declarations # required to silence deprecation warnings zbufftest-dll : CFLAGS += -Wno-deprecated-declarations # required to silence deprecation warnings
zbufftest-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd zbufftest-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd
zbufftest-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/datagen.c zbufftest.c zbufftest-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c zbufftest.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT) $(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)
ZSTREAM_LOCAL_FILES := $(PRGDIR)/datagen.c $(PRGDIR)/util.c seqgen.c zstreamtest.c ZSTREAM_LOCAL_FILES := $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c seqgen.c zstreamtest.c
ZSTREAM_PROPER_FILES := $(ZDICT_FILES) $(ZSTREAM_LOCAL_FILES) ZSTREAM_PROPER_FILES := $(ZDICT_FILES) $(ZSTREAM_LOCAL_FILES)
ZSTREAMFILES := $(ZSTD_FILES) $(ZSTREAM_PROPER_FILES) ZSTREAMFILES := $(ZSTD_FILES) $(ZSTREAM_PROPER_FILES)
zstreamtest32 : CFLAGS += -m32 zstreamtest32 : CFLAGS += -m32
@@ -203,7 +203,7 @@ zstreamtest-dll : $(ZSTREAM_LOCAL_FILES)
$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT) $(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)
paramgrill : DEBUGFLAGS = # turn off assert() by default for speed measurements paramgrill : DEBUGFLAGS = # turn off assert() by default for speed measurements
paramgrill : $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/benchfn.c $(PRGDIR)/benchzstd.c $(PRGDIR)/datagen.c paramgrill.c paramgrill : $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c $(PRGDIR)/benchzstd.c $(PRGDIR)/datagen.c paramgrill.c
$(CC) $(FLAGS) $^ -lm -o $@$(EXT) $(CC) $(FLAGS) $^ -lm -o $@$(EXT)
datagen : $(PRGDIR)/datagen.c datagencli.c datagen : $(PRGDIR)/datagen.c datagencli.c
@@ -222,7 +222,7 @@ legacy : CPPFLAGS += -I$(ZSTDDIR)/legacy -DZSTD_LEGACY_SUPPORT=4
legacy : $(ZSTD_FILES) $(wildcard $(ZSTDDIR)/legacy/*.c) legacy.c legacy : $(ZSTD_FILES) $(wildcard $(ZSTDDIR)/legacy/*.c) legacy.c
$(CC) $(FLAGS) $^ -o $@$(EXT) $(CC) $(FLAGS) $^ -o $@$(EXT)
decodecorpus : $(filter-out zstdc_zstd_compress.o, $(ZSTD_OBJECTS)) $(ZDICT_FILES) $(PRGDIR)/util.c decodecorpus.c decodecorpus : $(filter-out zstdc_zstd_compress.o, $(ZSTD_OBJECTS)) $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c decodecorpus.c
$(CC) $(FLAGS) $^ -o $@$(EXT) -lm $(CC) $(FLAGS) $^ -o $@$(EXT) -lm
symbols : symbols.c zstd-dll symbols : symbols.c zstd-dll
@@ -233,7 +233,7 @@ else
$(CC) $(FLAGS) $< -o $@$(EXT) -Wl,-rpath=$(ZSTDDIR) $(ZSTDDIR)/libzstd.so # broken on Mac $(CC) $(FLAGS) $< -o $@$(EXT) -Wl,-rpath=$(ZSTDDIR) $(ZSTDDIR)/libzstd.so # broken on Mac
endif endif
poolTests : $(PRGDIR)/util.c poolTests.c $(ZSTDDIR)/common/pool.c $(ZSTDDIR)/common/threading.c $(ZSTDDIR)/common/zstd_common.c $(ZSTDDIR)/common/error_private.c poolTests : $(PRGDIR)/util.c $(PRGDIR)/timefn.c poolTests.c $(ZSTDDIR)/common/pool.c $(ZSTDDIR)/common/threading.c $(ZSTDDIR)/common/zstd_common.c $(ZSTDDIR)/common/error_private.c
$(CC) $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT) $(CC) $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT)
.PHONY: versionsTest .PHONY: versionsTest
@@ -353,8 +353,12 @@ test-gzstd: gzstd
$(RM) *.gz *.zst README2.md gz_zstd zstd_gz hello.txt $(RM) *.gz *.zst README2.md gz_zstd zstd_gz hello.txt
test-zstdgrep: gzstd test-zstdgrep: gzstd
@echo a | $(PRGDIR)/zstd | $(PRGDIR)/zstdgrep a -[ -f /tmp/zstdcat ] || ln -s $(PWD)/$(PRGDIR)/zstd /tmp/zstdcat
@echo a | $(PRGDIR)/zstd | $(PRGDIR)/zstdgrep b && return 1 || return 0 echo a | $(PRGDIR)/zstd | env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep a
echo a | $(PRGDIR)/zstd | env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep b && return 1 || return 0
-echo 'hello world' > test.txt && $(PRGDIR)/zstd test.txt
env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep hello test.txt.zst
env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep weird test.txt.zst && return 1 || return 0
test-fullbench: fullbench datagen test-fullbench: fullbench datagen
$(QEMU_SYS) ./fullbench -i1 $(QEMU_SYS) ./fullbench -i1
+2 -2
View File
@@ -72,7 +72,7 @@ Command line tool to generate test .zst files.
This tool will generate .zst files with checksums, This tool will generate .zst files with checksums,
as well as optionally output the corresponding correct uncompressed data for as well as optionally output the corresponding correct uncompressed data for
extra verfication. extra verification.
Example: Example:
``` ```
@@ -123,7 +123,7 @@ Full list of arguments
Higher values will make optimizer run longer, more chances to find better solution. Higher values will make optimizer run longer, more chances to find better solution.
memLog : Limits the log of the size of each memotable (1 per strategy). Will use hash tables when state space is larger than max size. memLog : Limits the log of the size of each memotable (1 per strategy). Will use hash tables when state space is larger than max size.
Setting memLog = 0 turns off memoization Setting memLog = 0 turns off memoization
--display= : specifiy which parameters are included in the output --display= : specify which parameters are included in the output
can use all --zstd parameter names and 'cParams' as a shorthand for all parameters used in ZSTD_compressionParameters can use all --zstd parameter names and 'cParams' as a shorthand for all parameters used in ZSTD_compressionParameters
(Default: display all params available) (Default: display all params available)
-P# : generated sample compressibility (when no file is provided) -P# : generated sample compressibility (when no file is provided)
+5 -2
View File
@@ -16,6 +16,7 @@
#include <string.h> #include <string.h>
#include "util.h" #include "util.h"
#include "timefn.h" /* UTIL_clockSpanMicro, SEC_TO_MICRO, UTIL_TIME_INITIALIZER */
#include "zstd.h" #include "zstd.h"
#include "zstd_internal.h" #include "zstd_internal.h"
#include "mem.h" #include "mem.h"
@@ -513,7 +514,7 @@ static size_t writeLiteralsBlockCompressed(U32* seed, frame_t* frame, size_t con
if ((RAND(seed) & 3) || !frame->stats.hufInit) { if ((RAND(seed) & 3) || !frame->stats.hufInit) {
do { do {
if (RAND(seed) & 3) { if (RAND(seed) & 3) {
/* add 10 to ensure some compressability */ /* add 10 to ensure some compressibility */
double const weight = ((RAND(seed) % 90) + 10) / 100.0; double const weight = ((RAND(seed) % 90) + 10) / 100.0;
DISPLAYLEVEL(5, " distribution weight: %d%%\n", DISPLAYLEVEL(5, " distribution weight: %d%%\n",
@@ -938,7 +939,9 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr,
FSE_CState_t stateOffsetBits; FSE_CState_t stateOffsetBits;
FSE_CState_t stateLitLength; FSE_CState_t stateLitLength;
CHECK_E(BIT_initCStream(&blockStream, op, oend-op), dstSize_tooSmall); /* not enough space remaining */ RETURN_ERROR_IF(
ERR_isError(BIT_initCStream(&blockStream, op, oend-op)),
dstSize_tooSmall, "not enough space remaining");
/* first symbols */ /* first symbols */
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]); FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
+26 -28
View File
@@ -17,6 +17,7 @@
#include <stdio.h> /* fprintf, fopen, ftello64 */ #include <stdio.h> /* fprintf, fopen, ftello64 */
#include <assert.h> /* assert */ #include <assert.h> /* assert */
#include "timefn.h" /* UTIL_clockSpanNano, UTIL_getTime */
#include "mem.h" /* U32 */ #include "mem.h" /* U32 */
#ifndef ZSTD_DLL_IMPORT #ifndef ZSTD_DLL_IMPORT
#include "zstd_internal.h" /* ZSTD_decodeSeqHeaders, ZSTD_blockHeaderSize, blockType_e, KB, MB */ #include "zstd_internal.h" /* ZSTD_decodeSeqHeaders, ZSTD_blockHeaderSize, blockType_e, KB, MB */
@@ -67,12 +68,6 @@ static const size_t g_sampleSize = 10000000;
static unsigned g_nbIterations = NBLOOPS; static unsigned g_nbIterations = NBLOOPS;
static double g_compressibility = COMPRESSIBILITY_DEFAULT; static double g_compressibility = COMPRESSIBILITY_DEFAULT;
static void BMK_SetNbIterations(unsigned nbLoops)
{
g_nbIterations = nbLoops;
DISPLAY("- %i iterations -\n", g_nbIterations);
}
/*_******************************************************* /*_*******************************************************
* Private functions * Private functions
@@ -316,9 +311,9 @@ static size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize,
/*_******************************************************* /*_*******************************************************
* Bench functions * Bench functions
*********************************************************/ *********************************************************/
static size_t benchMem(unsigned benchNb, static int benchMem(unsigned benchNb,
const void* src, size_t srcSize, const void* src, size_t srcSize,
int cLevel, ZSTD_compressionParameters cparams) int cLevel, ZSTD_compressionParameters cparams)
{ {
size_t dstBuffSize = ZSTD_compressBound(srcSize); size_t dstBuffSize = ZSTD_compressBound(srcSize);
BYTE* dstBuff; BYTE* dstBuff;
@@ -395,22 +390,22 @@ static size_t benchMem(unsigned benchNb,
cparams->minMatch, cparams->targetLength, cparams->strategy); */ cparams->minMatch, cparams->targetLength, cparams->strategy); */
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel);
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_windowLog, cparams.windowLog); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_windowLog, (int)cparams.windowLog);
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_hashLog, cparams.hashLog); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_hashLog, (int)cparams.hashLog);
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_chainLog, cparams.chainLog); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_chainLog, (int)cparams.chainLog);
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_searchLog, cparams.searchLog); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_searchLog, (int)cparams.searchLog);
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_minMatch, cparams.minMatch); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_minMatch, (int)cparams.minMatch);
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_targetLength, cparams.targetLength); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_targetLength, (int)cparams.targetLength);
ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_strategy, cparams.strategy); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_strategy, cparams.strategy);
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_compressionLevel, cLevel); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_compressionLevel, cLevel);
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_windowLog, cparams.windowLog); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_windowLog, (int)cparams.windowLog);
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_hashLog, cparams.hashLog); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_hashLog, (int)cparams.hashLog);
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_chainLog, cparams.chainLog); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_chainLog, (int)cparams.chainLog);
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_searchLog, cparams.searchLog); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_searchLog, (int)cparams.searchLog);
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_minMatch, cparams.minMatch); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_minMatch, (int)cparams.minMatch);
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_targetLength, cparams.targetLength); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_targetLength, (int)cparams.targetLength);
ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_strategy, cparams.strategy); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_strategy, cparams.strategy);
/* Preparation */ /* Preparation */
@@ -469,8 +464,9 @@ static size_t benchMem(unsigned benchNb,
iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */ iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */
ip += ZSTD_blockHeaderSize; /* skip block header */ ip += ZSTD_blockHeaderSize; /* skip block header */
ZSTD_decompressBegin(g_zdc); ZSTD_decompressBegin(g_zdc);
ip += ZSTD_decodeLiteralsBlock(g_zdc, ip, iend-ip); /* skip literal segment */ assert(iend > ip);
g_cSize = iend-ip; ip += ZSTD_decodeLiteralsBlock(g_zdc, ip, (size_t)(iend-ip)); /* skip literal segment */
g_cSize = (size_t)(iend-ip);
memcpy(buff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */ memcpy(buff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */
srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */
break; break;
@@ -501,7 +497,7 @@ static size_t benchMem(unsigned benchNb,
BMK_benchParams_t bp; BMK_benchParams_t bp;
BMK_runTime_t bestResult; BMK_runTime_t bestResult;
bestResult.sumOfReturn = 0; bestResult.sumOfReturn = 0;
bestResult.nanoSecPerRun = (unsigned long long)(-1LL); bestResult.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000; /* hopefully large enough : must be larger than any potential measurement */
assert(tfs != NULL); assert(tfs != NULL);
bp.benchFn = benchFunction; bp.benchFn = benchFunction;
@@ -654,7 +650,9 @@ static unsigned readU32FromChar(const char** stringPtr)
while ((**stringPtr >='0') && (**stringPtr <='9')) { while ((**stringPtr >='0') && (**stringPtr <='9')) {
unsigned const max = (((unsigned)(-1)) / 10) - 1; unsigned const max = (((unsigned)(-1)) / 10) - 1;
if (result > max) ERROR_OUT(errorMsg); if (result > max) ERROR_OUT(errorMsg);
result *= 10, result += **stringPtr - '0', (*stringPtr)++ ; result *= 10;
result += (unsigned)(**stringPtr - '0');
(*stringPtr)++ ;
} }
if ((**stringPtr=='K') || (**stringPtr=='M')) { if ((**stringPtr=='K') || (**stringPtr=='M')) {
unsigned const maxK = ((unsigned)(-1)) >> 10; unsigned const maxK = ((unsigned)(-1)) >> 10;
@@ -671,7 +669,7 @@ static unsigned readU32FromChar(const char** stringPtr)
return result; return result;
} }
static unsigned longCommandWArg(const char** stringPtr, const char* longCommand) static int longCommandWArg(const char** stringPtr, const char* longCommand)
{ {
size_t const comSize = strlen(longCommand); size_t const comSize = strlen(longCommand);
int const result = !strncmp(*stringPtr, longCommand, comSize); int const result = !strncmp(*stringPtr, longCommand, comSize);
@@ -772,7 +770,7 @@ int main(int argc, const char** argv)
/* Modify Nb Iterations */ /* Modify Nb Iterations */
case 'i': case 'i':
argument++; argument++;
BMK_SetNbIterations((int)readU32FromChar(&argument)); g_nbIterations = readU32FromChar(&argument);
break; break;
/* Select compressibility of synthetic sample */ /* Select compressibility of synthetic sample */
@@ -782,7 +780,7 @@ int main(int argc, const char** argv)
break; break;
case 'l': case 'l':
argument++; argument++;
cLevel = readU32FromChar(&argument); cLevel = (int)readU32FromChar(&argument);
cparams = ZSTD_getCParams(cLevel, 0, 0); cparams = ZSTD_getCParams(cLevel, 0, 0);
break; break;
+16 -6
View File
@@ -27,16 +27,16 @@ PRGDIR = ../../programs
FUZZ_CPPFLAGS := -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \ FUZZ_CPPFLAGS := -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \
-I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR) \ -I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR) \
$(CPPFLAGS) -DZSTD_MULTITHREAD $(CPPFLAGS)
FUZZ_EXTRA_FLAGS := -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ FUZZ_EXTRA_FLAGS := -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
-Wstrict-prototypes -Wundef -Wformat-security \ -Wstrict-prototypes -Wundef \
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
-Wredundant-decls \ -Wredundant-decls \
-g -fno-omit-frame-pointer -g -fno-omit-frame-pointer
FUZZ_CFLAGS := $(FUZZ_EXTRA_FLAGS) $(CFLAGS) FUZZ_CFLAGS := $(FUZZ_EXTRA_FLAGS) $(CFLAGS)
FUZZ_CXXFLAGS := $(FUZZ_EXTRA_FLAGS) -std=c++11 $(CXXFLAGS) FUZZ_CXXFLAGS := $(FUZZ_EXTRA_FLAGS) -std=c++11 $(CXXFLAGS)
FUZZ_LDFLAGS := $(LDFLAGS) FUZZ_LDFLAGS := -pthread $(LDFLAGS)
FUZZ_ARFLAGS := $(ARFLAGS) FUZZ_ARFLAGS := $(ARFLAGS)
FUZZ_TARGET_FLAGS = $(FUZZ_CPPFLAGS) $(FUZZ_CXXFLAGS) $(FUZZ_LDFLAGS) FUZZ_TARGET_FLAGS = $(FUZZ_CPPFLAGS) $(FUZZ_CXXFLAGS) $(FUZZ_LDFLAGS)
@@ -46,11 +46,13 @@ FUZZ_SRC := $(PRGDIR)/util.c zstd_helpers.c
ZSTDCOMMON_SRC := $(ZSTDDIR)/common/*.c ZSTDCOMMON_SRC := $(ZSTDDIR)/common/*.c
ZSTDCOMP_SRC := $(ZSTDDIR)/compress/*.c ZSTDCOMP_SRC := $(ZSTDDIR)/compress/*.c
ZSTDDECOMP_SRC := $(ZSTDDIR)/decompress/*.c ZSTDDECOMP_SRC := $(ZSTDDIR)/decompress/*.c
ZSTDDICT_SRC := $(ZSTDDIR)/dictBuilder/*.c
FUZZ_SRC := \ FUZZ_SRC := \
$(FUZZ_SRC) \ $(FUZZ_SRC) \
$(ZSTDDECOMP_SRC) \ $(ZSTDDECOMP_SRC) \
$(ZSTDCOMMON_SRC) \ $(ZSTDCOMMON_SRC) \
$(ZSTDCOMP_SRC) $(ZSTDCOMP_SRC) \
$(ZSTDDICT_SRC)
FUZZ_OBJ := $(patsubst %.c,%.o, $(wildcard $(FUZZ_SRC))) FUZZ_OBJ := $(patsubst %.c,%.o, $(wildcard $(FUZZ_SRC)))
@@ -65,7 +67,9 @@ FUZZ_TARGETS := \
block_round_trip \ block_round_trip \
simple_decompress \ simple_decompress \
stream_decompress \ stream_decompress \
block_decompress block_decompress \
dictionary_round_trip \
dictionary_decompress
all: $(FUZZ_TARGETS) all: $(FUZZ_TARGETS)
@@ -90,11 +94,17 @@ stream_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) stream_decompress.o
block_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) block_decompress.o block_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) block_decompress.o
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) block_decompress.o $(LIB_FUZZING_ENGINE) -o $@ $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) block_decompress.o $(LIB_FUZZING_ENGINE) -o $@
dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_round_trip.o
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_round_trip.o $(LIB_FUZZING_ENGINE) -o $@
dictionary_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_decompress.o
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_decompress.o $(LIB_FUZZING_ENGINE) -o $@
libregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c regression_driver.o libregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c regression_driver.o
$(AR) $(FUZZ_ARFLAGS) $@ regression_driver.o $(AR) $(FUZZ_ARFLAGS) $@ regression_driver.o
# Install libfuzzer (not usable for MSAN testing) # Install libfuzzer (not usable for MSAN testing)
# Provided for convienence. To use this library run make libFuzzer and # Provided for convenience. To use this library run make libFuzzer and
# set LDFLAGS=-L. # set LDFLAGS=-L.
.PHONY: libFuzzer .PHONY: libFuzzer
libFuzzer: libFuzzer:
+2 -2
View File
@@ -37,8 +37,8 @@ The specific fuzzing engine is selected with `LIB_FUZZING_ENGINE` or
`--lib-fuzzing-engine`, the default is `libregression.a`. `--lib-fuzzing-engine`, the default is `libregression.a`.
It has flags that can easily set up sanitizers `--enable-{a,ub,m}san`, and It has flags that can easily set up sanitizers `--enable-{a,ub,m}san`, and
coverage instrumentation `--enable-coverage`. coverage instrumentation `--enable-coverage`.
It sets sane defaults which can be overriden with flags `--debug`, It sets sane defaults which can be overridden with flags `--debug`,
`--enable-ubsan-pointer-overlow`, etc. `--enable-ubsan-pointer-overflow`, etc.
Run `./fuzz.py build -h` for help. Run `./fuzz.py build -h` for help.
### Running Fuzzers ### Running Fuzzers
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2016-present, Facebook, Inc.
* 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).
*/
/**
* This fuzz target attempts to decompress the fuzzed data with the dictionary
* decompression function to ensure the decompressor never crashes. It does not
* fuzz the dictionary.
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include "fuzz_helpers.h"
#include "zstd_helpers.h"
static ZSTD_DCtx *dctx = NULL;
static void* rBuf = NULL;
static size_t bufSize = 0;
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
FUZZ_dict_t dict;
size_t neededBufSize;
uint32_t seed = FUZZ_seed(&src, &size);
neededBufSize = MAX(20 * size, (size_t)256 << 10);
/* Allocate all buffers and contexts if not already allocated */
if (neededBufSize > bufSize) {
free(rBuf);
rBuf = malloc(neededBufSize);
bufSize = neededBufSize;
FUZZ_ASSERT(rBuf);
}
if (!dctx) {
dctx = ZSTD_createDCtx();
FUZZ_ASSERT(dctx);
}
dict = FUZZ_train(src, size, &seed);
if (FUZZ_rand32(&seed, 0, 1) == 0) {
ZSTD_decompress_usingDict(dctx,
rBuf, neededBufSize,
src, size,
dict.buff, dict.size);
} else {
FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
dctx, dict.buff, dict.size,
(ZSTD_dictLoadMethod_e)FUZZ_rand32(&seed, 0, 1),
(ZSTD_dictContentType_e)FUZZ_rand32(&seed, 0, 2)));
ZSTD_decompressDCtx(dctx, rBuf, neededBufSize, src, size);
}
free(dict.buff);
#ifndef STATEFUL_FUZZING
ZSTD_freeDCtx(dctx); dctx = NULL;
#endif
return 0;
}
+106
View File
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2016-present, Facebook, Inc.
* 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).
*/
/**
* This fuzz target performs a zstd round-trip test (compress & decompress) with
* a dictionary, compares the result with the original, and calls abort() on
* corruption.
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "fuzz_helpers.h"
#include "zstd_helpers.h"
static const int kMaxClevel = 19;
static ZSTD_CCtx *cctx = NULL;
static ZSTD_DCtx *dctx = NULL;
static uint32_t seed;
static size_t roundTripTest(void *result, size_t resultCapacity,
void *compressed, size_t compressedCapacity,
const void *src, size_t srcSize)
{
ZSTD_dictContentType_e dictContentType = ZSTD_dct_auto;
FUZZ_dict_t dict = FUZZ_train(src, srcSize, &seed);
size_t cSize;
if ((FUZZ_rand(&seed) & 15) == 0) {
int const cLevel = FUZZ_rand(&seed) % kMaxClevel;
cSize = ZSTD_compress_usingDict(cctx,
compressed, compressedCapacity,
src, srcSize,
dict.buff, dict.size,
cLevel);
} else {
dictContentType = FUZZ_rand32(&seed, 0, 2);
FUZZ_setRandomParameters(cctx, srcSize, &seed);
/* Disable checksum so we can use sizes smaller than compress bound. */
FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0));
FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(
cctx, dict.buff, dict.size,
(ZSTD_dictLoadMethod_e)FUZZ_rand32(&seed, 0, 1),
dictContentType));
cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);
}
FUZZ_ZASSERT(cSize);
FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
dctx, dict.buff, dict.size,
(ZSTD_dictLoadMethod_e)FUZZ_rand32(&seed, 0, 1),
dictContentType));
{
size_t const ret = ZSTD_decompressDCtx(
dctx, result, resultCapacity, compressed, cSize);
free(dict.buff);
return ret;
}
}
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
size_t const rBufSize = size;
void* rBuf = malloc(rBufSize);
size_t cBufSize = ZSTD_compressBound(size);
void* cBuf;
seed = FUZZ_seed(&src, &size);
/* Half of the time fuzz with a 1 byte smaller output size.
* This will still succeed because we force the checksum to be disabled,
* giving us 4 bytes of overhead.
*/
cBufSize -= FUZZ_rand32(&seed, 0, 1);
cBuf = malloc(cBufSize);
if (!cctx) {
cctx = ZSTD_createCCtx();
FUZZ_ASSERT(cctx);
}
if (!dctx) {
dctx = ZSTD_createDCtx();
FUZZ_ASSERT(dctx);
}
{
size_t const result =
roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size);
FUZZ_ZASSERT(result);
FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size");
FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!");
}
free(rBuf);
free(cBuf);
#ifndef STATEFUL_FUZZING
ZSTD_freeCCtx(cctx); cctx = NULL;
ZSTD_freeDCtx(dctx); dctx = NULL;
#endif
return 0;
}
+22 -6
View File
@@ -34,6 +34,8 @@ TARGETS = [
'simple_decompress', 'simple_decompress',
'stream_decompress', 'stream_decompress',
'block_decompress', 'block_decompress',
'dictionary_round_trip',
'dictionary_decompress',
] ]
ALL_TARGETS = TARGETS + ['all'] ALL_TARGETS = TARGETS + ['all']
FUZZ_RNG_SEED_SIZE = 4 FUZZ_RNG_SEED_SIZE = 4
@@ -192,11 +194,21 @@ def build_parser(args):
default=LIB_FUZZING_ENGINE, default=LIB_FUZZING_ENGINE,
help=('The fuzzing engine to use e.g. /path/to/libFuzzer.a ' help=('The fuzzing engine to use e.g. /path/to/libFuzzer.a '
"(default: $LIB_FUZZING_ENGINE='{})".format(LIB_FUZZING_ENGINE))) "(default: $LIB_FUZZING_ENGINE='{})".format(LIB_FUZZING_ENGINE)))
parser.add_argument(
fuzz_group = parser.add_mutually_exclusive_group()
fuzz_group.add_argument(
'--enable-coverage', '--enable-coverage',
dest='coverage', dest='coverage',
action='store_true', action='store_true',
help='Enable coverage instrumentation (-fsanitize-coverage)') help='Enable coverage instrumentation (-fsanitize-coverage)')
fuzz_group.add_argument(
'--enable-fuzzer',
dest='fuzzer',
action='store_true',
help=('Enable clang fuzzer (-fsanitize=fuzzer). When enabled '
'LIB_FUZZING_ENGINE is ignored')
)
parser.add_argument( parser.add_argument(
'--enable-asan', dest='asan', action='store_true', help='Enable UBSAN') '--enable-asan', dest='asan', action='store_true', help='Enable UBSAN')
parser.add_argument( parser.add_argument(
@@ -327,13 +339,13 @@ def build_parser(args):
args = parse_env_flags(args, ' '.join( args = parse_env_flags(args, ' '.join(
[args.cppflags, args.cflags, args.cxxflags, args.ldflags])) [args.cppflags, args.cflags, args.cxxflags, args.ldflags]))
# Check option sanitiy # Check option sanity
if args.msan and (args.asan or args.ubsan): if args.msan and (args.asan or args.ubsan):
raise RuntimeError('MSAN may not be used with any other sanitizers') raise RuntimeError('MSAN may not be used with any other sanitizers')
if args.msan_track_origins and not args.msan: if args.msan_track_origins and not args.msan:
raise RuntimeError('--enable-msan-track-origins requires MSAN') raise RuntimeError('--enable-msan-track-origins requires MSAN')
if args.ubsan_pointer_overflow and not args.ubsan: if args.ubsan_pointer_overflow and not args.ubsan:
raise RuntimeError('--enable-ubsan-pointer-overlow requires UBSAN') raise RuntimeError('--enable-ubsan-pointer-overflow requires UBSAN')
if args.sanitize_recover and not args.sanitize: if args.sanitize_recover and not args.sanitize:
raise RuntimeError('--enable-sanitize-recover but no sanitizers used') raise RuntimeError('--enable-sanitize-recover but no sanitizers used')
@@ -364,13 +376,17 @@ def build(args):
'-DFUZZ_RNG_SEED_SIZE={}'.format(args.fuzz_rng_seed_size), '-DFUZZ_RNG_SEED_SIZE={}'.format(args.fuzz_rng_seed_size),
] ]
mflags += ['LIB_FUZZING_ENGINE={}'.format(args.lib_fuzzing_engine)]
# Set flags for options # Set flags for options
assert not (args.fuzzer and args.coverage)
if args.coverage: if args.coverage:
common_flags += [ common_flags += [
'-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp' '-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp'
] ]
if args.fuzzer:
common_flags += ['-fsanitize=fuzzer']
args.lib_fuzzing_engine = ''
mflags += ['LIB_FUZZING_ENGINE={}'.format(args.lib_fuzzing_engine)]
if args.sanitize_recover: if args.sanitize_recover:
recover_flags = ['-fsanitize-recover=all'] recover_flags = ['-fsanitize-recover=all']
@@ -607,7 +623,7 @@ def regression(args):
def gen_parser(args): def gen_parser(args):
description = """ description = """
Generate a seed corpus appropiate for TARGET with data generated with Generate a seed corpus appropriate for TARGET with data generated with
decodecorpus. decodecorpus.
The fuzz inputs are prepended with a seed before the zstd data, so the The fuzz inputs are prepended with a seed before the zstd data, so the
output of decodecorpus shouldn't be used directly. output of decodecorpus shouldn't be used directly.
+1 -1
View File
@@ -55,7 +55,7 @@ extern "C" {
#endif #endif
/** /**
* Determininistically constructs a seed based on the fuzz input. * Deterministically constructs a seed based on the fuzz input.
* Consumes up to the first FUZZ_RNG_SEED_SIZE bytes of the input. * Consumes up to the first FUZZ_RNG_SEED_SIZE bytes of the input.
*/ */
FUZZ_STATIC uint32_t FUZZ_seed(uint8_t const **src, size_t* size) { FUZZ_STATIC uint32_t FUZZ_seed(uint8_t const **src, size_t* size) {
+7 -2
View File
@@ -40,8 +40,13 @@ int main(int argc, char const **argv) {
size_t readSize; size_t readSize;
FILE *file; FILE *file;
/* Check that it is a regular file, and that the fileSize is valid */ /* Check that it is a regular file, and that the fileSize is valid.
FUZZ_ASSERT_MSG(UTIL_isRegularFile(fileName), fileName); * If it is not a regular file, then it may have been deleted since we
* constructed the list, so just skip it.
*/
if (!UTIL_isRegularFile(fileName)) {
continue;
}
FUZZ_ASSERT_MSG(fileSize <= kMaxFileSize, fileName); FUZZ_ASSERT_MSG(fileSize <= kMaxFileSize, fileName);
/* Ensure we have a large enough buffer allocated */ /* Ensure we have a large enough buffer allocated */
if (fileSize > bufferSize) { if (fileSize > bufferSize) {
+16 -24
View File
@@ -25,9 +25,6 @@ static const int kMaxClevel = 19;
static ZSTD_CCtx *cctx = NULL; static ZSTD_CCtx *cctx = NULL;
static ZSTD_DCtx *dctx = NULL; static ZSTD_DCtx *dctx = NULL;
static void* cBuf = NULL;
static void* rBuf = NULL;
static size_t bufSize = 0;
static uint32_t seed; static uint32_t seed;
static size_t roundTripTest(void *result, size_t resultCapacity, static size_t roundTripTest(void *result, size_t resultCapacity,
@@ -36,16 +33,8 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
{ {
size_t cSize; size_t cSize;
if (FUZZ_rand(&seed) & 1) { if (FUZZ_rand(&seed) & 1) {
ZSTD_inBuffer in = {src, srcSize, 0};
ZSTD_outBuffer out = {compressed, compressedCapacity, 0};
size_t err;
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
FUZZ_setRandomParameters(cctx, srcSize, &seed); FUZZ_setRandomParameters(cctx, srcSize, &seed);
err = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end); cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);
FUZZ_ZASSERT(err);
FUZZ_ASSERT(err == 0);
cSize = out.pos;
} else { } else {
int const cLevel = FUZZ_rand(&seed) % kMaxClevel; int const cLevel = FUZZ_rand(&seed) % kMaxClevel;
cSize = ZSTD_compressCCtx( cSize = ZSTD_compressCCtx(
@@ -57,20 +46,21 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{ {
size_t neededBufSize; size_t const rBufSize = size;
void* rBuf = malloc(rBufSize);
size_t cBufSize = ZSTD_compressBound(size);
void* cBuf;
seed = FUZZ_seed(&src, &size); seed = FUZZ_seed(&src, &size);
neededBufSize = ZSTD_compressBound(size); /* Half of the time fuzz with a 1 byte smaller output size.
* This will still succeed because we don't use a dictionary, so the dictID
* field is empty, giving us 4 bytes of overhead.
*/
cBufSize -= FUZZ_rand32(&seed, 0, 1);
cBuf = malloc(cBufSize);
FUZZ_ASSERT(cBuf && rBuf);
/* Allocate all buffers and contexts if not already allocated */
if (neededBufSize > bufSize) {
free(cBuf);
free(rBuf);
cBuf = malloc(neededBufSize);
rBuf = malloc(neededBufSize);
bufSize = neededBufSize;
FUZZ_ASSERT(cBuf && rBuf);
}
if (!cctx) { if (!cctx) {
cctx = ZSTD_createCCtx(); cctx = ZSTD_createCCtx();
FUZZ_ASSERT(cctx); FUZZ_ASSERT(cctx);
@@ -82,11 +72,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{ {
size_t const result = size_t const result =
roundTripTest(rBuf, neededBufSize, cBuf, neededBufSize, src, size); roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size);
FUZZ_ZASSERT(result); FUZZ_ZASSERT(result);
FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size"); FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size");
FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!"); FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!");
} }
free(rBuf);
free(cBuf);
#ifndef STATEFUL_FUZZING #ifndef STATEFUL_FUZZING
ZSTD_freeCCtx(cctx); cctx = NULL; ZSTD_freeCCtx(cctx); cctx = NULL;
ZSTD_freeDCtx(dctx); dctx = NULL; ZSTD_freeDCtx(dctx); dctx = NULL;
+1 -3
View File
@@ -62,9 +62,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
if (!dstream) { if (!dstream) {
dstream = ZSTD_createDStream(); dstream = ZSTD_createDStream();
FUZZ_ASSERT(dstream); FUZZ_ASSERT(dstream);
FUZZ_ASSERT(!ZSTD_isError(ZSTD_initDStream(dstream)));
} else { } else {
FUZZ_ASSERT(!ZSTD_isError(ZSTD_resetDStream(dstream))); FUZZ_ZASSERT(ZSTD_DCtx_reset(dstream, ZSTD_reset_session_only));
} }
while (size > 0) { while (size > 0) {
@@ -73,7 +72,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
ZSTD_outBuffer out = makeOutBuffer(); ZSTD_outBuffer out = makeOutBuffer();
size_t const rc = ZSTD_decompressStream(dstream, &out, &in); size_t const rc = ZSTD_decompressStream(dstream, &out, &in);
if (ZSTD_isError(rc)) goto error; if (ZSTD_isError(rc)) goto error;
if (rc == 0) FUZZ_ASSERT(!ZSTD_isError(ZSTD_resetDStream(dstream)));
} }
} }
+1 -1
View File
@@ -63,7 +63,7 @@ static size_t compress(uint8_t *dst, size_t capacity,
ZSTD_inBuffer in = makeInBuffer(&src, &srcSize); ZSTD_inBuffer in = makeInBuffer(&src, &srcSize);
/* Mode controls the action. If mode == -1 we pick a new mode */ /* Mode controls the action. If mode == -1 we pick a new mode */
int mode = -1; int mode = -1;
while (in.pos < in.size) { while (in.pos < in.size || mode != -1) {
ZSTD_outBuffer out = makeOutBuffer(dst, capacity); ZSTD_outBuffer out = makeOutBuffer(dst, capacity);
/* Previous action finished, pick a new mode. */ /* Previous action finished, pick a new mode. */
if (mode == -1) mode = FUZZ_rand(&seed) % 10; if (mode == -1) mode = FUZZ_rand(&seed) % 10;
+55 -2
View File
@@ -8,10 +8,14 @@
*/ */
#define ZSTD_STATIC_LINKING_ONLY #define ZSTD_STATIC_LINKING_ONLY
#define ZDICT_STATIC_LINKING_ONLY
#include <string.h>
#include "zstd_helpers.h" #include "zstd_helpers.h"
#include "fuzz_helpers.h" #include "fuzz_helpers.h"
#include "zstd.h" #include "zstd.h"
#include "zdict.h"
static void set(ZSTD_CCtx *cctx, ZSTD_cParameter param, int value) static void set(ZSTD_CCtx *cctx, ZSTD_cParameter param, int value)
{ {
@@ -71,8 +75,7 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, uint32_t *state)
setRand(cctx, ZSTD_c_contentSizeFlag, 0, 1, state); setRand(cctx, ZSTD_c_contentSizeFlag, 0, 1, state);
setRand(cctx, ZSTD_c_checksumFlag, 0, 1, state); setRand(cctx, ZSTD_c_checksumFlag, 0, 1, state);
setRand(cctx, ZSTD_c_dictIDFlag, 0, 1, state); setRand(cctx, ZSTD_c_dictIDFlag, 0, 1, state);
setRand(cctx, ZSTD_c_forceAttachDict, 0, 2, state); /* Select long distance matching parameters */
/* Select long distance matchig parameters */
setRand(cctx, ZSTD_c_enableLongDistanceMatching, 0, 1, state); setRand(cctx, ZSTD_c_enableLongDistanceMatching, 0, 1, state);
setRand(cctx, ZSTD_c_ldmHashLog, ZSTD_HASHLOG_MIN, 16, state); setRand(cctx, ZSTD_c_ldmHashLog, ZSTD_HASHLOG_MIN, 16, state);
setRand(cctx, ZSTD_c_ldmMinMatch, ZSTD_LDM_MINMATCH_MIN, setRand(cctx, ZSTD_c_ldmMinMatch, ZSTD_LDM_MINMATCH_MIN,
@@ -81,4 +84,54 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, uint32_t *state)
state); state);
setRand(cctx, ZSTD_c_ldmHashRateLog, ZSTD_LDM_HASHRATELOG_MIN, setRand(cctx, ZSTD_c_ldmHashRateLog, ZSTD_LDM_HASHRATELOG_MIN,
ZSTD_LDM_HASHRATELOG_MAX, state); ZSTD_LDM_HASHRATELOG_MAX, state);
/* Set misc parameters */
setRand(cctx, ZSTD_c_nbWorkers, 0, 2, state);
setRand(cctx, ZSTD_c_rsyncable, 0, 1, state);
setRand(cctx, ZSTD_c_forceMaxWindow, 0, 1, state);
setRand(cctx, ZSTD_c_literalCompressionMode, 0, 2, state);
setRand(cctx, ZSTD_c_forceAttachDict, 0, 2, state);
}
FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, uint32_t *state)
{
size_t const dictSize = MAX(srcSize / 8, 1024);
size_t const totalSampleSize = dictSize * 11;
FUZZ_dict_t dict = { malloc(dictSize), dictSize };
char* const samples = (char*)malloc(totalSampleSize);
unsigned nbSamples = 100;
size_t* const samplesSizes = (size_t*)malloc(sizeof(size_t) * nbSamples);
size_t pos = 0;
size_t sample = 0;
ZDICT_fastCover_params_t params;
FUZZ_ASSERT(dict.buff && samples && samplesSizes);
for (sample = 0; sample < nbSamples; ++sample) {
size_t const remaining = totalSampleSize - pos;
size_t const offset = FUZZ_rand32(state, 0, MAX(srcSize, 1) - 1);
size_t const limit = MIN(srcSize - offset, remaining);
size_t const toCopy = MIN(limit, remaining / (nbSamples - sample));
memcpy(samples + pos, src + offset, toCopy);
pos += toCopy;
samplesSizes[sample] = toCopy;
}
memset(samples + pos, 0, totalSampleSize - pos);
memset(&params, 0, sizeof(params));
params.accel = 5;
params.k = 40;
params.d = 8;
params.f = 14;
params.zParams.compressionLevel = 1;
dict.size = ZDICT_trainFromBuffer_fastCover(dict.buff, dictSize,
samples, samplesSizes, nbSamples, params);
if (ZSTD_isError(dict.size)) {
free(dict.buff);
memset(&dict, 0, sizeof(dict));
}
free(samplesSizes);
free(samples);
return dict;
} }
+13
View File
@@ -14,6 +14,8 @@
#ifndef ZSTD_HELPERS_H #ifndef ZSTD_HELPERS_H
#define ZSTD_HELPERS_H #define ZSTD_HELPERS_H
#define ZSTD_STATIC_LINKING_ONLY
#include "zstd.h" #include "zstd.h"
#include <stdint.h> #include <stdint.h>
@@ -27,6 +29,17 @@ ZSTD_compressionParameters FUZZ_randomCParams(size_t srcSize, uint32_t *state);
ZSTD_frameParameters FUZZ_randomFParams(uint32_t *state); ZSTD_frameParameters FUZZ_randomFParams(uint32_t *state);
ZSTD_parameters FUZZ_randomParams(size_t srcSize, uint32_t *state); ZSTD_parameters FUZZ_randomParams(size_t srcSize, uint32_t *state);
typedef struct {
void* buff;
size_t size;
} FUZZ_dict_t;
/* Quickly train a dictionary from a source for fuzzing.
* NOTE: Don't use this to train production dictionaries, it is only optimized
* for speed, and doesn't care about dictionary quality.
*/
FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, uint32_t *state);
#ifdef __cplusplus #ifdef __cplusplus
} }
+285 -4
View File
@@ -38,6 +38,7 @@
#define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ #define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
#include "xxhash.h" /* XXH64 */ #include "xxhash.h" /* XXH64 */
#include "util.h" #include "util.h"
#include "timefn.h" /* SEC_TO_MICRO, UTIL_time_t, UTIL_TIME_INITIALIZER, UTIL_clockSpanMicro, UTIL_getTime */
/*-************************************ /*-************************************
@@ -124,12 +125,14 @@ static U32 FUZ_highbit32(U32 v32)
#define CHECK(fn) { CHECK_V(err, fn); } #define CHECK(fn) { CHECK_V(err, fn); }
#define CHECKPLUS(var, fn, more) { CHECK_V(var, fn); more; } #define CHECKPLUS(var, fn, more) { CHECK_V(var, fn); more; }
#define CHECK_EQ(lhs, rhs) { \ #define CHECK_OP(op, lhs, rhs) { \
if ((lhs) != (rhs)) { \ if (!((lhs) op (rhs))) { \
DISPLAY("Error L%u => %s != %s ", __LINE__, #lhs, #rhs); \ DISPLAY("Error L%u => FAILED %s %s %s ", __LINE__, #lhs, #op, #rhs); \
goto _output_error; \ goto _output_error; \
} \ } \
} }
#define CHECK_EQ(lhs, rhs) CHECK_OP(==, lhs, rhs)
#define CHECK_LT(lhs, rhs) CHECK_OP(<, lhs, rhs)
/*============================================= /*=============================================
@@ -374,6 +377,20 @@ static int basicUnitTests(U32 seed, double compressibility)
} }
DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : tight ZSTD_decompressBound test : ", testNb++);
{
unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize);
if (bound != CNBuffSize) goto _output_error;
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with invalid srcSize : ", testNb++);
{
unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize - 1);
if (bound != ZSTD_CONTENTSIZE_ERROR) goto _output_error;
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize); DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, (unsigned)CNBuffSize);
{ size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize); { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);
if (r != CNBuffSize) goto _output_error; } if (r != CNBuffSize) goto _output_error; }
@@ -429,6 +446,27 @@ static int basicUnitTests(U32 seed, double compressibility)
if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; } if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; }
DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with content size missing : ", testNb++);
{ /* create compressed buffer with content size missing */
ZSTD_CCtx* cctx = ZSTD_createCCtx();
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0) );
CHECKPLUS(r, ZSTD_compress2(cctx,
compressedBuffer, compressedBufferSize,
CNBuffer, CNBuffSize),
cSize=r );
ZSTD_freeCCtx(cctx);
}
{ /* ensure frame content size is missing */
ZSTD_frameHeader zfh;
size_t const ret = ZSTD_getFrameHeader(&zfh, compressedBuffer, compressedBufferSize);
if (ret != 0 || zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error;
}
{ /* ensure CNBuffSize <= decompressBound */
unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, compressedBufferSize);
if (CNBuffSize > bound) goto _output_error;
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3d : check CCtx size after compressing empty input : ", testNb++); DISPLAYLEVEL(3, "test%3d : check CCtx size after compressing empty input : ", testNb++);
{ ZSTD_CCtx* const cctx = ZSTD_createCCtx(); { ZSTD_CCtx* const cctx = ZSTD_createCCtx();
size_t const r = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 19); size_t const r = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 19);
@@ -828,6 +866,59 @@ static int basicUnitTests(U32 seed, double compressibility)
ZSTDMT_freeCCtx(mtctx); ZSTDMT_freeCCtx(mtctx);
} }
DISPLAYLEVEL(3, "test%3i : compress -T2 with/without literals compression : ", testNb++)
{ ZSTD_CCtx* cctx = ZSTD_createCCtx();
size_t cSize1, cSize2;
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2) );
cSize1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
CHECK(cSize1);
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_literalCompressionMode, ZSTD_lcm_uncompressed) );
cSize2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
CHECK(cSize2);
CHECK_LT(cSize1, cSize2);
ZSTD_freeCCtx(cctx);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Multithreaded ZSTD_compress2() with rsyncable : ", testNb++)
{ ZSTD_CCtx* cctx = ZSTD_createCCtx();
/* Set rsyncable and don't give the ZSTD_compressBound(CNBuffSize) so
* ZSTDMT is forced to not take the shortcut.
*/
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1) );
CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_rsyncable, 1) );
CHECK( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize - 1, CNBuffer, CNBuffSize) );
ZSTD_freeCCtx(cctx);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : setting multithreaded parameters : ", testNb++)
{ ZSTD_CCtx_params* params = ZSTD_createCCtxParams();
int value;
/* Check that the overlap log and job size are unset. */
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
CHECK_EQ(value, 0);
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
CHECK_EQ(value, 0);
/* Set and check the overlap log and job size. */
CHECK( ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, 5) );
CHECK( ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, 2 MB) );
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
CHECK_EQ(value, 5);
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
CHECK_EQ(value, 2 MB);
/* Set the number of workers and check the overlap log and job size. */
CHECK( ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, 2) );
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );
CHECK_EQ(value, 5);
CHECK( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );
CHECK_EQ(value, 2 MB);
ZSTD_freeCCtxParams(params);
}
DISPLAYLEVEL(3, "OK \n");
/* Simple API multiframe test */ /* Simple API multiframe test */
DISPLAYLEVEL(3, "test%3i : compress multiple frames : ", testNb++); DISPLAYLEVEL(3, "test%3i : compress multiple frames : ", testNb++);
@@ -859,6 +950,11 @@ static int basicUnitTests(U32 seed, double compressibility)
if (r != CNBuffSize / 2) goto _output_error; } if (r != CNBuffSize / 2) goto _output_error; }
DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : get tight decompressed bound of multiple frames : ", testNb++);
{ unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, cSize);
if (bound != CNBuffSize / 2) goto _output_error; }
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : decompress multiple frames : ", testNb++); DISPLAYLEVEL(3, "test%3i : decompress multiple frames : ", testNb++);
{ CHECK_V(r, ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize)); { CHECK_V(r, ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize));
if (r != CNBuffSize / 2) goto _output_error; } if (r != CNBuffSize / 2) goto _output_error; }
@@ -1203,9 +1299,13 @@ static int basicUnitTests(U32 seed, double compressibility)
{ {
size_t ret; size_t ret;
MEM_writeLE32((char*)dictBuffer+2, ZSTD_MAGIC_DICTIONARY); MEM_writeLE32((char*)dictBuffer+2, ZSTD_MAGIC_DICTIONARY);
/* Either operation is allowed to fail, but one must fail. */
ret = ZSTD_CCtx_loadDictionary_advanced( ret = ZSTD_CCtx_loadDictionary_advanced(
cctx, (const char*)dictBuffer+2, dictSize-2, ZSTD_dlm_byRef, ZSTD_dct_auto); cctx, (const char*)dictBuffer+2, dictSize-2, ZSTD_dlm_byRef, ZSTD_dct_auto);
if (!ZSTD_isError(ret)) goto _output_error; if (!ZSTD_isError(ret)) {
ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100));
if (!ZSTD_isError(ret)) goto _output_error;
}
} }
DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "OK \n");
@@ -1216,6 +1316,187 @@ static int basicUnitTests(U32 seed, double compressibility)
ret = ZSTD_CCtx_loadDictionary_advanced( ret = ZSTD_CCtx_loadDictionary_advanced(
cctx, (const char*)dictBuffer+2, dictSize-2, ZSTD_dlm_byRef, ZSTD_dct_rawContent); cctx, (const char*)dictBuffer+2, dictSize-2, ZSTD_dlm_byRef, ZSTD_dct_rawContent);
if (ZSTD_isError(ret)) goto _output_error; if (ZSTD_isError(ret)) goto _output_error;
ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100));
if (ZSTD_isError(ret)) goto _output_error;
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_CCtx_refCDict() then set parameters : ", testNb++);
{ ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, dictSize, 1);
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 ));
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 ));
ZSTD_freeCDict(cdict);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Loading dictionary before setting parameters is the same as loading after : ", testNb++);
{
size_t size1, size2;
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) );
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
if (ZSTD_isError(size1)) goto _output_error;
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) );
size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
if (ZSTD_isError(size2)) goto _output_error;
if (size1 != size2) goto _output_error;
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the prefix : ", testNb++);
{
CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Loading a dictionary clears the cdict : ", testNb++);
{
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
ZSTD_freeCDict(cdict);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the prefix : ", testNb++);
{
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
ZSTD_freeCDict(cdict);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Loading a cdict clears the dictionary : ", testNb++);
{
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
ZSTD_freeCDict(cdict);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the dictionary : ", testNb++);
{
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );
CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Loading a prefix clears the cdict : ", testNb++);
{
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);
CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );
CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );
CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );
ZSTD_freeCDict(cdict);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Loaded dictionary persists across reset session : ", testNb++);
{
size_t size1, size2;
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
if (ZSTD_isError(size1)) goto _output_error;
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
if (ZSTD_isError(size2)) goto _output_error;
if (size1 != size2) goto _output_error;
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : Loaded dictionary is cleared after resetting parameters : ", testNb++);
{
size_t size1, size2;
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );
size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
if (ZSTD_isError(size1)) goto _output_error;
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
if (ZSTD_isError(size2)) goto _output_error;
if (size1 == size2) goto _output_error;
}
DISPLAYLEVEL(3, "OK \n");
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, dictBuffer, dictSize) );
cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));
CHECK_Z(cSize);
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with dictionary : ", testNb++);
{
ZSTD_DCtx* dctx = ZSTD_createDCtx();
size_t ret;
/* We should fail to decompress without a dictionary. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
if (!ZSTD_isError(ret)) goto _output_error;
/* We should succeed to decompress with the dictionary. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictSize) );
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
/* The dictionary should presist across calls. */
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
/* When we reset the context the dictionary is cleared. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
if (!ZSTD_isError(ret)) goto _output_error;
ZSTD_freeDCtx(dctx);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with ddict : ", testNb++);
{
ZSTD_DCtx* dctx = ZSTD_createDCtx();
ZSTD_DDict* ddict = ZSTD_createDDict(dictBuffer, dictSize);
size_t ret;
/* We should succeed to decompress with the ddict. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddict) );
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
/* The ddict should presist across calls. */
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
/* When we reset the context the ddict is cleared. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
if (!ZSTD_isError(ret)) goto _output_error;
ZSTD_freeDCtx(dctx);
ZSTD_freeDDict(ddict);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with prefix : ", testNb++);
{
ZSTD_DCtx* dctx = ZSTD_createDCtx();
size_t ret;
/* We should succeed to decompress with the prefix. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_DCtx_refPrefix_advanced(dctx, dictBuffer, dictSize, ZSTD_dct_auto) );
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );
/* The prefix should be cleared after the first compression. */
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
if (!ZSTD_isError(ret)) goto _output_error;
ZSTD_freeDCtx(dctx);
} }
DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "OK \n");
+43 -8
View File
@@ -16,10 +16,11 @@
/*=========================================== /*===========================================
* Dependencies * Dependencies
*==========================================*/ *==========================================*/
#include <stddef.h> /* size_t */ #include <stddef.h> /* size_t */
#include <stdlib.h> /* malloc, free */ #include <stdlib.h> /* malloc, free */
#include <stdio.h> /* fprintf */ #include <stdio.h> /* fprintf */
#include <string.h> /* strlen */ #include <string.h> /* strlen */
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_decompressBound */
#include "zstd.h" #include "zstd.h"
#include "zstd_errors.h" #include "zstd_errors.h"
@@ -74,6 +75,7 @@ static int testSimpleAPI(void)
static int testStreamingAPI(void) static int testStreamingAPI(void)
{ {
int error_code = 0;
size_t const outBuffSize = ZSTD_DStreamOutSize(); size_t const outBuffSize = ZSTD_DStreamOutSize();
char* const outBuff = malloc(outBuffSize); char* const outBuff = malloc(outBuffSize);
ZSTD_DStream* const stream = ZSTD_createDStream(); ZSTD_DStream* const stream = ZSTD_createDStream();
@@ -87,6 +89,7 @@ static int testStreamingAPI(void)
} }
if (stream == NULL) { if (stream == NULL) {
DISPLAY("ERROR: Could not create dstream\n"); DISPLAY("ERROR: Could not create dstream\n");
free(outBuff);
return 1; return 1;
} }
@@ -96,13 +99,15 @@ static int testStreamingAPI(void)
size_t const ret = ZSTD_initDStream(stream); size_t const ret = ZSTD_initDStream(stream);
if (ZSTD_isError(ret)) { if (ZSTD_isError(ret)) {
DISPLAY("ERROR: ZSTD_initDStream: %s\n", ZSTD_getErrorName(ret)); DISPLAY("ERROR: ZSTD_initDStream: %s\n", ZSTD_getErrorName(ret));
return 1; error_code = 1;
break;
} } } }
{ size_t const ret = ZSTD_decompressStream(stream, &output, &input); { size_t const ret = ZSTD_decompressStream(stream, &output, &input);
if (ZSTD_isError(ret)) { if (ZSTD_isError(ret)) {
DISPLAY("ERROR: ZSTD_decompressStream: %s\n", ZSTD_getErrorName(ret)); DISPLAY("ERROR: ZSTD_decompressStream: %s\n", ZSTD_getErrorName(ret));
return 1; error_code = 1;
break;
} }
if (ret == 0) { if (ret == 0) {
@@ -111,7 +116,8 @@ static int testStreamingAPI(void)
if (memcmp(outBuff, EXPECTED + outputPos, output.pos) != 0) { if (memcmp(outBuff, EXPECTED + outputPos, output.pos) != 0) {
DISPLAY("ERROR: Wrong decoded output produced\n"); DISPLAY("ERROR: Wrong decoded output produced\n");
return 1; error_code = 1;
break;
} }
outputPos += output.pos; outputPos += output.pos;
if (input.pos == input.size && output.pos < output.size) { if (input.pos == input.size && output.pos < output.size) {
@@ -121,7 +127,34 @@ static int testStreamingAPI(void)
free(outBuff); free(outBuff);
ZSTD_freeDStream(stream); ZSTD_freeDStream(stream);
DISPLAY("Streaming API OK\n"); if (error_code == 0) DISPLAY("Streaming API OK\n");
return error_code;
}
static int testFrameDecoding(void)
{
if (strlen(EXPECTED) > ZSTD_decompressBound(COMPRESSED, COMPRESSED_SIZE)) {
DISPLAY("ERROR: ZSTD_decompressBound: decompressed bound too small\n");
return 1;
}
{ const char* ip = COMPRESSED;
size_t remainingSize = COMPRESSED_SIZE;
while (1) {
size_t frameSize = ZSTD_findFrameCompressedSize(ip, remainingSize);
if (ZSTD_isError(frameSize)) {
DISPLAY("ERROR: ZSTD_findFrameCompressedSize: %s\n", ZSTD_getErrorName(frameSize));
return 1;
}
if (frameSize > remainingSize) {
DISPLAY("ERROR: ZSTD_findFrameCompressedSize: expected frameSize to align with src buffer");
return 1;
}
ip += frameSize;
remainingSize -= frameSize;
if (remainingSize == 0) break;
}
}
DISPLAY("Frame Decoding OK\n");
return 0; return 0;
} }
@@ -131,6 +164,8 @@ int main(void)
if (ret) return ret; } if (ret) return ret; }
{ int const ret = testStreamingAPI(); { int const ret = testStreamingAPI();
if (ret) return ret; } if (ret) return ret; }
{ int const ret = testFrameDecoding();
if (ret) return ret; }
DISPLAY("OK\n"); DISPLAY("OK\n");
return 0; return 0;
+32 -23
View File
@@ -19,6 +19,7 @@
#include <math.h> /* log */ #include <math.h> /* log */
#include <assert.h> #include <assert.h>
#include "timefn.h" /* SEC_TO_MICRO, UTIL_time_t, UTIL_clockSpanMicro, UTIL_clockSpanNano, UTIL_getTime */
#include "mem.h" #include "mem.h"
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters, ZSTD_estimateCCtxSize */ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters, ZSTD_estimateCCtxSize */
#include "zstd.h" #include "zstd.h"
@@ -141,7 +142,7 @@ static const char* g_shortParamNames[NUM_PARAMS] =
/* maps value from { 0 to rangetable[param] - 1 } to valid paramvalues */ /* maps value from { 0 to rangetable[param] - 1 } to valid paramvalues */
static U32 rangeMap(varInds_t param, int ind) static U32 rangeMap(varInds_t param, int ind)
{ {
ind = MAX(MIN(ind, (int)rangetable[param] - 1), 0); U32 const uind = (U32)MAX(MIN(ind, (int)rangetable[param] - 1), 0);
switch(param) { switch(param) {
case wlog_ind: /* using default: triggers -Wswitch-enum */ case wlog_ind: /* using default: triggers -Wswitch-enum */
case clog_ind: case clog_ind:
@@ -149,11 +150,11 @@ static U32 rangeMap(varInds_t param, int ind)
case slog_ind: case slog_ind:
case mml_ind: case mml_ind:
case strt_ind: case strt_ind:
return mintable[param] + ind; return mintable[param] + uind;
case tlen_ind: case tlen_ind:
return tlen_table[ind]; return tlen_table[uind];
case fadt_ind: /* 0, 1, 2 -> -1, 0, 1 */ case fadt_ind: /* 0, 1, 2 -> -1, 0, 1 */
return ind - 1; return uind - 1;
case NUM_PARAMS: case NUM_PARAMS:
default:; default:;
} }
@@ -173,7 +174,7 @@ static int invRangeMap(varInds_t param, U32 value)
case slog_ind: case slog_ind:
case mml_ind: case mml_ind:
case strt_ind: case strt_ind:
return value - mintable[param]; return (int)(value - mintable[param]);
case tlen_ind: /* bin search */ case tlen_ind: /* bin search */
{ {
int lo = 0; int lo = 0;
@@ -493,13 +494,15 @@ static void
paramVariation(paramValues_t* ptr, memoTable_t* mtAll, const U32 nbChanges) paramVariation(paramValues_t* ptr, memoTable_t* mtAll, const U32 nbChanges)
{ {
paramValues_t p; paramValues_t p;
U32 validated = 0; int validated = 0;
while (!validated) { while (!validated) {
U32 i; U32 i;
p = *ptr; p = *ptr;
for (i = 0 ; i < nbChanges ; i++) { for (i = 0 ; i < nbChanges ; i++) {
const U32 changeID = (U32)FUZ_rand(&g_rand) % (mtAll[p.vals[strt_ind]].varLen << 1); const U32 changeID = (U32)FUZ_rand(&g_rand) % (mtAll[p.vals[strt_ind]].varLen << 1);
paramVaryOnce(mtAll[p.vals[strt_ind]].varArray[changeID >> 1], ((changeID & 1) << 1) - 1, &p); paramVaryOnce(mtAll[p.vals[strt_ind]].varArray[changeID >> 1],
(int)((changeID & 1) << 1) - 1,
&p);
} }
validated = paramValid(p); validated = paramValid(p);
} }
@@ -511,7 +514,7 @@ static paramValues_t randomParams(void)
{ {
varInds_t v; paramValues_t p; varInds_t v; paramValues_t p;
for(v = 0; v < NUM_PARAMS; v++) { for(v = 0; v < NUM_PARAMS; v++) {
p.vals[v] = rangeMap(v, FUZ_rand(&g_rand) % rangetable[v]); p.vals[v] = rangeMap(v, (int)(FUZ_rand(&g_rand) % rangetable[v]));
} }
return p; return p;
} }
@@ -1232,7 +1235,7 @@ static int createBuffersFromMemory(buffers_t* buff, void * srcBuffer, const size
return 0; return 0;
} }
/* allocates buffer's arguments. returns success / failuere */ /* allocates buffer's arguments. returns success / failure */
static int createBuffers(buffers_t* buff, const char* const * const fileNamesTable, static int createBuffers(buffers_t* buff, const char* const * const fileNamesTable,
size_t nbFiles) { size_t nbFiles) {
size_t pos = 0; size_t pos = 0;
@@ -1505,7 +1508,7 @@ createMemoTableArray(const paramValues_t p,
} }
/* Sets pc to random unmeasured set of parameters */ /* Sets pc to random unmeasured set of parameters */
/* specifiy strategy */ /* specify strategy */
static void randomConstrainedParams(paramValues_t* pc, const memoTable_t* memoTableArray, const ZSTD_strategy st) static void randomConstrainedParams(paramValues_t* pc, const memoTable_t* memoTableArray, const ZSTD_strategy st)
{ {
size_t j; size_t j;
@@ -1570,7 +1573,7 @@ BMK_benchMemInvertible( buffers_t buf, contexts_t ctx,
display_params_tested(*comprParams); display_params_tested(*comprParams);
memset(&bResult, 0, sizeof(bResult)); memset(&bResult, 0, sizeof(bResult));
/* warmimg up memory */ /* warming up memory */
for (i = 0; i < buf.nbBlocks; i++) { for (i = 0; i < buf.nbBlocks; i++) {
if (mode != BMK_decodeOnly) { if (mode != BMK_decodeOnly) {
RDG_genBuffer(dstPtrs[i], dstCapacities[i], 0.10, 0.50, 1); RDG_genBuffer(dstPtrs[i], dstCapacities[i], 0.10, 0.50, 1);
@@ -1638,7 +1641,7 @@ BMK_benchMemInvertible( buffers_t buf, contexts_t ctx,
return bOut; return bOut;
} }
{ BMK_runTime_t const rResult = BMK_extract_runTime(cOutcome); { BMK_runTime_t const rResult = BMK_extract_runTime(cOutcome);
bResult.cSpeed = (srcSize * TIMELOOP_NANOSEC) / rResult.nanoSecPerRun; bResult.cSpeed = (unsigned long long)((double)srcSize * TIMELOOP_NANOSEC / rResult.nanoSecPerRun);
bResult.cSize = rResult.sumOfReturn; bResult.cSize = rResult.sumOfReturn;
} }
compressionCompleted = BMK_isCompleted_TimedFn(timeStateCompress); compressionCompleted = BMK_isCompleted_TimedFn(timeStateCompress);
@@ -1656,7 +1659,7 @@ BMK_benchMemInvertible( buffers_t buf, contexts_t ctx,
return bOut; return bOut;
} }
{ BMK_runTime_t const rResult = BMK_extract_runTime(dOutcome); { BMK_runTime_t const rResult = BMK_extract_runTime(dOutcome);
bResult.dSpeed = (srcSize * TIMELOOP_NANOSEC) / rResult.nanoSecPerRun; bResult.dSpeed = (unsigned long long)((double)srcSize * TIMELOOP_NANOSEC / rResult.nanoSecPerRun);
} }
decompressionCompleted = BMK_isCompleted_TimedFn(timeStateDecompress); decompressionCompleted = BMK_isCompleted_TimedFn(timeStateDecompress);
} }
@@ -1989,7 +1992,7 @@ BMK_selectRandomStart( FILE* f,
/* BMK_generate_cLevelTable() : /* BMK_generate_cLevelTable() :
* test a large number of configurations * test a large number of configurations
* and distribute them accross compression levels according to speed conditions. * and distribute them across compression levels according to speed conditions.
* display and save all intermediate results into rfName = "grillResults.txt". * display and save all intermediate results into rfName = "grillResults.txt".
* the function automatically stops after g_timeLimit_s. * the function automatically stops after g_timeLimit_s.
* this function cannot error, it directly exit() in case of problem. * this function cannot error, it directly exit() in case of problem.
@@ -2199,7 +2202,9 @@ static winnerInfo_t climbOnce(const constraint_t target,
for (offset = -1; offset <= 1; offset += 2) { for (offset = -1; offset <= 1; offset += 2) {
CHECKTIME(winnerInfo); CHECKTIME(winnerInfo);
candidateInfo.params = cparam; candidateInfo.params = cparam;
paramVaryOnce(mtAll[cparam.vals[strt_ind]].varArray[i], offset, &candidateInfo.params); paramVaryOnce(mtAll[cparam.vals[strt_ind]].varArray[i],
offset,
&candidateInfo.params);
if(paramValid(candidateInfo.params)) { if(paramValid(candidateInfo.params)) {
int res; int res;
@@ -2265,7 +2270,7 @@ static winnerInfo_t climbOnce(const constraint_t target,
/* Optimizes for a fixed strategy */ /* Optimizes for a fixed strategy */
/* flexible parameters: iterations of failed climbing (or if we do non-random, maybe this is when everything is close to visitied) /* flexible parameters: iterations of failed climbing (or if we do non-random, maybe this is when everything is close to visited)
weight more on visit for bad results, less on good results/more on later results / ones with more failures. weight more on visit for bad results, less on good results/more on later results / ones with more failures.
allocate memoTable here. allocate memoTable here.
*/ */
@@ -2351,7 +2356,7 @@ static int nextStrategy(const int currentStrategy, const int bestStrategy)
* cLevel - compression level to exceed (all solutions must be > lvl in cSpeed + ratio) * cLevel - compression level to exceed (all solutions must be > lvl in cSpeed + ratio)
*/ */
static int g_maxTries = 5; static unsigned g_maxTries = 5;
#define TRY_DECAY 1 #define TRY_DECAY 1
static int static int
@@ -2561,7 +2566,7 @@ _cleanUp:
* @return 0 and doesn't modify *stringPtr otherwise. * @return 0 and doesn't modify *stringPtr otherwise.
* from zstdcli.c * from zstdcli.c
*/ */
static unsigned longCommandWArg(const char** stringPtr, const char* longCommand) static int longCommandWArg(const char** stringPtr, const char* longCommand)
{ {
size_t const comSize = strlen(longCommand); size_t const comSize = strlen(longCommand);
int const result = !strncmp(*stringPtr, longCommand, comSize); int const result = !strncmp(*stringPtr, longCommand, comSize);
@@ -2588,7 +2593,10 @@ static unsigned readU32FromChar(const char** stringPtr)
while ((**stringPtr >='0') && (**stringPtr <='9')) { while ((**stringPtr >='0') && (**stringPtr <='9')) {
unsigned const max = (((unsigned)(-1)) / 10) - 1; unsigned const max = (((unsigned)(-1)) / 10) - 1;
if (result > max) errorOut(errorMsg); if (result > max) errorOut(errorMsg);
result *= 10, result += **stringPtr - '0', (*stringPtr)++ ; result *= 10;
assert(**stringPtr >= '0');
result += (unsigned)(**stringPtr - '0');
(*stringPtr)++ ;
} }
if ((**stringPtr=='K') || (**stringPtr=='M')) { if ((**stringPtr=='K') || (**stringPtr=='M')) {
unsigned const maxK = ((unsigned)(-1)) >> 10; unsigned const maxK = ((unsigned)(-1)) >> 10;
@@ -2726,7 +2734,7 @@ int main(int argc, const char** argv)
PARSE_SUB_ARGS("strict=", "stc=", g_strictness); PARSE_SUB_ARGS("strict=", "stc=", g_strictness);
PARSE_SUB_ARGS("maxTries=", "tries=", g_maxTries); PARSE_SUB_ARGS("maxTries=", "tries=", g_maxTries);
PARSE_SUB_ARGS("memoLimitLog=", "memLog=", memoTableLog); PARSE_SUB_ARGS("memoLimitLog=", "memLog=", memoTableLog);
if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevelOpt = readU32FromChar(&argument); g_optmode = 1; if (argument[0]==',') { argument++; continue; } else break; } if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevelOpt = (int)readU32FromChar(&argument); g_optmode = 1; if (argument[0]==',') { argument++; continue; } else break; }
if (longCommandWArg(&argument, "speedForRatio=") || longCommandWArg(&argument, "speedRatio=")) { g_ratioMultiplier = readDoubleFromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; } if (longCommandWArg(&argument, "speedForRatio=") || longCommandWArg(&argument, "speedRatio=")) { g_ratioMultiplier = readDoubleFromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }
DISPLAY("invalid optimization parameter \n"); DISPLAY("invalid optimization parameter \n");
@@ -2743,7 +2751,7 @@ int main(int argc, const char** argv)
g_singleRun = 1; g_singleRun = 1;
for ( ; ;) { for ( ; ;) {
if(parse_params(&argument, &g_params)) { if(argument[0] == ',') { argument++; continue; } else break; } if(parse_params(&argument, &g_params)) { if(argument[0] == ',') { argument++; continue; } else break; }
if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevelRun = readU32FromChar(&argument); g_params = emptyParams(); if (argument[0]==',') { argument++; continue; } else break; } if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevelRun = (int)readU32FromChar(&argument); g_params = emptyParams(); if (argument[0]==',') { argument++; continue; } else break; }
DISPLAY("invalid compression parameter \n"); DISPLAY("invalid compression parameter \n");
return 1; return 1;
@@ -2855,7 +2863,7 @@ int main(int argc, const char** argv)
continue; continue;
case 'L': case 'L':
{ argument++; { argument++;
cLevelRun = readU32FromChar(&argument); cLevelRun = (int)readU32FromChar(&argument);
g_params = emptyParams(); g_params = emptyParams();
continue; continue;
} }
@@ -2944,7 +2952,8 @@ int main(int argc, const char** argv)
} }
} else { } else {
if (g_optimizer) { if (g_optimizer) {
result = optimizeForSize(argv+filenamesStart, argc-filenamesStart, dictFileName, target, paramTarget, cLevelOpt, cLevelRun, memoTableLog); assert(filenamesStart < argc);
result = optimizeForSize(argv+filenamesStart, (size_t)(argc-filenamesStart), dictFileName, target, paramTarget, cLevelOpt, cLevelRun, memoTableLog);
} else { } else {
result = benchFiles(argv+filenamesStart, argc-filenamesStart, dictFileName, cLevelRun); result = benchFiles(argv+filenamesStart, argc-filenamesStart, dictFileName, cLevelRun);
} }
+38 -4
View File
@@ -49,7 +49,7 @@ fileRoundTripTest() {
} }
truncateLastByte() { truncateLastByte() {
dd bs=1 count=$(($(wc -c < "$1") - 1)) if="$1" status=none dd bs=1 count=$(($(wc -c < "$1") - 1)) if="$1"
} }
UNAME=$(uname) UNAME=$(uname)
@@ -200,6 +200,15 @@ $ZSTD tmp -fo tmp && die "zstd compression overwrote the input file"
$ZSTD tmp.zst -dfo tmp.zst && die "zstd decompression overwrote the input file" $ZSTD tmp.zst -dfo tmp.zst && die "zstd decompression overwrote the input file"
$ECHO "test: detect that input file does not exist" $ECHO "test: detect that input file does not exist"
$ZSTD nothere && die "zstd hasn't detected that input file does not exist" $ZSTD nothere && die "zstd hasn't detected that input file does not exist"
$ECHO "test: --[no-]compress-literals"
$ZSTD tmp -c --no-compress-literals -1 | $ZSTD -t
$ZSTD tmp -c --no-compress-literals --fast=1 | $ZSTD -t
$ZSTD tmp -c --no-compress-literals -19 | $ZSTD -t
$ZSTD tmp -c --compress-literals -1 | $ZSTD -t
$ZSTD tmp -c --compress-literals --fast=1 | $ZSTD -t
$ZSTD tmp -c --compress-literals -19 | $ZSTD -t
$ZSTD -b --fast=1 -i1e1 tmp --compress-literals
$ZSTD -b --fast=1 -i1e1 tmp --no-compress-literals
$ECHO "test : file removal" $ECHO "test : file removal"
$ZSTD -f --rm tmp $ZSTD -f --rm tmp
@@ -314,18 +323,28 @@ $ECHO foo | $ZSTD > /dev/full && die "write error not detected!"
$ECHO "$ECHO foo | $ZSTD | $ZSTD -d > /dev/full" $ECHO "$ECHO foo | $ZSTD | $ZSTD -d > /dev/full"
$ECHO foo | $ZSTD | $ZSTD -d > /dev/full && die "write error not detected!" $ECHO foo | $ZSTD | $ZSTD -d > /dev/full && die "write error not detected!"
fi
if [ "$isWindows" = false ] && [ "$UNAME" != 'SunOS' ] ; then
$ECHO "\n===> symbolic link test " $ECHO "\n===> symbolic link test "
rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst rm -f hello.tmp world.tmp world2.tmp hello.tmp.zst world.tmp.zst
$ECHO "hello world" > hello.tmp $ECHO "hello world" > hello.tmp
ln -s hello.tmp world.tmp ln -s hello.tmp world.tmp
$ZSTD world.tmp hello.tmp ln -s hello.tmp world2.tmp
$ZSTD world.tmp hello.tmp || true
test -f hello.tmp.zst # regular file should have been compressed! test -f hello.tmp.zst # regular file should have been compressed!
test ! -f world.tmp.zst # symbolic link should not have been compressed! test ! -f world.tmp.zst # symbolic link should not have been compressed!
$ZSTD world.tmp || true
test ! -f world.tmp.zst # symbolic link should not have been compressed!
$ZSTD world.tmp world2.tmp || true
test ! -f world.tmp.zst # symbolic link should not have been compressed!
test ! -f world2.tmp.zst # symbolic link should not have been compressed!
$ZSTD world.tmp hello.tmp -f $ZSTD world.tmp hello.tmp -f
test -f world.tmp.zst # symbolic link should have been compressed with --force test -f world.tmp.zst # symbolic link should have been compressed with --force
rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst rm -f hello.tmp world.tmp world2.tmp hello.tmp.zst world.tmp.zst
fi fi
@@ -391,6 +410,8 @@ $ECHO "- Create first dictionary "
TESTFILE=../programs/zstdcli.c TESTFILE=../programs/zstdcli.c
$ZSTD --train *.c ../programs/*.c -o tmpDict $ZSTD --train *.c ../programs/*.c -o tmpDict
cp $TESTFILE tmp cp $TESTFILE tmp
$ECHO "- Test dictionary compression with tmpDict as an input file and dictionary"
$ZSTD -f tmpDict -D tmpDict && die "compression error not detected!"
$ECHO "- Dictionary compression roundtrip" $ECHO "- Dictionary compression roundtrip"
$ZSTD -f tmp -D tmpDict $ZSTD -f tmp -D tmpDict
$ZSTD -d tmp.zst -D tmpDict -fo result $ZSTD -d tmp.zst -D tmpDict -fo result
@@ -809,6 +830,19 @@ $ZSTD --list tmp* && die "-l must fail on non-zstd file"
$ZSTD -lv tmp1* && die "-l must fail on non-zstd file" $ZSTD -lv tmp1* && die "-l must fail on non-zstd file"
$ZSTD --list -v tmp2 tmp12.zst && die "-l must fail on non-zstd file" $ZSTD --list -v tmp2 tmp12.zst && die "-l must fail on non-zstd file"
$ECHO "test : detect truncated compressed file "
TEST_DATA_FILE=truncatable-input.txt
FULL_COMPRESSED_FILE=${TEST_DATA_FILE}.zst
TRUNCATED_COMPRESSED_FILE=truncated-input.txt.zst
./datagen -g50000 > $TEST_DATA_FILE
$ZSTD -f $TEST_DATA_FILE -o $FULL_COMPRESSED_FILE
dd bs=1 count=100 if=$FULL_COMPRESSED_FILE of=$TRUNCATED_COMPRESSED_FILE
$ZSTD --list $TRUNCATED_COMPRESSED_FILE && die "-l must fail on truncated file"
rm $TEST_DATA_FILE
rm $FULL_COMPRESSED_FILE
rm $TRUNCATED_COMPRESSED_FILE
$ECHO "\n===> zstd --list/-l errors when presented with stdin / no files" $ECHO "\n===> zstd --list/-l errors when presented with stdin / no files"
$ZSTD -l && die "-l must fail on empty list of files" $ZSTD -l && die "-l must fail on empty list of files"
$ZSTD -l - && die "-l does not work on stdin" $ZSTD -l - && die "-l does not work on stdin"
+11 -8
View File
@@ -12,6 +12,7 @@
#include "pool.h" #include "pool.h"
#include "threading.h" #include "threading.h"
#include "util.h" #include "util.h"
#include "timefn.h"
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
@@ -25,25 +26,27 @@
#define ASSERT_EQ(lhs, rhs) ASSERT_TRUE((lhs) == (rhs)) #define ASSERT_EQ(lhs, rhs) ASSERT_TRUE((lhs) == (rhs))
struct data { struct data {
pthread_mutex_t mutex; ZSTD_pthread_mutex_t mutex;
unsigned data[16]; unsigned data[16];
size_t i; size_t i;
}; };
static void fn(void *opaque) { static void fn(void *opaque)
{
struct data *data = (struct data *)opaque; struct data *data = (struct data *)opaque;
ZSTD_pthread_mutex_lock(&data->mutex); ZSTD_pthread_mutex_lock(&data->mutex);
data->data[data->i] = data->i; data->data[data->i] = (unsigned)(data->i);
++data->i; ++data->i;
ZSTD_pthread_mutex_unlock(&data->mutex); ZSTD_pthread_mutex_unlock(&data->mutex);
} }
static int testOrder(size_t numThreads, size_t queueSize) { static int testOrder(size_t numThreads, size_t queueSize)
{
struct data data; struct data data;
POOL_ctx *ctx = POOL_create(numThreads, queueSize); POOL_ctx* const ctx = POOL_create(numThreads, queueSize);
ASSERT_TRUE(ctx); ASSERT_TRUE(ctx);
data.i = 0; data.i = 0;
ZSTD_pthread_mutex_init(&data.mutex, NULL); (void)ZSTD_pthread_mutex_init(&data.mutex, NULL);
{ size_t i; { size_t i;
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {
POOL_add(ctx, &fn, &data); POOL_add(ctx, &fn, &data);
@@ -71,7 +74,7 @@ static void waitFn(void *opaque) {
/* Tests for deadlock */ /* Tests for deadlock */
static int testWait(size_t numThreads, size_t queueSize) { static int testWait(size_t numThreads, size_t queueSize) {
struct data data; struct data data;
POOL_ctx *ctx = POOL_create(numThreads, queueSize); POOL_ctx* const ctx = POOL_create(numThreads, queueSize);
ASSERT_TRUE(ctx); ASSERT_TRUE(ctx);
{ size_t i; { size_t i;
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {
@@ -93,7 +96,7 @@ typedef struct {
} poolTest_t; } poolTest_t;
static void waitLongFn(void *opaque) { static void waitLongFn(void *opaque) {
poolTest_t* test = (poolTest_t*) opaque; poolTest_t* const test = (poolTest_t*) opaque;
UTIL_sleepMilli(10); UTIL_sleepMilli(10);
ZSTD_pthread_mutex_lock(&test->mut); ZSTD_pthread_mutex_lock(&test->mut);
test->val = test->val + 1; test->val = test->val + 1;
+48
View File
@@ -90,6 +90,17 @@ static config_t mt_ldm = {
.param_values = PARAM_VALUES(mt_ldm_param_values), .param_values = PARAM_VALUES(mt_ldm_param_values),
}; };
static param_value_t mt_advanced_param_values[] = {
{.param = ZSTD_c_nbWorkers, .value = 2},
{.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_uncompressed},
};
static config_t mt_advanced = {
.name = "multithreaded with advanced params",
.cli_args = "-T2 --no-compress-literals",
.param_values = PARAM_VALUES(mt_advanced_param_values),
};
static param_value_t const small_wlog_param_values[] = { static param_value_t const small_wlog_param_values[] = {
{.param = ZSTD_c_windowLog, .value = 10}, {.param = ZSTD_c_windowLog, .value = 10},
}; };
@@ -122,6 +133,39 @@ static config_t small_clog = {
.param_values = PARAM_VALUES(small_clog_param_values), .param_values = PARAM_VALUES(small_clog_param_values),
}; };
static param_value_t const uncompressed_literals_param_values[] = {
{.param = ZSTD_c_compressionLevel, .value = 3},
{.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_uncompressed},
};
static config_t uncompressed_literals = {
.name = "uncompressed literals",
.cli_args = "-3 --no-compress-literals",
.param_values = PARAM_VALUES(uncompressed_literals_param_values),
};
static param_value_t const uncompressed_literals_opt_param_values[] = {
{.param = ZSTD_c_compressionLevel, .value = 19},
{.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_uncompressed},
};
static config_t uncompressed_literals_opt = {
.name = "uncompressed literals optimal",
.cli_args = "-19 --no-compress-literals",
.param_values = PARAM_VALUES(uncompressed_literals_opt_param_values),
};
static param_value_t const huffman_literals_param_values[] = {
{.param = ZSTD_c_compressionLevel, .value = -1},
{.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_huffman},
};
static config_t huffman_literals = {
.name = "huffman literals",
.cli_args = "--fast=1 --compress-literals",
.param_values = PARAM_VALUES(huffman_literals_param_values),
};
static param_value_t const explicit_params_param_values[] = { static param_value_t const explicit_params_param_values[] = {
{.param = ZSTD_c_checksumFlag, .value = 1}, {.param = ZSTD_c_checksumFlag, .value = 1},
{.param = ZSTD_c_contentSizeFlag, .value = 0}, {.param = ZSTD_c_contentSizeFlag, .value = 0},
@@ -155,6 +199,10 @@ static config_t const* g_configs[] = {
&small_hlog, &small_hlog,
&small_clog, &small_clog,
&explicit_params, &explicit_params,
&uncompressed_literals,
&uncompressed_literals_opt,
&huffman_literals,
&mt_advanced,
NULL, NULL,
}; };
+163 -58
View File
@@ -175,8 +175,8 @@ static result_t compress_cctx_compress(
state->compressed.capacity, state->compressed.capacity,
input.data, input.data,
input.size, input.size,
state->dictionary.data, config->use_dictionary ? state->dictionary.data : NULL,
state->dictionary.size, config->use_dictionary ? state->dictionary.size : 0,
params); params);
else if (config->use_dictionary) else if (config->use_dictionary)
state->compressed.size = ZSTD_compress_usingDict( state->compressed.size = ZSTD_compress_usingDict(
@@ -432,77 +432,158 @@ out:
return result; return result;
} }
static result_t old_streaming_compress( static int init_cstream(
method_state_t* base, buffer_state_t* state,
config_t const* config) { ZSTD_CStream* zcs,
buffer_state_t* state = container_of(base, buffer_state_t, base); config_t const* config,
int const advanced,
if (buffer_state_bad(state, config)) ZSTD_CDict** cdict)
return result_error(result_error_system_error); {
int const level = config_get_level(config);
if (level == CONFIG_NO_LEVEL)
return result_error(result_error_skip);
ZSTD_CStream* zcs = ZSTD_createCStream();
result_t result;
if (zcs == NULL) {
result = result_error(result_error_compression_error);
goto out;
}
size_t zret; size_t zret;
if (config->use_dictionary) { if (advanced) {
zret = ZSTD_initCStream_usingDict( ZSTD_parameters const params = config_get_zstd_params(config, 0, 0);
zcs, state->dictionary.data, state->dictionary.size, level); ZSTD_CDict* dict = NULL;
if (cdict) {
*cdict = ZSTD_createCDict_advanced(
state->dictionary.data,
state->dictionary.size,
ZSTD_dlm_byRef,
ZSTD_dct_auto,
params.cParams,
ZSTD_defaultCMem);
if (!*cdict) {
return 1;
}
zret = ZSTD_initCStream_usingCDict_advanced(
zcs, *cdict, params.fParams, ZSTD_CONTENTSIZE_UNKNOWN);
} else {
zret = ZSTD_initCStream_advanced(
zcs,
state->dictionary.data,
state->dictionary.size,
params,
ZSTD_CONTENTSIZE_UNKNOWN);
}
} else { } else {
zret = ZSTD_initCStream(zcs, level); int const level = config_get_level(config);
if (cdict) {
*cdict = ZSTD_createCDict(
state->dictionary.data,
state->dictionary.size,
level);
if (!*cdict) {
return 1;
}
zret = ZSTD_initCStream_usingCDict(zcs, *cdict);
} else if (config->use_dictionary) {
zret = ZSTD_initCStream_usingDict(
zcs, state->dictionary.data, state->dictionary.size, level);
} else {
zret = ZSTD_initCStream(zcs, level);
}
} }
if (ZSTD_isError(zret)) { if (ZSTD_isError(zret)) {
result = result_error(result_error_compression_error); return 1;
goto out; }
return 0;
}
static result_t old_streaming_compress_internal(
method_state_t* base,
config_t const* config,
int const advanced,
int const cdict) {
buffer_state_t* state = container_of(base, buffer_state_t, base);
if (buffer_state_bad(state, config))
return result_error(result_error_system_error);
ZSTD_CStream* zcs = ZSTD_createCStream();
ZSTD_CDict* cd = NULL;
result_t result;
if (zcs == NULL) {
result = result_error(result_error_compression_error);
goto out;
}
if (init_cstream(state, zcs, config, advanced, cdict ? &cd : NULL)) {
result = result_error(result_error_compression_error);
goto out;
}
result_data_t data = {.total_size = 0};
for (size_t i = 0; i < state->inputs.size; ++i) {
data_buffer_t input = state->inputs.buffers[i];
size_t zret = ZSTD_resetCStream(
zcs,
config->no_pledged_src_size ? ZSTD_CONTENTSIZE_UNKNOWN : input.size);
if (ZSTD_isError(zret)) {
result = result_error(result_error_compression_error);
goto out;
} }
result_data_t data = {.total_size = 0}; while (input.size > 0) {
for (size_t i = 0; i < state->inputs.size; ++i) { ZSTD_inBuffer in = {input.data, MIN(input.size, 4096)};
data_buffer_t input = state->inputs.buffers[i]; input.data += in.size;
zret = ZSTD_resetCStream( input.size -= in.size;
zcs, ZSTD_EndDirective const op =
config->no_pledged_src_size ? ZSTD_CONTENTSIZE_UNKNOWN input.size > 0 ? ZSTD_e_continue : ZSTD_e_end;
: input.size); zret = 0;
while (in.pos < in.size || (op == ZSTD_e_end && zret != 0)) {
ZSTD_outBuffer out = {state->compressed.data,
MIN(state->compressed.capacity, 1024)};
if (op == ZSTD_e_continue || in.pos < in.size)
zret = ZSTD_compressStream(zcs, &out, &in);
else
zret = ZSTD_endStream(zcs, &out);
if (ZSTD_isError(zret)) { if (ZSTD_isError(zret)) {
result = result_error(result_error_compression_error); result = result_error(result_error_compression_error);
goto out; goto out;
}
while (input.size > 0) {
ZSTD_inBuffer in = {input.data, MIN(input.size, 4096)};
input.data += in.size;
input.size -= in.size;
ZSTD_EndDirective const op =
input.size > 0 ? ZSTD_e_continue : ZSTD_e_end;
zret = 0;
while (in.pos < in.size || (op == ZSTD_e_end && zret != 0)) {
ZSTD_outBuffer out = {state->compressed.data,
MIN(state->compressed.capacity, 1024)};
if (op == ZSTD_e_continue || in.pos < in.size)
zret = ZSTD_compressStream(zcs, &out, &in);
else
zret = ZSTD_endStream(zcs, &out);
if (ZSTD_isError(zret)) {
result = result_error(result_error_compression_error);
goto out;
}
data.total_size += out.pos;
}
} }
data.total_size += out.pos;
}
} }
}
result = result_data(data); result = result_data(data);
out: out:
ZSTD_freeCStream(zcs); ZSTD_freeCStream(zcs);
ZSTD_freeCDict(cd);
return result; return result;
} }
static result_t old_streaming_compress(
method_state_t* base,
config_t const* config)
{
return old_streaming_compress_internal(
base, config, /* advanced */ 0, /* cdict */ 0);
}
static result_t old_streaming_compress_advanced(
method_state_t* base,
config_t const* config)
{
return old_streaming_compress_internal(
base, config, /* advanced */ 1, /* cdict */ 0);
}
static result_t old_streaming_compress_cdict(
method_state_t* base,
config_t const* config)
{
return old_streaming_compress_internal(
base, config, /* advanced */ 0, /* cdict */ 1);
}
static result_t old_streaming_compress_cdict_advanced(
method_state_t* base,
config_t const* config)
{
return old_streaming_compress_internal(
base, config, /* advanced */ 1, /* cdict */ 1);
}
method_t const simple = { method_t const simple = {
.name = "compress simple", .name = "compress simple",
.create = buffer_state_create, .create = buffer_state_create,
@@ -545,6 +626,27 @@ method_t const old_streaming = {
.destroy = buffer_state_destroy, .destroy = buffer_state_destroy,
}; };
method_t const old_streaming_advanced = {
.name = "old streaming advanced",
.create = buffer_state_create,
.compress = old_streaming_compress,
.destroy = buffer_state_destroy,
};
method_t const old_streaming_cdict = {
.name = "old streaming cdcit",
.create = buffer_state_create,
.compress = old_streaming_compress,
.destroy = buffer_state_destroy,
};
method_t const old_streaming_advanced_cdict = {
.name = "old streaming advanced cdict",
.create = buffer_state_create,
.compress = old_streaming_compress,
.destroy = buffer_state_destroy,
};
method_t const cli = { method_t const cli = {
.name = "zstdcli", .name = "zstdcli",
.create = method_state_create, .create = method_state_create,
@@ -560,6 +662,9 @@ static method_t const* g_methods[] = {
&advanced_one_pass_small_out, &advanced_one_pass_small_out,
&advanced_streaming, &advanced_streaming,
&old_streaming, &old_streaming,
&old_streaming_advanced,
&old_streaming_cdict,
&old_streaming_advanced_cdict,
NULL, NULL,
}; };
+816 -448
View File
@@ -1,448 +1,816 @@
Data, Config, Method, Total compressed size Data, Config, Method, Total compressed size
silesia.tar, level -5, compress simple, 7160438 silesia.tar, level -5, compress simple, 6738558
silesia.tar, level -3, compress simple, 6789024 silesia.tar, level -3, compress simple, 6446362
silesia.tar, level -1, compress simple, 6195462 silesia.tar, level -1, compress simple, 6186038
silesia.tar, level 0, compress simple, 4875008 silesia.tar, level 0, compress simple, 4875008
silesia.tar, level 1, compress simple, 5339697 silesia.tar, level 1, compress simple, 5334825
silesia.tar, level 3, compress simple, 4875008 silesia.tar, level 3, compress simple, 4875008
silesia.tar, level 4, compress simple, 4813507 silesia.tar, level 4, compress simple, 4813507
silesia.tar, level 5, compress simple, 4722235 silesia.tar, level 5, compress simple, 4722235
silesia.tar, level 6, compress simple, 4672194 silesia.tar, level 6, compress simple, 4672194
silesia.tar, level 7, compress simple, 4606658 silesia.tar, level 7, compress simple, 4606658
silesia.tar, level 9, compress simple, 4554098 silesia.tar, level 9, compress simple, 4554098
silesia.tar, level 13, compress simple, 4491702 silesia.tar, level 13, compress simple, 4491702
silesia.tar, level 16, compress simple, 4381277 silesia.tar, level 16, compress simple, 4381277
silesia.tar, level 19, compress simple, 4281514 silesia.tar, level 19, compress simple, 4281514
silesia, level -5, compress cctx, 7152294 silesia.tar, uncompressed literals, compress simple, 4875008
silesia, level -3, compress cctx, 6789969 silesia.tar, uncompressed literals optimal, compress simple, 4281514
silesia, level -1, compress cctx, 6191548 silesia.tar, huffman literals, compress simple, 6186038
silesia, level 0, compress cctx, 4862377 silesia, level -5, compress cctx, 6737567
silesia, level 1, compress cctx, 5318036 silesia, level -3, compress cctx, 6444663
silesia, level 3, compress cctx, 4862377 silesia, level -1, compress cctx, 6178442
silesia, level 4, compress cctx, 4800629 silesia, level 0, compress cctx, 4862377
silesia, level 5, compress cctx, 4710178 silesia, level 1, compress cctx, 5313144
silesia, level 6, compress cctx, 4659996 silesia, level 3, compress cctx, 4862377
silesia, level 7, compress cctx, 4596234 silesia, level 4, compress cctx, 4800629
silesia, level 9, compress cctx, 4543862 silesia, level 5, compress cctx, 4710178
silesia, level 13, compress cctx, 4482073 silesia, level 6, compress cctx, 4659996
silesia, level 16, compress cctx, 4377391 silesia, level 7, compress cctx, 4596234
silesia, level 19, compress cctx, 4293262 silesia, level 9, compress cctx, 4543862
silesia, long distance mode, compress cctx, 4862377 silesia, level 13, compress cctx, 4482073
silesia, multithreaded, compress cctx, 4862377 silesia, level 16, compress cctx, 4377391
silesia, multithreaded long distance mode, compress cctx, 4862377 silesia, level 19, compress cctx, 4293262
silesia, small window log, compress cctx, 7115734 silesia, long distance mode, compress cctx, 4862377
silesia, small hash log, compress cctx, 6554898 silesia, multithreaded, compress cctx, 4862377
silesia, small chain log, compress cctx, 4931093 silesia, multithreaded long distance mode, compress cctx, 4862377
silesia, explicit params, compress cctx, 4813352 silesia, small window log, compress cctx, 7115734
github, level -5, compress cctx, 232744 silesia, small hash log, compress cctx, 6554898
github, level -5 with dict, compress cctx, 47294 silesia, small chain log, compress cctx, 4931093
github, level -3, compress cctx, 220611 silesia, explicit params, compress cctx, 4813352
github, level -3 with dict, compress cctx, 48047 silesia, uncompressed literals, compress cctx, 4862377
github, level -1, compress cctx, 176575 silesia, uncompressed literals optimal, compress cctx, 4293262
github, level -1 with dict, compress cctx, 43527 silesia, huffman literals, compress cctx, 6178442
github, level 0, compress cctx, 136397 silesia, multithreaded with advanced params, compress cctx, 4862377
github, level 0 with dict, compress cctx, 41536 github, level -5, compress cctx, 205285
github, level 1, compress cctx, 143457 github, level -5 with dict, compress cctx, 47294
github, level 1 with dict, compress cctx, 42157 github, level -3, compress cctx, 190643
github, level 3, compress cctx, 136397 github, level -3 with dict, compress cctx, 48047
github, level 3 with dict, compress cctx, 41536 github, level -1, compress cctx, 175568
github, level 4, compress cctx, 136144 github, level -1 with dict, compress cctx, 43527
github, level 4 with dict, compress cctx, 41721 github, level 0, compress cctx, 136397
github, level 5, compress cctx, 135106 github, level 0 with dict, compress cctx, 41536
github, level 5 with dict, compress cctx, 38934 github, level 1, compress cctx, 142450
github, level 6, compress cctx, 135108 github, level 1 with dict, compress cctx, 42157
github, level 6 with dict, compress cctx, 38628 github, level 3, compress cctx, 136397
github, level 7, compress cctx, 135108 github, level 3 with dict, compress cctx, 41536
github, level 7 with dict, compress cctx, 38741 github, level 4, compress cctx, 136144
github, level 9, compress cctx, 135108 github, level 4 with dict, compress cctx, 41721
github, level 9 with dict, compress cctx, 39335 github, level 5, compress cctx, 135106
github, level 13, compress cctx, 133717 github, level 5 with dict, compress cctx, 38934
github, level 13 with dict, compress cctx, 39923 github, level 6, compress cctx, 135108
github, level 16, compress cctx, 133717 github, level 6 with dict, compress cctx, 38628
github, level 16 with dict, compress cctx, 37568 github, level 7, compress cctx, 135108
github, level 19, compress cctx, 133717 github, level 7 with dict, compress cctx, 38741
github, level 19 with dict, compress cctx, 37567 github, level 9, compress cctx, 135108
github, long distance mode, compress cctx, decompression error github, level 9 with dict, compress cctx, 39335
github, multithreaded, compress cctx, decompression error github, level 13, compress cctx, 133717
github, multithreaded long distance mode, compress cctx, decompression error github, level 13 with dict, compress cctx, 39923
github, small window log, compress cctx, decompression error github, level 16, compress cctx, 133717
github, small hash log, compress cctx, decompression error github, level 16 with dict, compress cctx, 37568
github, small chain log, compress cctx, decompression error github, level 19, compress cctx, 133717
github, explicit params, compress cctx, decompression error github, level 19 with dict, compress cctx, 37567
silesia, level -5, zstdcli, 7152342 github, long distance mode, compress cctx, 141473
silesia, level -3, zstdcli, 6790021 github, multithreaded, compress cctx, 141473
silesia, level -1, zstdcli, 6191597 github, multithreaded long distance mode, compress cctx, 141473
silesia, level 0, zstdcli, 4862425 github, small window log, compress cctx, 141473
silesia, level 1, zstdcli, 5318084 github, small hash log, compress cctx, 138943
silesia, level 3, zstdcli, 4862425 github, small chain log, compress cctx, 139239
silesia, level 4, zstdcli, 4800677 github, explicit params, compress cctx, 140924
silesia, level 5, zstdcli, 4710226 github, uncompressed literals, compress cctx, 136397
silesia, level 6, zstdcli, 4660044 github, uncompressed literals optimal, compress cctx, 133717
silesia, level 7, zstdcli, 4596282 github, huffman literals, compress cctx, 175568
silesia, level 9, zstdcli, 4543910 github, multithreaded with advanced params, compress cctx, 141473
silesia, level 13, zstdcli, 4482121 silesia, level -5, zstdcli, 6882514
silesia, level 16, zstdcli, 4377439 silesia, level -3, zstdcli, 6568406
silesia, level 19, zstdcli, 4293310 silesia, level -1, zstdcli, 6183433
silesia, long distance mode, zstdcli, 4853437 silesia, level 0, zstdcli, 4862425
silesia, multithreaded, zstdcli, 4862425 silesia, level 1, zstdcli, 5314157
silesia, multithreaded long distance mode, zstdcli, 4853437 silesia, level 3, zstdcli, 4862425
silesia, small window log, zstdcli, 7126434 silesia, level 4, zstdcli, 4800677
silesia, small hash log, zstdcli, 6554946 silesia, level 5, zstdcli, 4710226
silesia, small chain log, zstdcli, 4931141 silesia, level 6, zstdcli, 4660044
silesia, explicit params, zstdcli, 4815380 silesia, level 7, zstdcli, 4596282
silesia.tar, level -5, zstdcli, 7161160 silesia, level 9, zstdcli, 4543910
silesia.tar, level -3, zstdcli, 6789865 silesia, level 13, zstdcli, 4482121
silesia.tar, level -1, zstdcli, 6196433 silesia, level 16, zstdcli, 4377439
silesia.tar, level 0, zstdcli, 4875136 silesia, level 19, zstdcli, 4293310
silesia.tar, level 1, zstdcli, 5340573 silesia, long distance mode, zstdcli, 4853437
silesia.tar, level 3, zstdcli, 4875136 silesia, multithreaded, zstdcli, 4862425
silesia.tar, level 4, zstdcli, 4814531 silesia, multithreaded long distance mode, zstdcli, 4853437
silesia.tar, level 5, zstdcli, 4723284 silesia, small window log, zstdcli, 7126434
silesia.tar, level 6, zstdcli, 4673591 silesia, small hash log, zstdcli, 6554946
silesia.tar, level 7, zstdcli, 4608342 silesia, small chain log, zstdcli, 4931141
silesia.tar, level 9, zstdcli, 4554700 silesia, explicit params, zstdcli, 4815380
silesia.tar, level 13, zstdcli, 4491706 silesia, uncompressed literals, zstdcli, 5155472
silesia.tar, level 16, zstdcli, 4381281 silesia, uncompressed literals optimal, zstdcli, 4325475
silesia.tar, level 19, zstdcli, 4281518 silesia, huffman literals, zstdcli, 5331158
silesia.tar, no source size, zstdcli, 4875132 silesia, multithreaded with advanced params, zstdcli, 5155472
silesia.tar, long distance mode, zstdcli, 4866975 silesia.tar, level -5, zstdcli, 6738906
silesia.tar, multithreaded, zstdcli, 4875136 silesia.tar, level -3, zstdcli, 6448409
silesia.tar, multithreaded long distance mode, zstdcli, 4866975 silesia.tar, level -1, zstdcli, 6186908
silesia.tar, small window log, zstdcli, 7130434 silesia.tar, level 0, zstdcli, 4875136
silesia.tar, small hash log, zstdcli, 6587841 silesia.tar, level 1, zstdcli, 5336255
silesia.tar, small chain log, zstdcli, 4943259 silesia.tar, level 3, zstdcli, 4875136
silesia.tar, explicit params, zstdcli, 4839202 silesia.tar, level 4, zstdcli, 4814531
github, level -5, zstdcli, 234744 silesia.tar, level 5, zstdcli, 4723284
github, level -5 with dict, zstdcli, 48718 silesia.tar, level 6, zstdcli, 4673591
github, level -3, zstdcli, 222611 silesia.tar, level 7, zstdcli, 4608342
github, level -3 with dict, zstdcli, 47395 silesia.tar, level 9, zstdcli, 4554700
github, level -1, zstdcli, 178575 silesia.tar, level 13, zstdcli, 4491706
github, level -1 with dict, zstdcli, 45170 silesia.tar, level 16, zstdcli, 4381281
github, level 0, zstdcli, 138397 silesia.tar, level 19, zstdcli, 4281518
github, level 0 with dict, zstdcli, 43170 silesia.tar, no source size, zstdcli, 4875132
github, level 1, zstdcli, 145457 silesia.tar, long distance mode, zstdcli, 4866975
github, level 1 with dict, zstdcli, 43682 silesia.tar, multithreaded, zstdcli, 4875136
github, level 3, zstdcli, 138397 silesia.tar, multithreaded long distance mode, zstdcli, 4866975
github, level 3 with dict, zstdcli, 43170 silesia.tar, small window log, zstdcli, 7130434
github, level 4, zstdcli, 138144 silesia.tar, small hash log, zstdcli, 6587841
github, level 4 with dict, zstdcli, 43306 silesia.tar, small chain log, zstdcli, 4943259
github, level 5, zstdcli, 137106 silesia.tar, explicit params, zstdcli, 4839202
github, level 5 with dict, zstdcli, 40938 silesia.tar, uncompressed literals, zstdcli, 5158134
github, level 6, zstdcli, 137108 silesia.tar, uncompressed literals optimal, zstdcli, 4321098
github, level 6 with dict, zstdcli, 40632 silesia.tar, huffman literals, zstdcli, 5347560
github, level 7, zstdcli, 137108 silesia.tar, multithreaded with advanced params, zstdcli, 5158134
github, level 7 with dict, zstdcli, 40766 github, level -5, zstdcli, 207285
github, level 9, zstdcli, 137108 github, level -5 with dict, zstdcli, 48718
github, level 9 with dict, zstdcli, 41326 github, level -3, zstdcli, 192643
github, level 13, zstdcli, 135717 github, level -3 with dict, zstdcli, 47395
github, level 13 with dict, zstdcli, 41716 github, level -1, zstdcli, 177568
github, level 16, zstdcli, 135717 github, level -1 with dict, zstdcli, 45170
github, level 16 with dict, zstdcli, 39577 github, level 0, zstdcli, 138397
github, level 19, zstdcli, 135717 github, level 0 with dict, zstdcli, 43170
github, level 19 with dict, zstdcli, 39576 github, level 1, zstdcli, 144450
github, long distance mode, zstdcli, 138397 github, level 1 with dict, zstdcli, 43682
github, multithreaded, zstdcli, 138397 github, level 3, zstdcli, 138397
github, multithreaded long distance mode, zstdcli, 138397 github, level 3 with dict, zstdcli, 43170
github, small window log, zstdcli, 138397 github, level 4, zstdcli, 138144
github, small hash log, zstdcli, 137467 github, level 4 with dict, zstdcli, 43306
github, small chain log, zstdcli, 138314 github, level 5, zstdcli, 137106
github, explicit params, zstdcli, 136140 github, level 5 with dict, zstdcli, 40938
silesia, level -5, advanced one pass, 7152294 github, level 6, zstdcli, 137108
silesia, level -3, advanced one pass, 6789969 github, level 6 with dict, zstdcli, 40632
silesia, level -1, advanced one pass, 6191548 github, level 7, zstdcli, 137108
silesia, level 0, advanced one pass, 4862377 github, level 7 with dict, zstdcli, 40766
silesia, level 1, advanced one pass, 5318036 github, level 9, zstdcli, 137108
silesia, level 3, advanced one pass, 4862377 github, level 9 with dict, zstdcli, 41326
silesia, level 4, advanced one pass, 4800629 github, level 13, zstdcli, 135717
silesia, level 5, advanced one pass, 4710178 github, level 13 with dict, zstdcli, 41716
silesia, level 6, advanced one pass, 4659996 github, level 16, zstdcli, 135717
silesia, level 7, advanced one pass, 4596234 github, level 16 with dict, zstdcli, 39577
silesia, level 9, advanced one pass, 4543862 github, level 19, zstdcli, 135717
silesia, level 13, advanced one pass, 4482073 github, level 19 with dict, zstdcli, 39576
silesia, level 16, advanced one pass, 4377391 github, long distance mode, zstdcli, 138397
silesia, level 19, advanced one pass, 4293262 github, multithreaded, zstdcli, 138397
silesia, no source size, advanced one pass, 4862377 github, multithreaded long distance mode, zstdcli, 138397
silesia, long distance mode, advanced one pass, 4853389 github, small window log, zstdcli, 138397
silesia, multithreaded, advanced one pass, 4862377 github, small hash log, zstdcli, 137467
silesia, multithreaded long distance mode, advanced one pass, 4853389 github, small chain log, zstdcli, 138314
silesia, small window log, advanced one pass, 7126386 github, explicit params, zstdcli, 136140
silesia, small hash log, advanced one pass, 6554898 github, uncompressed literals, zstdcli, 169004
silesia, small chain log, advanced one pass, 4931093 github, uncompressed literals optimal, zstdcli, 158824
silesia, explicit params, advanced one pass, 4815369 github, huffman literals, zstdcli, 144450
silesia.tar, level -5, advanced one pass, 7160438 github, multithreaded with advanced params, zstdcli, 169004
silesia.tar, level -3, advanced one pass, 6789024 silesia, level -5, advanced one pass, 6737567
silesia.tar, level -1, advanced one pass, 6195462 silesia, level -3, advanced one pass, 6444663
silesia.tar, level 0, advanced one pass, 4875008 silesia, level -1, advanced one pass, 6178442
silesia.tar, level 1, advanced one pass, 5339697 silesia, level 0, advanced one pass, 4862377
silesia.tar, level 3, advanced one pass, 4875008 silesia, level 1, advanced one pass, 5313144
silesia.tar, level 4, advanced one pass, 4813507 silesia, level 3, advanced one pass, 4862377
silesia.tar, level 5, advanced one pass, 4722235 silesia, level 4, advanced one pass, 4800629
silesia.tar, level 6, advanced one pass, 4672194 silesia, level 5, advanced one pass, 4710178
silesia.tar, level 7, advanced one pass, 4606658 silesia, level 6, advanced one pass, 4659996
silesia.tar, level 9, advanced one pass, 4554098 silesia, level 7, advanced one pass, 4596234
silesia.tar, level 13, advanced one pass, 4491702 silesia, level 9, advanced one pass, 4543862
silesia.tar, level 16, advanced one pass, 4381277 silesia, level 13, advanced one pass, 4482073
silesia.tar, level 19, advanced one pass, 4281514 silesia, level 16, advanced one pass, 4377391
silesia.tar, no source size, advanced one pass, 4875008 silesia, level 19, advanced one pass, 4293262
silesia.tar, long distance mode, advanced one pass, 4861218 silesia, no source size, advanced one pass, 4862377
silesia.tar, multithreaded, advanced one pass, 4874631 silesia, long distance mode, advanced one pass, 4853389
silesia.tar, multithreaded long distance mode, advanced one pass, 4860683 silesia, multithreaded, advanced one pass, 4862377
silesia.tar, small window log, advanced one pass, 7130394 silesia, multithreaded long distance mode, advanced one pass, 4853389
silesia.tar, small hash log, advanced one pass, 6587833 silesia, small window log, advanced one pass, 7126386
silesia.tar, small chain log, advanced one pass, 4943255 silesia, small hash log, advanced one pass, 6554898
silesia.tar, explicit params, advanced one pass, 4829974 silesia, small chain log, advanced one pass, 4931093
github, level -5, advanced one pass, 232744 silesia, explicit params, advanced one pass, 4815369
github, level -5 with dict, advanced one pass, 46718 silesia, uncompressed literals, advanced one pass, 5155424
github, level -3, advanced one pass, 220611 silesia, uncompressed literals optimal, advanced one pass, 4325427
github, level -3 with dict, advanced one pass, 45395 silesia, huffman literals, advanced one pass, 5326210
github, level -1, advanced one pass, 176575 silesia, multithreaded with advanced params, advanced one pass, 5155424
github, level -1 with dict, advanced one pass, 43170 silesia.tar, level -5, advanced one pass, 6738558
github, level 0, advanced one pass, 136397 silesia.tar, level -3, advanced one pass, 6446362
github, level 0 with dict, advanced one pass, 41170 silesia.tar, level -1, advanced one pass, 6186038
github, level 1, advanced one pass, 143457 silesia.tar, level 0, advanced one pass, 4875008
github, level 1 with dict, advanced one pass, 41682 silesia.tar, level 1, advanced one pass, 5334825
github, level 3, advanced one pass, 136397 silesia.tar, level 3, advanced one pass, 4875008
github, level 3 with dict, advanced one pass, 41170 silesia.tar, level 4, advanced one pass, 4813507
github, level 4, advanced one pass, 136144 silesia.tar, level 5, advanced one pass, 4722235
github, level 4 with dict, advanced one pass, 41306 silesia.tar, level 6, advanced one pass, 4672194
github, level 5, advanced one pass, 135106 silesia.tar, level 7, advanced one pass, 4606658
github, level 5 with dict, advanced one pass, 38938 silesia.tar, level 9, advanced one pass, 4554098
github, level 6, advanced one pass, 135108 silesia.tar, level 13, advanced one pass, 4491702
github, level 6 with dict, advanced one pass, 38632 silesia.tar, level 16, advanced one pass, 4381277
github, level 7, advanced one pass, 135108 silesia.tar, level 19, advanced one pass, 4281514
github, level 7 with dict, advanced one pass, 38766 silesia.tar, no source size, advanced one pass, 4875008
github, level 9, advanced one pass, 135108 silesia.tar, long distance mode, advanced one pass, 4861218
github, level 9 with dict, advanced one pass, 39326 silesia.tar, multithreaded, advanced one pass, 4874631
github, level 13, advanced one pass, 133717 silesia.tar, multithreaded long distance mode, advanced one pass, 4860683
github, level 13 with dict, advanced one pass, 39716 silesia.tar, small window log, advanced one pass, 7130394
github, level 16, advanced one pass, 133717 silesia.tar, small hash log, advanced one pass, 6587833
github, level 16 with dict, advanced one pass, 37577 silesia.tar, small chain log, advanced one pass, 4943255
github, level 19, advanced one pass, 133717 silesia.tar, explicit params, advanced one pass, 4829974
github, level 19 with dict, advanced one pass, 37576 silesia.tar, uncompressed literals, advanced one pass, 5157992
github, no source size, advanced one pass, 136397 silesia.tar, uncompressed literals optimal, advanced one pass, 4321094
github, long distance mode, advanced one pass, 136397 silesia.tar, huffman literals, advanced one pass, 5347283
github, multithreaded, advanced one pass, 136397 silesia.tar, multithreaded with advanced params, advanced one pass, 5158545
github, multithreaded long distance mode, advanced one pass, 136397 github, level -5, advanced one pass, 205285
github, small window log, advanced one pass, 136397 github, level -5 with dict, advanced one pass, 46718
github, small hash log, advanced one pass, 135467 github, level -3, advanced one pass, 190643
github, small chain log, advanced one pass, 136314 github, level -3 with dict, advanced one pass, 45395
github, explicit params, advanced one pass, 137670 github, level -1, advanced one pass, 175568
silesia, level -5, advanced one pass small out, 7152294 github, level -1 with dict, advanced one pass, 43170
silesia, level -3, advanced one pass small out, 6789969 github, level 0, advanced one pass, 136397
silesia, level -1, advanced one pass small out, 6191548 github, level 0 with dict, advanced one pass, 41170
silesia, level 0, advanced one pass small out, 4862377 github, level 1, advanced one pass, 142450
silesia, level 1, advanced one pass small out, 5318036 github, level 1 with dict, advanced one pass, 41682
silesia, level 3, advanced one pass small out, 4862377 github, level 3, advanced one pass, 136397
silesia, level 4, advanced one pass small out, 4800629 github, level 3 with dict, advanced one pass, 41170
silesia, level 5, advanced one pass small out, 4710178 github, level 4, advanced one pass, 136144
silesia, level 6, advanced one pass small out, 4659996 github, level 4 with dict, advanced one pass, 41306
silesia, level 7, advanced one pass small out, 4596234 github, level 5, advanced one pass, 135106
silesia, level 9, advanced one pass small out, 4543862 github, level 5 with dict, advanced one pass, 38938
silesia, level 13, advanced one pass small out, 4482073 github, level 6, advanced one pass, 135108
silesia, level 16, advanced one pass small out, 4377391 github, level 6 with dict, advanced one pass, 38632
silesia, level 19, advanced one pass small out, 4293262 github, level 7, advanced one pass, 135108
silesia, no source size, advanced one pass small out, 4862377 github, level 7 with dict, advanced one pass, 38766
silesia, long distance mode, advanced one pass small out, 4853389 github, level 9, advanced one pass, 135108
silesia, multithreaded, advanced one pass small out, 4862377 github, level 9 with dict, advanced one pass, 39326
silesia, multithreaded long distance mode, advanced one pass small out, 4853389 github, level 13, advanced one pass, 133717
silesia, small window log, advanced one pass small out, 7126386 github, level 13 with dict, advanced one pass, 39716
silesia, small hash log, advanced one pass small out, 6554898 github, level 16, advanced one pass, 133717
silesia, small chain log, advanced one pass small out, 4931093 github, level 16 with dict, advanced one pass, 37577
silesia, explicit params, advanced one pass small out, 4815369 github, level 19, advanced one pass, 133717
silesia.tar, level -5, advanced one pass small out, 7160438 github, level 19 with dict, advanced one pass, 37576
silesia.tar, level -3, advanced one pass small out, 6789024 github, no source size, advanced one pass, 136397
silesia.tar, level -1, advanced one pass small out, 6195462 github, long distance mode, advanced one pass, 136397
silesia.tar, level 0, advanced one pass small out, 4875008 github, multithreaded, advanced one pass, 136397
silesia.tar, level 1, advanced one pass small out, 5339697 github, multithreaded long distance mode, advanced one pass, 136397
silesia.tar, level 3, advanced one pass small out, 4875008 github, small window log, advanced one pass, 136397
silesia.tar, level 4, advanced one pass small out, 4813507 github, small hash log, advanced one pass, 135467
silesia.tar, level 5, advanced one pass small out, 4722235 github, small chain log, advanced one pass, 136314
silesia.tar, level 6, advanced one pass small out, 4672194 github, explicit params, advanced one pass, 137670
silesia.tar, level 7, advanced one pass small out, 4606658 github, uncompressed literals, advanced one pass, 167004
silesia.tar, level 9, advanced one pass small out, 4554098 github, uncompressed literals optimal, advanced one pass, 156824
silesia.tar, level 13, advanced one pass small out, 4491702 github, huffman literals, advanced one pass, 142450
silesia.tar, level 16, advanced one pass small out, 4381277 github, multithreaded with advanced params, advanced one pass, 167004
silesia.tar, level 19, advanced one pass small out, 4281514 silesia, level -5, advanced one pass small out, 6737567
silesia.tar, no source size, advanced one pass small out, 4875008 silesia, level -3, advanced one pass small out, 6444663
silesia.tar, long distance mode, advanced one pass small out, 4861218 silesia, level -1, advanced one pass small out, 6178442
silesia.tar, multithreaded, advanced one pass small out, 4874631 silesia, level 0, advanced one pass small out, 4862377
silesia.tar, multithreaded long distance mode, advanced one pass small out, 4860683 silesia, level 1, advanced one pass small out, 5313144
silesia.tar, small window log, advanced one pass small out, 7130394 silesia, level 3, advanced one pass small out, 4862377
silesia.tar, small hash log, advanced one pass small out, 6587833 silesia, level 4, advanced one pass small out, 4800629
silesia.tar, small chain log, advanced one pass small out, 4943255 silesia, level 5, advanced one pass small out, 4710178
silesia.tar, explicit params, advanced one pass small out, 4829974 silesia, level 6, advanced one pass small out, 4659996
github, level -5, advanced one pass small out, 232744 silesia, level 7, advanced one pass small out, 4596234
github, level -5 with dict, advanced one pass small out, 46718 silesia, level 9, advanced one pass small out, 4543862
github, level -3, advanced one pass small out, 220611 silesia, level 13, advanced one pass small out, 4482073
github, level -3 with dict, advanced one pass small out, 45395 silesia, level 16, advanced one pass small out, 4377391
github, level -1, advanced one pass small out, 176575 silesia, level 19, advanced one pass small out, 4293262
github, level -1 with dict, advanced one pass small out, 43170 silesia, no source size, advanced one pass small out, 4862377
github, level 0, advanced one pass small out, 136397 silesia, long distance mode, advanced one pass small out, 4853389
github, level 0 with dict, advanced one pass small out, 41170 silesia, multithreaded, advanced one pass small out, 4862377
github, level 1, advanced one pass small out, 143457 silesia, multithreaded long distance mode, advanced one pass small out, 4853389
github, level 1 with dict, advanced one pass small out, 41682 silesia, small window log, advanced one pass small out, 7126386
github, level 3, advanced one pass small out, 136397 silesia, small hash log, advanced one pass small out, 6554898
github, level 3 with dict, advanced one pass small out, 41170 silesia, small chain log, advanced one pass small out, 4931093
github, level 4, advanced one pass small out, 136144 silesia, explicit params, advanced one pass small out, 4815369
github, level 4 with dict, advanced one pass small out, 41306 silesia, uncompressed literals, advanced one pass small out, 5155424
github, level 5, advanced one pass small out, 135106 silesia, uncompressed literals optimal, advanced one pass small out, 4325427
github, level 5 with dict, advanced one pass small out, 38938 silesia, huffman literals, advanced one pass small out, 5326210
github, level 6, advanced one pass small out, 135108 silesia, multithreaded with advanced params, advanced one pass small out, 5155424
github, level 6 with dict, advanced one pass small out, 38632 silesia.tar, level -5, advanced one pass small out, 6738558
github, level 7, advanced one pass small out, 135108 silesia.tar, level -3, advanced one pass small out, 6446362
github, level 7 with dict, advanced one pass small out, 38766 silesia.tar, level -1, advanced one pass small out, 6186038
github, level 9, advanced one pass small out, 135108 silesia.tar, level 0, advanced one pass small out, 4875008
github, level 9 with dict, advanced one pass small out, 39326 silesia.tar, level 1, advanced one pass small out, 5334825
github, level 13, advanced one pass small out, 133717 silesia.tar, level 3, advanced one pass small out, 4875008
github, level 13 with dict, advanced one pass small out, 39716 silesia.tar, level 4, advanced one pass small out, 4813507
github, level 16, advanced one pass small out, 133717 silesia.tar, level 5, advanced one pass small out, 4722235
github, level 16 with dict, advanced one pass small out, 37577 silesia.tar, level 6, advanced one pass small out, 4672194
github, level 19, advanced one pass small out, 133717 silesia.tar, level 7, advanced one pass small out, 4606658
github, level 19 with dict, advanced one pass small out, 37576 silesia.tar, level 9, advanced one pass small out, 4554098
github, no source size, advanced one pass small out, 136397 silesia.tar, level 13, advanced one pass small out, 4491702
github, long distance mode, advanced one pass small out, 136397 silesia.tar, level 16, advanced one pass small out, 4381277
github, multithreaded, advanced one pass small out, 136397 silesia.tar, level 19, advanced one pass small out, 4281514
github, multithreaded long distance mode, advanced one pass small out, 136397 silesia.tar, no source size, advanced one pass small out, 4875008
github, small window log, advanced one pass small out, 136397 silesia.tar, long distance mode, advanced one pass small out, 4861218
github, small hash log, advanced one pass small out, 135467 silesia.tar, multithreaded, advanced one pass small out, 4874631
github, small chain log, advanced one pass small out, 136314 silesia.tar, multithreaded long distance mode, advanced one pass small out, 4860683
github, explicit params, advanced one pass small out, 137670 silesia.tar, small window log, advanced one pass small out, 7130394
silesia, level -5, advanced streaming, 7152294 silesia.tar, small hash log, advanced one pass small out, 6587833
silesia, level -3, advanced streaming, 6789973 silesia.tar, small chain log, advanced one pass small out, 4943255
silesia, level -1, advanced streaming, 6191549 silesia.tar, explicit params, advanced one pass small out, 4829974
silesia, level 0, advanced streaming, 4862377 silesia.tar, uncompressed literals, advanced one pass small out, 5157992
silesia, level 1, advanced streaming, 5318036 silesia.tar, uncompressed literals optimal, advanced one pass small out, 4321094
silesia, level 3, advanced streaming, 4862377 silesia.tar, huffman literals, advanced one pass small out, 5347283
silesia, level 4, advanced streaming, 4800629 silesia.tar, multithreaded with advanced params, advanced one pass small out, 5158545
silesia, level 5, advanced streaming, 4710178 github, level -5, advanced one pass small out, 205285
silesia, level 6, advanced streaming, 4659996 github, level -5 with dict, advanced one pass small out, 46718
silesia, level 7, advanced streaming, 4596234 github, level -3, advanced one pass small out, 190643
silesia, level 9, advanced streaming, 4543862 github, level -3 with dict, advanced one pass small out, 45395
silesia, level 13, advanced streaming, 4482073 github, level -1, advanced one pass small out, 175568
silesia, level 16, advanced streaming, 4377391 github, level -1 with dict, advanced one pass small out, 43170
silesia, level 19, advanced streaming, 4293262 github, level 0, advanced one pass small out, 136397
silesia, no source size, advanced streaming, 4862341 github, level 0 with dict, advanced one pass small out, 41170
silesia, long distance mode, advanced streaming, 4853389 github, level 1, advanced one pass small out, 142450
silesia, multithreaded, advanced streaming, 4862377 github, level 1 with dict, advanced one pass small out, 41682
silesia, multithreaded long distance mode, advanced streaming, 4853389 github, level 3, advanced one pass small out, 136397
silesia, small window log, advanced streaming, 7126389 github, level 3 with dict, advanced one pass small out, 41170
silesia, small hash log, advanced streaming, 6554898 github, level 4, advanced one pass small out, 136144
silesia, small chain log, advanced streaming, 4931093 github, level 4 with dict, advanced one pass small out, 41306
silesia, explicit params, advanced streaming, 4815380 github, level 5, advanced one pass small out, 135106
silesia.tar, level -5, advanced streaming, 7160440 github, level 5 with dict, advanced one pass small out, 38938
silesia.tar, level -3, advanced streaming, 6789026 github, level 6, advanced one pass small out, 135108
silesia.tar, level -1, advanced streaming, 6195465 github, level 6 with dict, advanced one pass small out, 38632
silesia.tar, level 0, advanced streaming, 4875010 github, level 7, advanced one pass small out, 135108
silesia.tar, level 1, advanced streaming, 5339701 github, level 7 with dict, advanced one pass small out, 38766
silesia.tar, level 3, advanced streaming, 4875010 github, level 9, advanced one pass small out, 135108
silesia.tar, level 4, advanced streaming, 4813507 github, level 9 with dict, advanced one pass small out, 39326
silesia.tar, level 5, advanced streaming, 4722240 github, level 13, advanced one pass small out, 133717
silesia.tar, level 6, advanced streaming, 4672203 github, level 13 with dict, advanced one pass small out, 39716
silesia.tar, level 7, advanced streaming, 4606658 github, level 16, advanced one pass small out, 133717
silesia.tar, level 9, advanced streaming, 4554105 github, level 16 with dict, advanced one pass small out, 37577
silesia.tar, level 13, advanced streaming, 4491703 github, level 19, advanced one pass small out, 133717
silesia.tar, level 16, advanced streaming, 4381277 github, level 19 with dict, advanced one pass small out, 37576
silesia.tar, level 19, advanced streaming, 4281514 github, no source size, advanced one pass small out, 136397
silesia.tar, no source size, advanced streaming, 4875006 github, long distance mode, advanced one pass small out, 136397
silesia.tar, long distance mode, advanced streaming, 4861218 github, multithreaded, advanced one pass small out, 136397
silesia.tar, multithreaded, advanced streaming, 4875132 github, multithreaded long distance mode, advanced one pass small out, 136397
silesia.tar, multithreaded long distance mode, advanced streaming, 4866971 github, small window log, advanced one pass small out, 136397
silesia.tar, small window log, advanced streaming, 7130394 github, small hash log, advanced one pass small out, 135467
silesia.tar, small hash log, advanced streaming, 6587834 github, small chain log, advanced one pass small out, 136314
silesia.tar, small chain log, advanced streaming, 4943260 github, explicit params, advanced one pass small out, 137670
silesia.tar, explicit params, advanced streaming, 4830002 github, uncompressed literals, advanced one pass small out, 167004
github, level -5, advanced streaming, 232744 github, uncompressed literals optimal, advanced one pass small out, 156824
github, level -5 with dict, advanced streaming, 46718 github, huffman literals, advanced one pass small out, 142450
github, level -3, advanced streaming, 220611 github, multithreaded with advanced params, advanced one pass small out, 167004
github, level -3 with dict, advanced streaming, 45395 silesia, level -5, advanced streaming, 6882466
github, level -1, advanced streaming, 176575 silesia, level -3, advanced streaming, 6568358
github, level -1 with dict, advanced streaming, 43170 silesia, level -1, advanced streaming, 6183385
github, level 0, advanced streaming, 136397 silesia, level 0, advanced streaming, 4862377
github, level 0 with dict, advanced streaming, 41170 silesia, level 1, advanced streaming, 5314109
github, level 1, advanced streaming, 143457 silesia, level 3, advanced streaming, 4862377
github, level 1 with dict, advanced streaming, 41682 silesia, level 4, advanced streaming, 4800629
github, level 3, advanced streaming, 136397 silesia, level 5, advanced streaming, 4710178
github, level 3 with dict, advanced streaming, 41170 silesia, level 6, advanced streaming, 4659996
github, level 4, advanced streaming, 136144 silesia, level 7, advanced streaming, 4596234
github, level 4 with dict, advanced streaming, 41306 silesia, level 9, advanced streaming, 4543862
github, level 5, advanced streaming, 135106 silesia, level 13, advanced streaming, 4482073
github, level 5 with dict, advanced streaming, 38938 silesia, level 16, advanced streaming, 4377391
github, level 6, advanced streaming, 135108 silesia, level 19, advanced streaming, 4293262
github, level 6 with dict, advanced streaming, 38632 silesia, no source size, advanced streaming, 4862341
github, level 7, advanced streaming, 135108 silesia, long distance mode, advanced streaming, 4853389
github, level 7 with dict, advanced streaming, 38766 silesia, multithreaded, advanced streaming, 4862377
github, level 9, advanced streaming, 135108 silesia, multithreaded long distance mode, advanced streaming, 4853389
github, level 9 with dict, advanced streaming, 39326 silesia, small window log, advanced streaming, 7126389
github, level 13, advanced streaming, 133717 silesia, small hash log, advanced streaming, 6554898
github, level 13 with dict, advanced streaming, 39716 silesia, small chain log, advanced streaming, 4931093
github, level 16, advanced streaming, 133717 silesia, explicit params, advanced streaming, 4815380
github, level 16 with dict, advanced streaming, 37577 silesia, uncompressed literals, advanced streaming, 5155424
github, level 19, advanced streaming, 133717 silesia, uncompressed literals optimal, advanced streaming, 4325427
github, level 19 with dict, advanced streaming, 37576 silesia, huffman literals, advanced streaming, 5331110
github, no source size, advanced streaming, 136397 silesia, multithreaded with advanced params, advanced streaming, 5155424
github, long distance mode, advanced streaming, 136397 silesia.tar, level -5, advanced streaming, 6982738
github, multithreaded, advanced streaming, 136397 silesia.tar, level -3, advanced streaming, 6641264
github, multithreaded long distance mode, advanced streaming, 136397 silesia.tar, level -1, advanced streaming, 6190789
github, small window log, advanced streaming, 136397 silesia.tar, level 0, advanced streaming, 4875010
github, small hash log, advanced streaming, 135467 silesia.tar, level 1, advanced streaming, 5336879
github, small chain log, advanced streaming, 136314 silesia.tar, level 3, advanced streaming, 4875010
github, explicit params, advanced streaming, 137670 silesia.tar, level 4, advanced streaming, 4813507
silesia, level -5, old streaming, 7152294 silesia.tar, level 5, advanced streaming, 4722240
silesia, level -3, old streaming, 6789973 silesia.tar, level 6, advanced streaming, 4672203
silesia, level -1, old streaming, 6191549 silesia.tar, level 7, advanced streaming, 4606658
silesia, level 0, old streaming, 4862377 silesia.tar, level 9, advanced streaming, 4554105
silesia, level 1, old streaming, 5318036 silesia.tar, level 13, advanced streaming, 4491703
silesia, level 3, old streaming, 4862377 silesia.tar, level 16, advanced streaming, 4381277
silesia, level 4, old streaming, 4800629 silesia.tar, level 19, advanced streaming, 4281514
silesia, level 5, old streaming, 4710178 silesia.tar, no source size, advanced streaming, 4875006
silesia, level 6, old streaming, 4659996 silesia.tar, long distance mode, advanced streaming, 4861218
silesia, level 7, old streaming, 4596234 silesia.tar, multithreaded, advanced streaming, 4875132
silesia, level 9, old streaming, 4543862 silesia.tar, multithreaded long distance mode, advanced streaming, 4866971
silesia, level 13, old streaming, 4482073 silesia.tar, small window log, advanced streaming, 7130394
silesia, level 16, old streaming, 4377391 silesia.tar, small hash log, advanced streaming, 6587834
silesia, level 19, old streaming, 4293262 silesia.tar, small chain log, advanced streaming, 4943260
silesia, no source size, old streaming, 4862341 silesia.tar, explicit params, advanced streaming, 4830002
silesia.tar, level -5, old streaming, 7160440 silesia.tar, uncompressed literals, advanced streaming, 5157995
silesia.tar, level -3, old streaming, 6789026 silesia.tar, uncompressed literals optimal, advanced streaming, 4321094
silesia.tar, level -1, old streaming, 6195465 silesia.tar, huffman literals, advanced streaming, 5352306
silesia.tar, level 0, old streaming, 4875010 silesia.tar, multithreaded with advanced params, advanced streaming, 5158130
silesia.tar, level 1, old streaming, 5339701 github, level -5, advanced streaming, 205285
silesia.tar, level 3, old streaming, 4875010 github, level -5 with dict, advanced streaming, 46718
silesia.tar, level 4, old streaming, 4813507 github, level -3, advanced streaming, 190643
silesia.tar, level 5, old streaming, 4722240 github, level -3 with dict, advanced streaming, 45395
silesia.tar, level 6, old streaming, 4672203 github, level -1, advanced streaming, 175568
silesia.tar, level 7, old streaming, 4606658 github, level -1 with dict, advanced streaming, 43170
silesia.tar, level 9, old streaming, 4554105 github, level 0, advanced streaming, 136397
silesia.tar, level 13, old streaming, 4491703 github, level 0 with dict, advanced streaming, 41170
silesia.tar, level 16, old streaming, 4381277 github, level 1, advanced streaming, 142450
silesia.tar, level 19, old streaming, 4281514 github, level 1 with dict, advanced streaming, 41682
silesia.tar, no source size, old streaming, 4875006 github, level 3, advanced streaming, 136397
github, level -5, old streaming, 232744 github, level 3 with dict, advanced streaming, 41170
github, level -5 with dict, old streaming, 46718 github, level 4, advanced streaming, 136144
github, level -3, old streaming, 220611 github, level 4 with dict, advanced streaming, 41306
github, level -3 with dict, old streaming, 45395 github, level 5, advanced streaming, 135106
github, level -1, old streaming, 176575 github, level 5 with dict, advanced streaming, 38938
github, level -1 with dict, old streaming, 43170 github, level 6, advanced streaming, 135108
github, level 0, old streaming, 136397 github, level 6 with dict, advanced streaming, 38632
github, level 0 with dict, old streaming, 41170 github, level 7, advanced streaming, 135108
github, level 1, old streaming, 143457 github, level 7 with dict, advanced streaming, 38766
github, level 1 with dict, old streaming, 41682 github, level 9, advanced streaming, 135108
github, level 3, old streaming, 136397 github, level 9 with dict, advanced streaming, 39326
github, level 3 with dict, old streaming, 41170 github, level 13, advanced streaming, 133717
github, level 4, old streaming, 136144 github, level 13 with dict, advanced streaming, 39716
github, level 4 with dict, old streaming, 41306 github, level 16, advanced streaming, 133717
github, level 5, old streaming, 135106 github, level 16 with dict, advanced streaming, 37577
github, level 5 with dict, old streaming, 38938 github, level 19, advanced streaming, 133717
github, level 6, old streaming, 135108 github, level 19 with dict, advanced streaming, 37576
github, level 6 with dict, old streaming, 38632 github, no source size, advanced streaming, 136397
github, level 7, old streaming, 135108 github, long distance mode, advanced streaming, 136397
github, level 7 with dict, old streaming, 38766 github, multithreaded, advanced streaming, 136397
github, level 9, old streaming, 135108 github, multithreaded long distance mode, advanced streaming, 136397
github, level 9 with dict, old streaming, 39326 github, small window log, advanced streaming, 136397
github, level 13, old streaming, 133717 github, small hash log, advanced streaming, 135467
github, level 13 with dict, old streaming, 39716 github, small chain log, advanced streaming, 136314
github, level 16, old streaming, 133717 github, explicit params, advanced streaming, 137670
github, level 16 with dict, old streaming, 37577 github, uncompressed literals, advanced streaming, 167004
github, level 19, old streaming, 133717 github, uncompressed literals optimal, advanced streaming, 156824
github, level 19 with dict, old streaming, 37576 github, huffman literals, advanced streaming, 142450
github, no source size, old streaming, 141003 github, multithreaded with advanced params, advanced streaming, 167004
silesia, level -5, old streaming, 6882466
silesia, level -3, old streaming, 6568358
silesia, level -1, old streaming, 6183385
silesia, level 0, old streaming, 4862377
silesia, level 1, old streaming, 5314109
silesia, level 3, old streaming, 4862377
silesia, level 4, old streaming, 4800629
silesia, level 5, old streaming, 4710178
silesia, level 6, old streaming, 4659996
silesia, level 7, old streaming, 4596234
silesia, level 9, old streaming, 4543862
silesia, level 13, old streaming, 4482073
silesia, level 16, old streaming, 4377391
silesia, level 19, old streaming, 4293262
silesia, no source size, old streaming, 4862341
silesia, long distance mode, old streaming, 12000408
silesia, multithreaded, old streaming, 12000408
silesia, multithreaded long distance mode, old streaming, 12000408
silesia, small window log, old streaming, 12000408
silesia, small hash log, old streaming, 12000408
silesia, small chain log, old streaming, 12000408
silesia, explicit params, old streaming, 12000408
silesia, uncompressed literals, old streaming, 4862377
silesia, uncompressed literals optimal, old streaming, 4293262
silesia, huffman literals, old streaming, 6183385
silesia, multithreaded with advanced params, old streaming, 12000408
silesia.tar, level -5, old streaming, 6982738
silesia.tar, level -3, old streaming, 6641264
silesia.tar, level -1, old streaming, 6190789
silesia.tar, level 0, old streaming, 4875010
silesia.tar, level 1, old streaming, 5336879
silesia.tar, level 3, old streaming, 4875010
silesia.tar, level 4, old streaming, 4813507
silesia.tar, level 5, old streaming, 4722240
silesia.tar, level 6, old streaming, 4672203
silesia.tar, level 7, old streaming, 4606658
silesia.tar, level 9, old streaming, 4554105
silesia.tar, level 13, old streaming, 4491703
silesia.tar, level 16, old streaming, 4381277
silesia.tar, level 19, old streaming, 4281514
silesia.tar, no source size, old streaming, 4875006
silesia.tar, long distance mode, old streaming, 12022046
silesia.tar, multithreaded, old streaming, 12022046
silesia.tar, multithreaded long distance mode, old streaming, 12022046
silesia.tar, small window log, old streaming, 12022046
silesia.tar, small hash log, old streaming, 12022046
silesia.tar, small chain log, old streaming, 12022046
silesia.tar, explicit params, old streaming, 12022046
silesia.tar, uncompressed literals, old streaming, 4875010
silesia.tar, uncompressed literals optimal, old streaming, 4281514
silesia.tar, huffman literals, old streaming, 6190789
silesia.tar, multithreaded with advanced params, old streaming, 12022046
github, level -5, old streaming, 205285
github, level -5 with dict, old streaming, 46718
github, level -3, old streaming, 190643
github, level -3 with dict, old streaming, 45395
github, level -1, old streaming, 175568
github, level -1 with dict, old streaming, 43170
github, level 0, old streaming, 136397
github, level 0 with dict, old streaming, 41170
github, level 1, old streaming, 142450
github, level 1 with dict, old streaming, 41682
github, level 3, old streaming, 136397
github, level 3 with dict, old streaming, 41170
github, level 4, old streaming, 136144
github, level 4 with dict, old streaming, 41306
github, level 5, old streaming, 135106
github, level 5 with dict, old streaming, 38938
github, level 6, old streaming, 135108
github, level 6 with dict, old streaming, 38632
github, level 7, old streaming, 135108
github, level 7 with dict, old streaming, 38766
github, level 9, old streaming, 135108
github, level 9 with dict, old streaming, 39326
github, level 13, old streaming, 133717
github, level 13 with dict, old streaming, 39716
github, level 16, old streaming, 133717
github, level 16 with dict, old streaming, 37577
github, level 19, old streaming, 133717
github, level 19 with dict, old streaming, 37576
github, no source size, old streaming, 141003
github, long distance mode, old streaming, 412933
github, multithreaded, old streaming, 412933
github, multithreaded long distance mode, old streaming, 412933
github, small window log, old streaming, 412933
github, small hash log, old streaming, 412933
github, small chain log, old streaming, 412933
github, explicit params, old streaming, 412933
github, uncompressed literals, old streaming, 136397
github, uncompressed literals optimal, old streaming, 133717
github, huffman literals, old streaming, 175568
github, multithreaded with advanced params, old streaming, 412933
silesia, level -5, old streaming advanced, 6882466
silesia, level -3, old streaming advanced, 6568358
silesia, level -1, old streaming advanced, 6183385
silesia, level 0, old streaming advanced, 4862377
silesia, level 1, old streaming advanced, 5314109
silesia, level 3, old streaming advanced, 4862377
silesia, level 4, old streaming advanced, 4800629
silesia, level 5, old streaming advanced, 4710178
silesia, level 6, old streaming advanced, 4659996
silesia, level 7, old streaming advanced, 4596234
silesia, level 9, old streaming advanced, 4543862
silesia, level 13, old streaming advanced, 4482073
silesia, level 16, old streaming advanced, 4377391
silesia, level 19, old streaming advanced, 4293262
silesia, no source size, old streaming advanced, 4862341
silesia, long distance mode, old streaming advanced, 12000408
silesia, multithreaded, old streaming advanced, 12000408
silesia, multithreaded long distance mode, old streaming advanced, 12000408
silesia, small window log, old streaming advanced, 12000408
silesia, small hash log, old streaming advanced, 12000408
silesia, small chain log, old streaming advanced, 12000408
silesia, explicit params, old streaming advanced, 12000408
silesia, uncompressed literals, old streaming advanced, 4862377
silesia, uncompressed literals optimal, old streaming advanced, 4293262
silesia, huffman literals, old streaming advanced, 6183385
silesia, multithreaded with advanced params, old streaming advanced, 12000408
silesia.tar, level -5, old streaming advanced, 6982738
silesia.tar, level -3, old streaming advanced, 6641264
silesia.tar, level -1, old streaming advanced, 6190789
silesia.tar, level 0, old streaming advanced, 4875010
silesia.tar, level 1, old streaming advanced, 5336879
silesia.tar, level 3, old streaming advanced, 4875010
silesia.tar, level 4, old streaming advanced, 4813507
silesia.tar, level 5, old streaming advanced, 4722240
silesia.tar, level 6, old streaming advanced, 4672203
silesia.tar, level 7, old streaming advanced, 4606658
silesia.tar, level 9, old streaming advanced, 4554105
silesia.tar, level 13, old streaming advanced, 4491703
silesia.tar, level 16, old streaming advanced, 4381277
silesia.tar, level 19, old streaming advanced, 4281514
silesia.tar, no source size, old streaming advanced, 4875006
silesia.tar, long distance mode, old streaming advanced, 12022046
silesia.tar, multithreaded, old streaming advanced, 12022046
silesia.tar, multithreaded long distance mode, old streaming advanced, 12022046
silesia.tar, small window log, old streaming advanced, 12022046
silesia.tar, small hash log, old streaming advanced, 12022046
silesia.tar, small chain log, old streaming advanced, 12022046
silesia.tar, explicit params, old streaming advanced, 12022046
silesia.tar, uncompressed literals, old streaming advanced, 4875010
silesia.tar, uncompressed literals optimal, old streaming advanced, 4281514
silesia.tar, huffman literals, old streaming advanced, 6190789
silesia.tar, multithreaded with advanced params, old streaming advanced, 12022046
github, level -5, old streaming advanced, 205285
github, level -5 with dict, old streaming advanced, 46718
github, level -3, old streaming advanced, 190643
github, level -3 with dict, old streaming advanced, 45395
github, level -1, old streaming advanced, 175568
github, level -1 with dict, old streaming advanced, 43170
github, level 0, old streaming advanced, 136397
github, level 0 with dict, old streaming advanced, 41170
github, level 1, old streaming advanced, 142450
github, level 1 with dict, old streaming advanced, 41682
github, level 3, old streaming advanced, 136397
github, level 3 with dict, old streaming advanced, 41170
github, level 4, old streaming advanced, 136144
github, level 4 with dict, old streaming advanced, 41306
github, level 5, old streaming advanced, 135106
github, level 5 with dict, old streaming advanced, 38938
github, level 6, old streaming advanced, 135108
github, level 6 with dict, old streaming advanced, 38632
github, level 7, old streaming advanced, 135108
github, level 7 with dict, old streaming advanced, 38766
github, level 9, old streaming advanced, 135108
github, level 9 with dict, old streaming advanced, 39326
github, level 13, old streaming advanced, 133717
github, level 13 with dict, old streaming advanced, 39716
github, level 16, old streaming advanced, 133717
github, level 16 with dict, old streaming advanced, 37577
github, level 19, old streaming advanced, 133717
github, level 19 with dict, old streaming advanced, 37576
github, no source size, old streaming advanced, 141003
github, long distance mode, old streaming advanced, 412933
github, multithreaded, old streaming advanced, 412933
github, multithreaded long distance mode, old streaming advanced, 412933
github, small window log, old streaming advanced, 412933
github, small hash log, old streaming advanced, 412933
github, small chain log, old streaming advanced, 412933
github, explicit params, old streaming advanced, 412933
github, uncompressed literals, old streaming advanced, 136397
github, uncompressed literals optimal, old streaming advanced, 133717
github, huffman literals, old streaming advanced, 175568
github, multithreaded with advanced params, old streaming advanced, 412933
silesia, level -5, old streaming cdcit, 6882466
silesia, level -3, old streaming cdcit, 6568358
silesia, level -1, old streaming cdcit, 6183385
silesia, level 0, old streaming cdcit, 4862377
silesia, level 1, old streaming cdcit, 5314109
silesia, level 3, old streaming cdcit, 4862377
silesia, level 4, old streaming cdcit, 4800629
silesia, level 5, old streaming cdcit, 4710178
silesia, level 6, old streaming cdcit, 4659996
silesia, level 7, old streaming cdcit, 4596234
silesia, level 9, old streaming cdcit, 4543862
silesia, level 13, old streaming cdcit, 4482073
silesia, level 16, old streaming cdcit, 4377391
silesia, level 19, old streaming cdcit, 4293262
silesia, no source size, old streaming cdcit, 4862341
silesia, long distance mode, old streaming cdcit, 12000408
silesia, multithreaded, old streaming cdcit, 12000408
silesia, multithreaded long distance mode, old streaming cdcit, 12000408
silesia, small window log, old streaming cdcit, 12000408
silesia, small hash log, old streaming cdcit, 12000408
silesia, small chain log, old streaming cdcit, 12000408
silesia, explicit params, old streaming cdcit, 12000408
silesia, uncompressed literals, old streaming cdcit, 4862377
silesia, uncompressed literals optimal, old streaming cdcit, 4293262
silesia, huffman literals, old streaming cdcit, 6183385
silesia, multithreaded with advanced params, old streaming cdcit, 12000408
silesia.tar, level -5, old streaming cdcit, 6982738
silesia.tar, level -3, old streaming cdcit, 6641264
silesia.tar, level -1, old streaming cdcit, 6190789
silesia.tar, level 0, old streaming cdcit, 4875010
silesia.tar, level 1, old streaming cdcit, 5336879
silesia.tar, level 3, old streaming cdcit, 4875010
silesia.tar, level 4, old streaming cdcit, 4813507
silesia.tar, level 5, old streaming cdcit, 4722240
silesia.tar, level 6, old streaming cdcit, 4672203
silesia.tar, level 7, old streaming cdcit, 4606658
silesia.tar, level 9, old streaming cdcit, 4554105
silesia.tar, level 13, old streaming cdcit, 4491703
silesia.tar, level 16, old streaming cdcit, 4381277
silesia.tar, level 19, old streaming cdcit, 4281514
silesia.tar, no source size, old streaming cdcit, 4875006
silesia.tar, long distance mode, old streaming cdcit, 12022046
silesia.tar, multithreaded, old streaming cdcit, 12022046
silesia.tar, multithreaded long distance mode, old streaming cdcit, 12022046
silesia.tar, small window log, old streaming cdcit, 12022046
silesia.tar, small hash log, old streaming cdcit, 12022046
silesia.tar, small chain log, old streaming cdcit, 12022046
silesia.tar, explicit params, old streaming cdcit, 12022046
silesia.tar, uncompressed literals, old streaming cdcit, 4875010
silesia.tar, uncompressed literals optimal, old streaming cdcit, 4281514
silesia.tar, huffman literals, old streaming cdcit, 6190789
silesia.tar, multithreaded with advanced params, old streaming cdcit, 12022046
github, level -5, old streaming cdcit, 205285
github, level -5 with dict, old streaming cdcit, 46718
github, level -3, old streaming cdcit, 190643
github, level -3 with dict, old streaming cdcit, 45395
github, level -1, old streaming cdcit, 175568
github, level -1 with dict, old streaming cdcit, 43170
github, level 0, old streaming cdcit, 136397
github, level 0 with dict, old streaming cdcit, 41170
github, level 1, old streaming cdcit, 142450
github, level 1 with dict, old streaming cdcit, 41682
github, level 3, old streaming cdcit, 136397
github, level 3 with dict, old streaming cdcit, 41170
github, level 4, old streaming cdcit, 136144
github, level 4 with dict, old streaming cdcit, 41306
github, level 5, old streaming cdcit, 135106
github, level 5 with dict, old streaming cdcit, 38938
github, level 6, old streaming cdcit, 135108
github, level 6 with dict, old streaming cdcit, 38632
github, level 7, old streaming cdcit, 135108
github, level 7 with dict, old streaming cdcit, 38766
github, level 9, old streaming cdcit, 135108
github, level 9 with dict, old streaming cdcit, 39326
github, level 13, old streaming cdcit, 133717
github, level 13 with dict, old streaming cdcit, 39716
github, level 16, old streaming cdcit, 133717
github, level 16 with dict, old streaming cdcit, 37577
github, level 19, old streaming cdcit, 133717
github, level 19 with dict, old streaming cdcit, 37576
github, no source size, old streaming cdcit, 141003
github, long distance mode, old streaming cdcit, 412933
github, multithreaded, old streaming cdcit, 412933
github, multithreaded long distance mode, old streaming cdcit, 412933
github, small window log, old streaming cdcit, 412933
github, small hash log, old streaming cdcit, 412933
github, small chain log, old streaming cdcit, 412933
github, explicit params, old streaming cdcit, 412933
github, uncompressed literals, old streaming cdcit, 136397
github, uncompressed literals optimal, old streaming cdcit, 133717
github, huffman literals, old streaming cdcit, 175568
github, multithreaded with advanced params, old streaming cdcit, 412933
silesia, level -5, old streaming advanced cdict, 6882466
silesia, level -3, old streaming advanced cdict, 6568358
silesia, level -1, old streaming advanced cdict, 6183385
silesia, level 0, old streaming advanced cdict, 4862377
silesia, level 1, old streaming advanced cdict, 5314109
silesia, level 3, old streaming advanced cdict, 4862377
silesia, level 4, old streaming advanced cdict, 4800629
silesia, level 5, old streaming advanced cdict, 4710178
silesia, level 6, old streaming advanced cdict, 4659996
silesia, level 7, old streaming advanced cdict, 4596234
silesia, level 9, old streaming advanced cdict, 4543862
silesia, level 13, old streaming advanced cdict, 4482073
silesia, level 16, old streaming advanced cdict, 4377391
silesia, level 19, old streaming advanced cdict, 4293262
silesia, no source size, old streaming advanced cdict, 4862341
silesia, long distance mode, old streaming advanced cdict, 12000408
silesia, multithreaded, old streaming advanced cdict, 12000408
silesia, multithreaded long distance mode, old streaming advanced cdict, 12000408
silesia, small window log, old streaming advanced cdict, 12000408
silesia, small hash log, old streaming advanced cdict, 12000408
silesia, small chain log, old streaming advanced cdict, 12000408
silesia, explicit params, old streaming advanced cdict, 12000408
silesia, uncompressed literals, old streaming advanced cdict, 4862377
silesia, uncompressed literals optimal, old streaming advanced cdict, 4293262
silesia, huffman literals, old streaming advanced cdict, 6183385
silesia, multithreaded with advanced params, old streaming advanced cdict, 12000408
silesia.tar, level -5, old streaming advanced cdict, 6982738
silesia.tar, level -3, old streaming advanced cdict, 6641264
silesia.tar, level -1, old streaming advanced cdict, 6190789
silesia.tar, level 0, old streaming advanced cdict, 4875010
silesia.tar, level 1, old streaming advanced cdict, 5336879
silesia.tar, level 3, old streaming advanced cdict, 4875010
silesia.tar, level 4, old streaming advanced cdict, 4813507
silesia.tar, level 5, old streaming advanced cdict, 4722240
silesia.tar, level 6, old streaming advanced cdict, 4672203
silesia.tar, level 7, old streaming advanced cdict, 4606658
silesia.tar, level 9, old streaming advanced cdict, 4554105
silesia.tar, level 13, old streaming advanced cdict, 4491703
silesia.tar, level 16, old streaming advanced cdict, 4381277
silesia.tar, level 19, old streaming advanced cdict, 4281514
silesia.tar, no source size, old streaming advanced cdict, 4875006
silesia.tar, long distance mode, old streaming advanced cdict, 12022046
silesia.tar, multithreaded, old streaming advanced cdict, 12022046
silesia.tar, multithreaded long distance mode, old streaming advanced cdict, 12022046
silesia.tar, small window log, old streaming advanced cdict, 12022046
silesia.tar, small hash log, old streaming advanced cdict, 12022046
silesia.tar, small chain log, old streaming advanced cdict, 12022046
silesia.tar, explicit params, old streaming advanced cdict, 12022046
silesia.tar, uncompressed literals, old streaming advanced cdict, 4875010
silesia.tar, uncompressed literals optimal, old streaming advanced cdict, 4281514
silesia.tar, huffman literals, old streaming advanced cdict, 6190789
silesia.tar, multithreaded with advanced params, old streaming advanced cdict, 12022046
github, level -5, old streaming advanced cdict, 205285
github, level -5 with dict, old streaming advanced cdict, 46718
github, level -3, old streaming advanced cdict, 190643
github, level -3 with dict, old streaming advanced cdict, 45395
github, level -1, old streaming advanced cdict, 175568
github, level -1 with dict, old streaming advanced cdict, 43170
github, level 0, old streaming advanced cdict, 136397
github, level 0 with dict, old streaming advanced cdict, 41170
github, level 1, old streaming advanced cdict, 142450
github, level 1 with dict, old streaming advanced cdict, 41682
github, level 3, old streaming advanced cdict, 136397
github, level 3 with dict, old streaming advanced cdict, 41170
github, level 4, old streaming advanced cdict, 136144
github, level 4 with dict, old streaming advanced cdict, 41306
github, level 5, old streaming advanced cdict, 135106
github, level 5 with dict, old streaming advanced cdict, 38938
github, level 6, old streaming advanced cdict, 135108
github, level 6 with dict, old streaming advanced cdict, 38632
github, level 7, old streaming advanced cdict, 135108
github, level 7 with dict, old streaming advanced cdict, 38766
github, level 9, old streaming advanced cdict, 135108
github, level 9 with dict, old streaming advanced cdict, 39326
github, level 13, old streaming advanced cdict, 133717
github, level 13 with dict, old streaming advanced cdict, 39716
github, level 16, old streaming advanced cdict, 133717
github, level 16 with dict, old streaming advanced cdict, 37577
github, level 19, old streaming advanced cdict, 133717
github, level 19 with dict, old streaming advanced cdict, 37576
github, no source size, old streaming advanced cdict, 141003
github, long distance mode, old streaming advanced cdict, 412933
github, multithreaded, old streaming advanced cdict, 412933
github, multithreaded long distance mode, old streaming advanced cdict, 412933
github, small window log, old streaming advanced cdict, 412933
github, small hash log, old streaming advanced cdict, 412933
github, small chain log, old streaming advanced cdict, 412933
github, explicit params, old streaming advanced cdict, 412933
github, uncompressed literals, old streaming advanced cdict, 136397
github, uncompressed literals optimal, old streaming advanced cdict, 133717
github, huffman literals, old streaming advanced cdict, 175568
github, multithreaded with advanced params, old streaming advanced cdict, 412933
1 Data Config Method Total compressed size
2 silesia.tar level -5 compress simple 7160438 6738558
3 silesia.tar level -3 compress simple 6789024 6446362
4 silesia.tar level -1 compress simple 6195462 6186038
5 silesia.tar level 0 compress simple 4875008
6 silesia.tar level 1 compress simple 5339697 5334825
7 silesia.tar level 3 compress simple 4875008
8 silesia.tar level 4 compress simple 4813507
9 silesia.tar level 5 compress simple 4722235
10 silesia.tar level 6 compress simple 4672194
11 silesia.tar level 7 compress simple 4606658
12 silesia.tar level 9 compress simple 4554098
13 silesia.tar level 13 compress simple 4491702
14 silesia.tar level 16 compress simple 4381277
15 silesia.tar level 19 compress simple 4281514
16 silesia silesia.tar level -5 uncompressed literals compress cctx compress simple 7152294 4875008
17 silesia silesia.tar level -3 uncompressed literals optimal compress cctx compress simple 6789969 4281514
18 silesia silesia.tar level -1 huffman literals compress cctx compress simple 6191548 6186038
19 silesia level 0 level -5 compress cctx 4862377 6737567
20 silesia level 1 level -3 compress cctx 5318036 6444663
21 silesia level 3 level -1 compress cctx 4862377 6178442
22 silesia level 4 level 0 compress cctx 4800629 4862377
23 silesia level 5 level 1 compress cctx 4710178 5313144
24 silesia level 6 level 3 compress cctx 4659996 4862377
25 silesia level 7 level 4 compress cctx 4596234 4800629
26 silesia level 9 level 5 compress cctx 4543862 4710178
27 silesia level 13 level 6 compress cctx 4482073 4659996
28 silesia level 16 level 7 compress cctx 4377391 4596234
29 silesia level 19 level 9 compress cctx 4293262 4543862
30 silesia long distance mode level 13 compress cctx 4862377 4482073
31 silesia multithreaded level 16 compress cctx 4862377 4377391
32 silesia multithreaded long distance mode level 19 compress cctx 4862377 4293262
33 silesia small window log long distance mode compress cctx 7115734 4862377
34 silesia small hash log multithreaded compress cctx 6554898 4862377
35 silesia small chain log multithreaded long distance mode compress cctx 4931093 4862377
36 silesia explicit params small window log compress cctx 4813352 7115734
37 github silesia level -5 small hash log compress cctx 232744 6554898
38 github silesia level -5 with dict small chain log compress cctx 47294 4931093
39 github silesia level -3 explicit params compress cctx 220611 4813352
40 github silesia level -3 with dict uncompressed literals compress cctx 48047 4862377
41 github silesia level -1 uncompressed literals optimal compress cctx 176575 4293262
42 github silesia level -1 with dict huffman literals compress cctx 43527 6178442
43 github silesia level 0 multithreaded with advanced params compress cctx 136397 4862377
44 github level 0 with dict level -5 compress cctx 41536 205285
45 github level 1 level -5 with dict compress cctx 143457 47294
46 github level 1 with dict level -3 compress cctx 42157 190643
47 github level 3 level -3 with dict compress cctx 136397 48047
48 github level 3 with dict level -1 compress cctx 41536 175568
49 github level 4 level -1 with dict compress cctx 136144 43527
50 github level 4 with dict level 0 compress cctx 41721 136397
51 github level 5 level 0 with dict compress cctx 135106 41536
52 github level 5 with dict level 1 compress cctx 38934 142450
53 github level 6 level 1 with dict compress cctx 135108 42157
54 github level 6 with dict level 3 compress cctx 38628 136397
55 github level 7 level 3 with dict compress cctx 135108 41536
56 github level 7 with dict level 4 compress cctx 38741 136144
57 github level 9 level 4 with dict compress cctx 135108 41721
58 github level 9 with dict level 5 compress cctx 39335 135106
59 github level 13 level 5 with dict compress cctx 133717 38934
60 github level 13 with dict level 6 compress cctx 39923 135108
61 github level 16 level 6 with dict compress cctx 133717 38628
62 github level 16 with dict level 7 compress cctx 37568 135108
63 github level 19 level 7 with dict compress cctx 133717 38741
64 github level 19 with dict level 9 compress cctx 37567 135108
65 github long distance mode level 9 with dict compress cctx decompression error 39335
66 github multithreaded level 13 compress cctx decompression error 133717
67 github multithreaded long distance mode level 13 with dict compress cctx decompression error 39923
68 github small window log level 16 compress cctx decompression error 133717
69 github small hash log level 16 with dict compress cctx decompression error 37568
70 github small chain log level 19 compress cctx decompression error 133717
71 github explicit params level 19 with dict compress cctx decompression error 37567
72 silesia github level -5 long distance mode zstdcli compress cctx 7152342 141473
73 silesia github level -3 multithreaded zstdcli compress cctx 6790021 141473
74 silesia github level -1 multithreaded long distance mode zstdcli compress cctx 6191597 141473
75 silesia github level 0 small window log zstdcli compress cctx 4862425 141473
76 silesia github level 1 small hash log zstdcli compress cctx 5318084 138943
77 silesia github level 3 small chain log zstdcli compress cctx 4862425 139239
78 silesia github level 4 explicit params zstdcli compress cctx 4800677 140924
79 silesia github level 5 uncompressed literals zstdcli compress cctx 4710226 136397
80 silesia github level 6 uncompressed literals optimal zstdcli compress cctx 4660044 133717
81 silesia github level 7 huffman literals zstdcli compress cctx 4596282 175568
82 silesia github level 9 multithreaded with advanced params zstdcli compress cctx 4543910 141473
83 silesia level 13 level -5 zstdcli 4482121 6882514
84 silesia level 16 level -3 zstdcli 4377439 6568406
85 silesia level 19 level -1 zstdcli 4293310 6183433
86 silesia long distance mode level 0 zstdcli 4853437 4862425
87 silesia multithreaded level 1 zstdcli 4862425 5314157
88 silesia multithreaded long distance mode level 3 zstdcli 4853437 4862425
89 silesia small window log level 4 zstdcli 7126434 4800677
90 silesia small hash log level 5 zstdcli 6554946 4710226
91 silesia small chain log level 6 zstdcli 4931141 4660044
92 silesia explicit params level 7 zstdcli 4815380 4596282
93 silesia.tar silesia level -5 level 9 zstdcli 7161160 4543910
94 silesia.tar silesia level -3 level 13 zstdcli 6789865 4482121
95 silesia.tar silesia level -1 level 16 zstdcli 6196433 4377439
96 silesia.tar silesia level 0 level 19 zstdcli 4875136 4293310
97 silesia.tar silesia level 1 long distance mode zstdcli 5340573 4853437
98 silesia.tar silesia level 3 multithreaded zstdcli 4875136 4862425
99 silesia.tar silesia level 4 multithreaded long distance mode zstdcli 4814531 4853437
100 silesia.tar silesia level 5 small window log zstdcli 4723284 7126434
101 silesia.tar silesia level 6 small hash log zstdcli 4673591 6554946
102 silesia.tar silesia level 7 small chain log zstdcli 4608342 4931141
103 silesia.tar silesia level 9 explicit params zstdcli 4554700 4815380
104 silesia.tar silesia level 13 uncompressed literals zstdcli 4491706 5155472
105 silesia.tar silesia level 16 uncompressed literals optimal zstdcli 4381281 4325475
106 silesia.tar silesia level 19 huffman literals zstdcli 4281518 5331158
107 silesia.tar silesia no source size multithreaded with advanced params zstdcli 4875132 5155472
108 silesia.tar long distance mode level -5 zstdcli 4866975 6738906
109 silesia.tar multithreaded level -3 zstdcli 4875136 6448409
110 silesia.tar multithreaded long distance mode level -1 zstdcli 4866975 6186908
111 silesia.tar small window log level 0 zstdcli 7130434 4875136
112 silesia.tar small hash log level 1 zstdcli 6587841 5336255
113 silesia.tar small chain log level 3 zstdcli 4943259 4875136
114 silesia.tar explicit params level 4 zstdcli 4839202 4814531
115 github silesia.tar level -5 level 5 zstdcli 234744 4723284
116 github silesia.tar level -5 with dict level 6 zstdcli 48718 4673591
117 github silesia.tar level -3 level 7 zstdcli 222611 4608342
118 github silesia.tar level -3 with dict level 9 zstdcli 47395 4554700
119 github silesia.tar level -1 level 13 zstdcli 178575 4491706
120 github silesia.tar level -1 with dict level 16 zstdcli 45170 4381281
121 github silesia.tar level 0 level 19 zstdcli 138397 4281518
122 github silesia.tar level 0 with dict no source size zstdcli 43170 4875132
123 github silesia.tar level 1 long distance mode zstdcli 145457 4866975
124 github silesia.tar level 1 with dict multithreaded zstdcli 43682 4875136
125 github silesia.tar level 3 multithreaded long distance mode zstdcli 138397 4866975
126 github silesia.tar level 3 with dict small window log zstdcli 43170 7130434
127 github silesia.tar level 4 small hash log zstdcli 138144 6587841
128 github silesia.tar level 4 with dict small chain log zstdcli 43306 4943259
129 github silesia.tar level 5 explicit params zstdcli 137106 4839202
130 github silesia.tar level 5 with dict uncompressed literals zstdcli 40938 5158134
131 github silesia.tar level 6 uncompressed literals optimal zstdcli 137108 4321098
132 github silesia.tar level 6 with dict huffman literals zstdcli 40632 5347560
133 github silesia.tar level 7 multithreaded with advanced params zstdcli 137108 5158134
134 github level 7 with dict level -5 zstdcli 40766 207285
135 github level 9 level -5 with dict zstdcli 137108 48718
136 github level 9 with dict level -3 zstdcli 41326 192643
137 github level 13 level -3 with dict zstdcli 135717 47395
138 github level 13 with dict level -1 zstdcli 41716 177568
139 github level 16 level -1 with dict zstdcli 135717 45170
140 github level 16 with dict level 0 zstdcli 39577 138397
141 github level 19 level 0 with dict zstdcli 135717 43170
142 github level 19 with dict level 1 zstdcli 39576 144450
143 github long distance mode level 1 with dict zstdcli 138397 43682
144 github multithreaded level 3 zstdcli 138397
145 github multithreaded long distance mode level 3 with dict zstdcli 138397 43170
146 github small window log level 4 zstdcli 138397 138144
147 github small hash log level 4 with dict zstdcli 137467 43306
148 github small chain log level 5 zstdcli 138314 137106
149 github explicit params level 5 with dict zstdcli 136140 40938
150 silesia github level -5 level 6 advanced one pass zstdcli 7152294 137108
151 silesia github level -3 level 6 with dict advanced one pass zstdcli 6789969 40632
152 silesia github level -1 level 7 advanced one pass zstdcli 6191548 137108
153 silesia github level 0 level 7 with dict advanced one pass zstdcli 4862377 40766
154 silesia github level 1 level 9 advanced one pass zstdcli 5318036 137108
155 silesia github level 3 level 9 with dict advanced one pass zstdcli 4862377 41326
156 silesia github level 4 level 13 advanced one pass zstdcli 4800629 135717
157 silesia github level 5 level 13 with dict advanced one pass zstdcli 4710178 41716
158 silesia github level 6 level 16 advanced one pass zstdcli 4659996 135717
159 silesia github level 7 level 16 with dict advanced one pass zstdcli 4596234 39577
160 silesia github level 9 level 19 advanced one pass zstdcli 4543862 135717
161 silesia github level 13 level 19 with dict advanced one pass zstdcli 4482073 39576
162 silesia github level 16 long distance mode advanced one pass zstdcli 4377391 138397
163 silesia github level 19 multithreaded advanced one pass zstdcli 4293262 138397
164 silesia github no source size multithreaded long distance mode advanced one pass zstdcli 4862377 138397
165 silesia github long distance mode small window log advanced one pass zstdcli 4853389 138397
166 silesia github multithreaded small hash log advanced one pass zstdcli 4862377 137467
167 silesia github multithreaded long distance mode small chain log advanced one pass zstdcli 4853389 138314
168 silesia github small window log explicit params advanced one pass zstdcli 7126386 136140
169 silesia github small hash log uncompressed literals advanced one pass zstdcli 6554898 169004
170 silesia github small chain log uncompressed literals optimal advanced one pass zstdcli 4931093 158824
171 silesia github explicit params huffman literals advanced one pass zstdcli 4815369 144450
172 silesia.tar github level -5 multithreaded with advanced params advanced one pass zstdcli 7160438 169004
173 silesia.tar silesia level -3 level -5 advanced one pass 6789024 6737567
174 silesia.tar silesia level -1 level -3 advanced one pass 6195462 6444663
175 silesia.tar silesia level 0 level -1 advanced one pass 4875008 6178442
176 silesia.tar silesia level 1 level 0 advanced one pass 5339697 4862377
177 silesia.tar silesia level 3 level 1 advanced one pass 4875008 5313144
178 silesia.tar silesia level 4 level 3 advanced one pass 4813507 4862377
179 silesia.tar silesia level 5 level 4 advanced one pass 4722235 4800629
180 silesia.tar silesia level 6 level 5 advanced one pass 4672194 4710178
181 silesia.tar silesia level 7 level 6 advanced one pass 4606658 4659996
182 silesia.tar silesia level 9 level 7 advanced one pass 4554098 4596234
183 silesia.tar silesia level 13 level 9 advanced one pass 4491702 4543862
184 silesia.tar silesia level 16 level 13 advanced one pass 4381277 4482073
185 silesia.tar silesia level 19 level 16 advanced one pass 4281514 4377391
186 silesia.tar silesia no source size level 19 advanced one pass 4875008 4293262
187 silesia.tar silesia long distance mode no source size advanced one pass 4861218 4862377
188 silesia.tar silesia multithreaded long distance mode advanced one pass 4874631 4853389
189 silesia.tar silesia multithreaded long distance mode multithreaded advanced one pass 4860683 4862377
190 silesia.tar silesia small window log multithreaded long distance mode advanced one pass 7130394 4853389
191 silesia.tar silesia small hash log small window log advanced one pass 6587833 7126386
192 silesia.tar silesia small chain log small hash log advanced one pass 4943255 6554898
193 silesia.tar silesia explicit params small chain log advanced one pass 4829974 4931093
194 github silesia level -5 explicit params advanced one pass 232744 4815369
195 github silesia level -5 with dict uncompressed literals advanced one pass 46718 5155424
196 github silesia level -3 uncompressed literals optimal advanced one pass 220611 4325427
197 github silesia level -3 with dict huffman literals advanced one pass 45395 5326210
198 github silesia level -1 multithreaded with advanced params advanced one pass 176575 5155424
199 github silesia.tar level -1 with dict level -5 advanced one pass 43170 6738558
200 github silesia.tar level 0 level -3 advanced one pass 136397 6446362
201 github silesia.tar level 0 with dict level -1 advanced one pass 41170 6186038
202 github silesia.tar level 1 level 0 advanced one pass 143457 4875008
203 github silesia.tar level 1 with dict level 1 advanced one pass 41682 5334825
204 github silesia.tar level 3 advanced one pass 136397 4875008
205 github silesia.tar level 3 with dict level 4 advanced one pass 41170 4813507
206 github silesia.tar level 4 level 5 advanced one pass 136144 4722235
207 github silesia.tar level 4 with dict level 6 advanced one pass 41306 4672194
208 github silesia.tar level 5 level 7 advanced one pass 135106 4606658
209 github silesia.tar level 5 with dict level 9 advanced one pass 38938 4554098
210 github silesia.tar level 6 level 13 advanced one pass 135108 4491702
211 github silesia.tar level 6 with dict level 16 advanced one pass 38632 4381277
212 github silesia.tar level 7 level 19 advanced one pass 135108 4281514
213 github silesia.tar level 7 with dict no source size advanced one pass 38766 4875008
214 github silesia.tar level 9 long distance mode advanced one pass 135108 4861218
215 github silesia.tar level 9 with dict multithreaded advanced one pass 39326 4874631
216 github silesia.tar level 13 multithreaded long distance mode advanced one pass 133717 4860683
217 github silesia.tar level 13 with dict small window log advanced one pass 39716 7130394
218 github silesia.tar level 16 small hash log advanced one pass 133717 6587833
219 github silesia.tar level 16 with dict small chain log advanced one pass 37577 4943255
220 github silesia.tar level 19 explicit params advanced one pass 133717 4829974
221 github silesia.tar level 19 with dict uncompressed literals advanced one pass 37576 5157992
222 github silesia.tar no source size uncompressed literals optimal advanced one pass 136397 4321094
223 github silesia.tar long distance mode huffman literals advanced one pass 136397 5347283
224 github silesia.tar multithreaded multithreaded with advanced params advanced one pass 136397 5158545
225 github multithreaded long distance mode level -5 advanced one pass 136397 205285
226 github small window log level -5 with dict advanced one pass 136397 46718
227 github small hash log level -3 advanced one pass 135467 190643
228 github small chain log level -3 with dict advanced one pass 136314 45395
229 github explicit params level -1 advanced one pass 137670 175568
230 silesia github level -5 level -1 with dict advanced one pass small out advanced one pass 7152294 43170
231 silesia github level -3 level 0 advanced one pass small out advanced one pass 6789969 136397
232 silesia github level -1 level 0 with dict advanced one pass small out advanced one pass 6191548 41170
233 silesia github level 0 level 1 advanced one pass small out advanced one pass 4862377 142450
234 silesia github level 1 level 1 with dict advanced one pass small out advanced one pass 5318036 41682
235 silesia github level 3 advanced one pass small out advanced one pass 4862377 136397
236 silesia github level 4 level 3 with dict advanced one pass small out advanced one pass 4800629 41170
237 silesia github level 5 level 4 advanced one pass small out advanced one pass 4710178 136144
238 silesia github level 6 level 4 with dict advanced one pass small out advanced one pass 4659996 41306
239 silesia github level 7 level 5 advanced one pass small out advanced one pass 4596234 135106
240 silesia github level 9 level 5 with dict advanced one pass small out advanced one pass 4543862 38938
241 silesia github level 13 level 6 advanced one pass small out advanced one pass 4482073 135108
242 silesia github level 16 level 6 with dict advanced one pass small out advanced one pass 4377391 38632
243 silesia github level 19 level 7 advanced one pass small out advanced one pass 4293262 135108
244 silesia github no source size level 7 with dict advanced one pass small out advanced one pass 4862377 38766
245 silesia github long distance mode level 9 advanced one pass small out advanced one pass 4853389 135108
246 silesia github multithreaded level 9 with dict advanced one pass small out advanced one pass 4862377 39326
247 silesia github multithreaded long distance mode level 13 advanced one pass small out advanced one pass 4853389 133717
248 silesia github small window log level 13 with dict advanced one pass small out advanced one pass 7126386 39716
249 silesia github small hash log level 16 advanced one pass small out advanced one pass 6554898 133717
250 silesia github small chain log level 16 with dict advanced one pass small out advanced one pass 4931093 37577
251 silesia github explicit params level 19 advanced one pass small out advanced one pass 4815369 133717
252 silesia.tar github level -5 level 19 with dict advanced one pass small out advanced one pass 7160438 37576
253 silesia.tar github level -3 no source size advanced one pass small out advanced one pass 6789024 136397
254 silesia.tar github level -1 long distance mode advanced one pass small out advanced one pass 6195462 136397
255 silesia.tar github level 0 multithreaded advanced one pass small out advanced one pass 4875008 136397
256 silesia.tar github level 1 multithreaded long distance mode advanced one pass small out advanced one pass 5339697 136397
257 silesia.tar github level 3 small window log advanced one pass small out advanced one pass 4875008 136397
258 silesia.tar github level 4 small hash log advanced one pass small out advanced one pass 4813507 135467
259 silesia.tar github level 5 small chain log advanced one pass small out advanced one pass 4722235 136314
260 silesia.tar github level 6 explicit params advanced one pass small out advanced one pass 4672194 137670
261 silesia.tar github level 7 uncompressed literals advanced one pass small out advanced one pass 4606658 167004
262 silesia.tar github level 9 uncompressed literals optimal advanced one pass small out advanced one pass 4554098 156824
263 silesia.tar github level 13 huffman literals advanced one pass small out advanced one pass 4491702 142450
264 silesia.tar github level 16 multithreaded with advanced params advanced one pass small out advanced one pass 4381277 167004
265 silesia.tar silesia level 19 level -5 advanced one pass small out 4281514 6737567
266 silesia.tar silesia no source size level -3 advanced one pass small out 4875008 6444663
267 silesia.tar silesia long distance mode level -1 advanced one pass small out 4861218 6178442
268 silesia.tar silesia multithreaded level 0 advanced one pass small out 4874631 4862377
269 silesia.tar silesia multithreaded long distance mode level 1 advanced one pass small out 4860683 5313144
270 silesia.tar silesia small window log level 3 advanced one pass small out 7130394 4862377
271 silesia.tar silesia small hash log level 4 advanced one pass small out 6587833 4800629
272 silesia.tar silesia small chain log level 5 advanced one pass small out 4943255 4710178
273 silesia.tar silesia explicit params level 6 advanced one pass small out 4829974 4659996
274 github silesia level -5 level 7 advanced one pass small out 232744 4596234
275 github silesia level -5 with dict level 9 advanced one pass small out 46718 4543862
276 github silesia level -3 level 13 advanced one pass small out 220611 4482073
277 github silesia level -3 with dict level 16 advanced one pass small out 45395 4377391
278 github silesia level -1 level 19 advanced one pass small out 176575 4293262
279 github silesia level -1 with dict no source size advanced one pass small out 43170 4862377
280 github silesia level 0 long distance mode advanced one pass small out 136397 4853389
281 github silesia level 0 with dict multithreaded advanced one pass small out 41170 4862377
282 github silesia level 1 multithreaded long distance mode advanced one pass small out 143457 4853389
283 github silesia level 1 with dict small window log advanced one pass small out 41682 7126386
284 github silesia level 3 small hash log advanced one pass small out 136397 6554898
285 github silesia level 3 with dict small chain log advanced one pass small out 41170 4931093
286 github silesia level 4 explicit params advanced one pass small out 136144 4815369
287 github silesia level 4 with dict uncompressed literals advanced one pass small out 41306 5155424
288 github silesia level 5 uncompressed literals optimal advanced one pass small out 135106 4325427
289 github silesia level 5 with dict huffman literals advanced one pass small out 38938 5326210
290 github silesia level 6 multithreaded with advanced params advanced one pass small out 135108 5155424
291 github silesia.tar level 6 with dict level -5 advanced one pass small out 38632 6738558
292 github silesia.tar level 7 level -3 advanced one pass small out 135108 6446362
293 github silesia.tar level 7 with dict level -1 advanced one pass small out 38766 6186038
294 github silesia.tar level 9 level 0 advanced one pass small out 135108 4875008
295 github silesia.tar level 9 with dict level 1 advanced one pass small out 39326 5334825
296 github silesia.tar level 13 level 3 advanced one pass small out 133717 4875008
297 github silesia.tar level 13 with dict level 4 advanced one pass small out 39716 4813507
298 github silesia.tar level 16 level 5 advanced one pass small out 133717 4722235
299 github silesia.tar level 16 with dict level 6 advanced one pass small out 37577 4672194
300 github silesia.tar level 19 level 7 advanced one pass small out 133717 4606658
301 github silesia.tar level 19 with dict level 9 advanced one pass small out 37576 4554098
302 github silesia.tar no source size level 13 advanced one pass small out 136397 4491702
303 github silesia.tar long distance mode level 16 advanced one pass small out 136397 4381277
304 github silesia.tar multithreaded level 19 advanced one pass small out 136397 4281514
305 github silesia.tar multithreaded long distance mode no source size advanced one pass small out 136397 4875008
306 github silesia.tar small window log long distance mode advanced one pass small out 136397 4861218
307 github silesia.tar small hash log multithreaded advanced one pass small out 135467 4874631
308 github silesia.tar small chain log multithreaded long distance mode advanced one pass small out 136314 4860683
309 github silesia.tar explicit params small window log advanced one pass small out 137670 7130394
310 silesia silesia.tar level -5 small hash log advanced streaming advanced one pass small out 7152294 6587833
311 silesia silesia.tar level -3 small chain log advanced streaming advanced one pass small out 6789973 4943255
312 silesia silesia.tar level -1 explicit params advanced streaming advanced one pass small out 6191549 4829974
313 silesia silesia.tar level 0 uncompressed literals advanced streaming advanced one pass small out 4862377 5157992
314 silesia silesia.tar level 1 uncompressed literals optimal advanced streaming advanced one pass small out 5318036 4321094
315 silesia silesia.tar level 3 huffman literals advanced streaming advanced one pass small out 4862377 5347283
316 silesia silesia.tar level 4 multithreaded with advanced params advanced streaming advanced one pass small out 4800629 5158545
317 silesia github level 5 level -5 advanced streaming advanced one pass small out 4710178 205285
318 silesia github level 6 level -5 with dict advanced streaming advanced one pass small out 4659996 46718
319 silesia github level 7 level -3 advanced streaming advanced one pass small out 4596234 190643
320 silesia github level 9 level -3 with dict advanced streaming advanced one pass small out 4543862 45395
321 silesia github level 13 level -1 advanced streaming advanced one pass small out 4482073 175568
322 silesia github level 16 level -1 with dict advanced streaming advanced one pass small out 4377391 43170
323 silesia github level 19 level 0 advanced streaming advanced one pass small out 4293262 136397
324 silesia github no source size level 0 with dict advanced streaming advanced one pass small out 4862341 41170
325 silesia github long distance mode level 1 advanced streaming advanced one pass small out 4853389 142450
326 silesia github multithreaded level 1 with dict advanced streaming advanced one pass small out 4862377 41682
327 silesia github multithreaded long distance mode level 3 advanced streaming advanced one pass small out 4853389 136397
328 silesia github small window log level 3 with dict advanced streaming advanced one pass small out 7126389 41170
329 silesia github small hash log level 4 advanced streaming advanced one pass small out 6554898 136144
330 silesia github small chain log level 4 with dict advanced streaming advanced one pass small out 4931093 41306
331 silesia github explicit params level 5 advanced streaming advanced one pass small out 4815380 135106
332 silesia.tar github level -5 level 5 with dict advanced streaming advanced one pass small out 7160440 38938
333 silesia.tar github level -3 level 6 advanced streaming advanced one pass small out 6789026 135108
334 silesia.tar github level -1 level 6 with dict advanced streaming advanced one pass small out 6195465 38632
335 silesia.tar github level 0 level 7 advanced streaming advanced one pass small out 4875010 135108
336 silesia.tar github level 1 level 7 with dict advanced streaming advanced one pass small out 5339701 38766
337 silesia.tar github level 3 level 9 advanced streaming advanced one pass small out 4875010 135108
338 silesia.tar github level 4 level 9 with dict advanced streaming advanced one pass small out 4813507 39326
339 silesia.tar github level 5 level 13 advanced streaming advanced one pass small out 4722240 133717
340 silesia.tar github level 6 level 13 with dict advanced streaming advanced one pass small out 4672203 39716
341 silesia.tar github level 7 level 16 advanced streaming advanced one pass small out 4606658 133717
342 silesia.tar github level 9 level 16 with dict advanced streaming advanced one pass small out 4554105 37577
343 silesia.tar github level 13 level 19 advanced streaming advanced one pass small out 4491703 133717
344 silesia.tar github level 16 level 19 with dict advanced streaming advanced one pass small out 4381277 37576
345 silesia.tar github level 19 no source size advanced streaming advanced one pass small out 4281514 136397
346 silesia.tar github no source size long distance mode advanced streaming advanced one pass small out 4875006 136397
347 silesia.tar github long distance mode multithreaded advanced streaming advanced one pass small out 4861218 136397
348 silesia.tar github multithreaded multithreaded long distance mode advanced streaming advanced one pass small out 4875132 136397
349 silesia.tar github multithreaded long distance mode small window log advanced streaming advanced one pass small out 4866971 136397
350 silesia.tar github small window log small hash log advanced streaming advanced one pass small out 7130394 135467
351 silesia.tar github small hash log small chain log advanced streaming advanced one pass small out 6587834 136314
352 silesia.tar github small chain log explicit params advanced streaming advanced one pass small out 4943260 137670
353 silesia.tar github explicit params uncompressed literals advanced streaming advanced one pass small out 4830002 167004
354 github level -5 uncompressed literals optimal advanced streaming advanced one pass small out 232744 156824
355 github level -5 with dict huffman literals advanced streaming advanced one pass small out 46718 142450
356 github level -3 multithreaded with advanced params advanced streaming advanced one pass small out 220611 167004
357 github silesia level -3 with dict level -5 advanced streaming 45395 6882466
358 github silesia level -1 level -3 advanced streaming 176575 6568358
359 github silesia level -1 with dict level -1 advanced streaming 43170 6183385
360 github silesia level 0 advanced streaming 136397 4862377
361 github silesia level 0 with dict level 1 advanced streaming 41170 5314109
362 github silesia level 1 level 3 advanced streaming 143457 4862377
363 github silesia level 1 with dict level 4 advanced streaming 41682 4800629
364 github silesia level 3 level 5 advanced streaming 136397 4710178
365 github silesia level 3 with dict level 6 advanced streaming 41170 4659996
366 github silesia level 4 level 7 advanced streaming 136144 4596234
367 github silesia level 4 with dict level 9 advanced streaming 41306 4543862
368 github silesia level 5 level 13 advanced streaming 135106 4482073
369 github silesia level 5 with dict level 16 advanced streaming 38938 4377391
370 github silesia level 6 level 19 advanced streaming 135108 4293262
371 github silesia level 6 with dict no source size advanced streaming 38632 4862341
372 github silesia level 7 long distance mode advanced streaming 135108 4853389
373 github silesia level 7 with dict multithreaded advanced streaming 38766 4862377
374 github silesia level 9 multithreaded long distance mode advanced streaming 135108 4853389
375 github silesia level 9 with dict small window log advanced streaming 39326 7126389
376 github silesia level 13 small hash log advanced streaming 133717 6554898
377 github silesia level 13 with dict small chain log advanced streaming 39716 4931093
378 github silesia level 16 explicit params advanced streaming 133717 4815380
379 github silesia level 16 with dict uncompressed literals advanced streaming 37577 5155424
380 github silesia level 19 uncompressed literals optimal advanced streaming 133717 4325427
381 github silesia level 19 with dict huffman literals advanced streaming 37576 5331110
382 github silesia no source size multithreaded with advanced params advanced streaming 136397 5155424
383 github silesia.tar long distance mode level -5 advanced streaming 136397 6982738
384 github silesia.tar multithreaded level -3 advanced streaming 136397 6641264
385 github silesia.tar multithreaded long distance mode level -1 advanced streaming 136397 6190789
386 github silesia.tar small window log level 0 advanced streaming 136397 4875010
387 github silesia.tar small hash log level 1 advanced streaming 135467 5336879
388 github silesia.tar small chain log level 3 advanced streaming 136314 4875010
389 github silesia.tar explicit params level 4 advanced streaming 137670 4813507
390 silesia silesia.tar level -5 level 5 old streaming advanced streaming 7152294 4722240
391 silesia silesia.tar level -3 level 6 old streaming advanced streaming 6789973 4672203
392 silesia silesia.tar level -1 level 7 old streaming advanced streaming 6191549 4606658
393 silesia silesia.tar level 0 level 9 old streaming advanced streaming 4862377 4554105
394 silesia silesia.tar level 1 level 13 old streaming advanced streaming 5318036 4491703
395 silesia silesia.tar level 3 level 16 old streaming advanced streaming 4862377 4381277
396 silesia silesia.tar level 4 level 19 old streaming advanced streaming 4800629 4281514
397 silesia silesia.tar level 5 no source size old streaming advanced streaming 4710178 4875006
398 silesia silesia.tar level 6 long distance mode old streaming advanced streaming 4659996 4861218
399 silesia silesia.tar level 7 multithreaded old streaming advanced streaming 4596234 4875132
400 silesia silesia.tar level 9 multithreaded long distance mode old streaming advanced streaming 4543862 4866971
401 silesia silesia.tar level 13 small window log old streaming advanced streaming 4482073 7130394
402 silesia silesia.tar level 16 small hash log old streaming advanced streaming 4377391 6587834
403 silesia silesia.tar level 19 small chain log old streaming advanced streaming 4293262 4943260
404 silesia silesia.tar no source size explicit params old streaming advanced streaming 4862341 4830002
405 silesia.tar level -5 uncompressed literals old streaming advanced streaming 7160440 5157995
406 silesia.tar level -3 uncompressed literals optimal old streaming advanced streaming 6789026 4321094
407 silesia.tar level -1 huffman literals old streaming advanced streaming 6195465 5352306
408 silesia.tar level 0 multithreaded with advanced params old streaming advanced streaming 4875010 5158130
409 silesia.tar github level 1 level -5 old streaming advanced streaming 5339701 205285
410 silesia.tar github level 3 level -5 with dict old streaming advanced streaming 4875010 46718
411 silesia.tar github level 4 level -3 old streaming advanced streaming 4813507 190643
412 silesia.tar github level 5 level -3 with dict old streaming advanced streaming 4722240 45395
413 silesia.tar github level 6 level -1 old streaming advanced streaming 4672203 175568
414 silesia.tar github level 7 level -1 with dict old streaming advanced streaming 4606658 43170
415 silesia.tar github level 9 level 0 old streaming advanced streaming 4554105 136397
416 silesia.tar github level 13 level 0 with dict old streaming advanced streaming 4491703 41170
417 silesia.tar github level 16 level 1 old streaming advanced streaming 4381277 142450
418 silesia.tar github level 19 level 1 with dict old streaming advanced streaming 4281514 41682
419 silesia.tar github no source size level 3 old streaming advanced streaming 4875006 136397
420 github level -5 level 3 with dict old streaming advanced streaming 232744 41170
421 github level -5 with dict level 4 old streaming advanced streaming 46718 136144
422 github level -3 level 4 with dict old streaming advanced streaming 220611 41306
423 github level -3 with dict level 5 old streaming advanced streaming 45395 135106
424 github level -1 level 5 with dict old streaming advanced streaming 176575 38938
425 github level -1 with dict level 6 old streaming advanced streaming 43170 135108
426 github level 0 level 6 with dict old streaming advanced streaming 136397 38632
427 github level 0 with dict level 7 old streaming advanced streaming 41170 135108
428 github level 1 level 7 with dict old streaming advanced streaming 143457 38766
429 github level 1 with dict level 9 old streaming advanced streaming 41682 135108
430 github level 3 level 9 with dict old streaming advanced streaming 136397 39326
431 github level 3 with dict level 13 old streaming advanced streaming 41170 133717
432 github level 4 level 13 with dict old streaming advanced streaming 136144 39716
433 github level 4 with dict level 16 old streaming advanced streaming 41306 133717
434 github level 5 level 16 with dict old streaming advanced streaming 135106 37577
435 github level 5 with dict level 19 old streaming advanced streaming 38938 133717
436 github level 6 level 19 with dict old streaming advanced streaming 135108 37576
437 github level 6 with dict no source size old streaming advanced streaming 38632 136397
438 github level 7 long distance mode old streaming advanced streaming 135108 136397
439 github level 7 with dict multithreaded old streaming advanced streaming 38766 136397
440 github level 9 multithreaded long distance mode old streaming advanced streaming 135108 136397
441 github level 9 with dict small window log old streaming advanced streaming 39326 136397
442 github level 13 small hash log old streaming advanced streaming 133717 135467
443 github level 13 with dict small chain log old streaming advanced streaming 39716 136314
444 github level 16 explicit params old streaming advanced streaming 133717 137670
445 github level 16 with dict uncompressed literals old streaming advanced streaming 37577 167004
446 github level 19 uncompressed literals optimal old streaming advanced streaming 133717 156824
447 github level 19 with dict huffman literals old streaming advanced streaming 37576 142450
448 github no source size multithreaded with advanced params old streaming advanced streaming 141003 167004
449 silesia level -5 old streaming 6882466
450 silesia level -3 old streaming 6568358
451 silesia level -1 old streaming 6183385
452 silesia level 0 old streaming 4862377
453 silesia level 1 old streaming 5314109
454 silesia level 3 old streaming 4862377
455 silesia level 4 old streaming 4800629
456 silesia level 5 old streaming 4710178
457 silesia level 6 old streaming 4659996
458 silesia level 7 old streaming 4596234
459 silesia level 9 old streaming 4543862
460 silesia level 13 old streaming 4482073
461 silesia level 16 old streaming 4377391
462 silesia level 19 old streaming 4293262
463 silesia no source size old streaming 4862341
464 silesia long distance mode old streaming 12000408
465 silesia multithreaded old streaming 12000408
466 silesia multithreaded long distance mode old streaming 12000408
467 silesia small window log old streaming 12000408
468 silesia small hash log old streaming 12000408
469 silesia small chain log old streaming 12000408
470 silesia explicit params old streaming 12000408
471 silesia uncompressed literals old streaming 4862377
472 silesia uncompressed literals optimal old streaming 4293262
473 silesia huffman literals old streaming 6183385
474 silesia multithreaded with advanced params old streaming 12000408
475 silesia.tar level -5 old streaming 6982738
476 silesia.tar level -3 old streaming 6641264
477 silesia.tar level -1 old streaming 6190789
478 silesia.tar level 0 old streaming 4875010
479 silesia.tar level 1 old streaming 5336879
480 silesia.tar level 3 old streaming 4875010
481 silesia.tar level 4 old streaming 4813507
482 silesia.tar level 5 old streaming 4722240
483 silesia.tar level 6 old streaming 4672203
484 silesia.tar level 7 old streaming 4606658
485 silesia.tar level 9 old streaming 4554105
486 silesia.tar level 13 old streaming 4491703
487 silesia.tar level 16 old streaming 4381277
488 silesia.tar level 19 old streaming 4281514
489 silesia.tar no source size old streaming 4875006
490 silesia.tar long distance mode old streaming 12022046
491 silesia.tar multithreaded old streaming 12022046
492 silesia.tar multithreaded long distance mode old streaming 12022046
493 silesia.tar small window log old streaming 12022046
494 silesia.tar small hash log old streaming 12022046
495 silesia.tar small chain log old streaming 12022046
496 silesia.tar explicit params old streaming 12022046
497 silesia.tar uncompressed literals old streaming 4875010
498 silesia.tar uncompressed literals optimal old streaming 4281514
499 silesia.tar huffman literals old streaming 6190789
500 silesia.tar multithreaded with advanced params old streaming 12022046
501 github level -5 old streaming 205285
502 github level -5 with dict old streaming 46718
503 github level -3 old streaming 190643
504 github level -3 with dict old streaming 45395
505 github level -1 old streaming 175568
506 github level -1 with dict old streaming 43170
507 github level 0 old streaming 136397
508 github level 0 with dict old streaming 41170
509 github level 1 old streaming 142450
510 github level 1 with dict old streaming 41682
511 github level 3 old streaming 136397
512 github level 3 with dict old streaming 41170
513 github level 4 old streaming 136144
514 github level 4 with dict old streaming 41306
515 github level 5 old streaming 135106
516 github level 5 with dict old streaming 38938
517 github level 6 old streaming 135108
518 github level 6 with dict old streaming 38632
519 github level 7 old streaming 135108
520 github level 7 with dict old streaming 38766
521 github level 9 old streaming 135108
522 github level 9 with dict old streaming 39326
523 github level 13 old streaming 133717
524 github level 13 with dict old streaming 39716
525 github level 16 old streaming 133717
526 github level 16 with dict old streaming 37577
527 github level 19 old streaming 133717
528 github level 19 with dict old streaming 37576
529 github no source size old streaming 141003
530 github long distance mode old streaming 412933
531 github multithreaded old streaming 412933
532 github multithreaded long distance mode old streaming 412933
533 github small window log old streaming 412933
534 github small hash log old streaming 412933
535 github small chain log old streaming 412933
536 github explicit params old streaming 412933
537 github uncompressed literals old streaming 136397
538 github uncompressed literals optimal old streaming 133717
539 github huffman literals old streaming 175568
540 github multithreaded with advanced params old streaming 412933
541 silesia level -5 old streaming advanced 6882466
542 silesia level -3 old streaming advanced 6568358
543 silesia level -1 old streaming advanced 6183385
544 silesia level 0 old streaming advanced 4862377
545 silesia level 1 old streaming advanced 5314109
546 silesia level 3 old streaming advanced 4862377
547 silesia level 4 old streaming advanced 4800629
548 silesia level 5 old streaming advanced 4710178
549 silesia level 6 old streaming advanced 4659996
550 silesia level 7 old streaming advanced 4596234
551 silesia level 9 old streaming advanced 4543862
552 silesia level 13 old streaming advanced 4482073
553 silesia level 16 old streaming advanced 4377391
554 silesia level 19 old streaming advanced 4293262
555 silesia no source size old streaming advanced 4862341
556 silesia long distance mode old streaming advanced 12000408
557 silesia multithreaded old streaming advanced 12000408
558 silesia multithreaded long distance mode old streaming advanced 12000408
559 silesia small window log old streaming advanced 12000408
560 silesia small hash log old streaming advanced 12000408
561 silesia small chain log old streaming advanced 12000408
562 silesia explicit params old streaming advanced 12000408
563 silesia uncompressed literals old streaming advanced 4862377
564 silesia uncompressed literals optimal old streaming advanced 4293262
565 silesia huffman literals old streaming advanced 6183385
566 silesia multithreaded with advanced params old streaming advanced 12000408
567 silesia.tar level -5 old streaming advanced 6982738
568 silesia.tar level -3 old streaming advanced 6641264
569 silesia.tar level -1 old streaming advanced 6190789
570 silesia.tar level 0 old streaming advanced 4875010
571 silesia.tar level 1 old streaming advanced 5336879
572 silesia.tar level 3 old streaming advanced 4875010
573 silesia.tar level 4 old streaming advanced 4813507
574 silesia.tar level 5 old streaming advanced 4722240
575 silesia.tar level 6 old streaming advanced 4672203
576 silesia.tar level 7 old streaming advanced 4606658
577 silesia.tar level 9 old streaming advanced 4554105
578 silesia.tar level 13 old streaming advanced 4491703
579 silesia.tar level 16 old streaming advanced 4381277
580 silesia.tar level 19 old streaming advanced 4281514
581 silesia.tar no source size old streaming advanced 4875006
582 silesia.tar long distance mode old streaming advanced 12022046
583 silesia.tar multithreaded old streaming advanced 12022046
584 silesia.tar multithreaded long distance mode old streaming advanced 12022046
585 silesia.tar small window log old streaming advanced 12022046
586 silesia.tar small hash log old streaming advanced 12022046
587 silesia.tar small chain log old streaming advanced 12022046
588 silesia.tar explicit params old streaming advanced 12022046
589 silesia.tar uncompressed literals old streaming advanced 4875010
590 silesia.tar uncompressed literals optimal old streaming advanced 4281514
591 silesia.tar huffman literals old streaming advanced 6190789
592 silesia.tar multithreaded with advanced params old streaming advanced 12022046
593 github level -5 old streaming advanced 205285
594 github level -5 with dict old streaming advanced 46718
595 github level -3 old streaming advanced 190643
596 github level -3 with dict old streaming advanced 45395
597 github level -1 old streaming advanced 175568
598 github level -1 with dict old streaming advanced 43170
599 github level 0 old streaming advanced 136397
600 github level 0 with dict old streaming advanced 41170
601 github level 1 old streaming advanced 142450
602 github level 1 with dict old streaming advanced 41682
603 github level 3 old streaming advanced 136397
604 github level 3 with dict old streaming advanced 41170
605 github level 4 old streaming advanced 136144
606 github level 4 with dict old streaming advanced 41306
607 github level 5 old streaming advanced 135106
608 github level 5 with dict old streaming advanced 38938
609 github level 6 old streaming advanced 135108
610 github level 6 with dict old streaming advanced 38632
611 github level 7 old streaming advanced 135108
612 github level 7 with dict old streaming advanced 38766
613 github level 9 old streaming advanced 135108
614 github level 9 with dict old streaming advanced 39326
615 github level 13 old streaming advanced 133717
616 github level 13 with dict old streaming advanced 39716
617 github level 16 old streaming advanced 133717
618 github level 16 with dict old streaming advanced 37577
619 github level 19 old streaming advanced 133717
620 github level 19 with dict old streaming advanced 37576
621 github no source size old streaming advanced 141003
622 github long distance mode old streaming advanced 412933
623 github multithreaded old streaming advanced 412933
624 github multithreaded long distance mode old streaming advanced 412933
625 github small window log old streaming advanced 412933
626 github small hash log old streaming advanced 412933
627 github small chain log old streaming advanced 412933
628 github explicit params old streaming advanced 412933
629 github uncompressed literals old streaming advanced 136397
630 github uncompressed literals optimal old streaming advanced 133717
631 github huffman literals old streaming advanced 175568
632 github multithreaded with advanced params old streaming advanced 412933
633 silesia level -5 old streaming cdcit 6882466
634 silesia level -3 old streaming cdcit 6568358
635 silesia level -1 old streaming cdcit 6183385
636 silesia level 0 old streaming cdcit 4862377
637 silesia level 1 old streaming cdcit 5314109
638 silesia level 3 old streaming cdcit 4862377
639 silesia level 4 old streaming cdcit 4800629
640 silesia level 5 old streaming cdcit 4710178
641 silesia level 6 old streaming cdcit 4659996
642 silesia level 7 old streaming cdcit 4596234
643 silesia level 9 old streaming cdcit 4543862
644 silesia level 13 old streaming cdcit 4482073
645 silesia level 16 old streaming cdcit 4377391
646 silesia level 19 old streaming cdcit 4293262
647 silesia no source size old streaming cdcit 4862341
648 silesia long distance mode old streaming cdcit 12000408
649 silesia multithreaded old streaming cdcit 12000408
650 silesia multithreaded long distance mode old streaming cdcit 12000408
651 silesia small window log old streaming cdcit 12000408
652 silesia small hash log old streaming cdcit 12000408
653 silesia small chain log old streaming cdcit 12000408
654 silesia explicit params old streaming cdcit 12000408
655 silesia uncompressed literals old streaming cdcit 4862377
656 silesia uncompressed literals optimal old streaming cdcit 4293262
657 silesia huffman literals old streaming cdcit 6183385
658 silesia multithreaded with advanced params old streaming cdcit 12000408
659 silesia.tar level -5 old streaming cdcit 6982738
660 silesia.tar level -3 old streaming cdcit 6641264
661 silesia.tar level -1 old streaming cdcit 6190789
662 silesia.tar level 0 old streaming cdcit 4875010
663 silesia.tar level 1 old streaming cdcit 5336879
664 silesia.tar level 3 old streaming cdcit 4875010
665 silesia.tar level 4 old streaming cdcit 4813507
666 silesia.tar level 5 old streaming cdcit 4722240
667 silesia.tar level 6 old streaming cdcit 4672203
668 silesia.tar level 7 old streaming cdcit 4606658
669 silesia.tar level 9 old streaming cdcit 4554105
670 silesia.tar level 13 old streaming cdcit 4491703
671 silesia.tar level 16 old streaming cdcit 4381277
672 silesia.tar level 19 old streaming cdcit 4281514
673 silesia.tar no source size old streaming cdcit 4875006
674 silesia.tar long distance mode old streaming cdcit 12022046
675 silesia.tar multithreaded old streaming cdcit 12022046
676 silesia.tar multithreaded long distance mode old streaming cdcit 12022046
677 silesia.tar small window log old streaming cdcit 12022046
678 silesia.tar small hash log old streaming cdcit 12022046
679 silesia.tar small chain log old streaming cdcit 12022046
680 silesia.tar explicit params old streaming cdcit 12022046
681 silesia.tar uncompressed literals old streaming cdcit 4875010
682 silesia.tar uncompressed literals optimal old streaming cdcit 4281514
683 silesia.tar huffman literals old streaming cdcit 6190789
684 silesia.tar multithreaded with advanced params old streaming cdcit 12022046
685 github level -5 old streaming cdcit 205285
686 github level -5 with dict old streaming cdcit 46718
687 github level -3 old streaming cdcit 190643
688 github level -3 with dict old streaming cdcit 45395
689 github level -1 old streaming cdcit 175568
690 github level -1 with dict old streaming cdcit 43170
691 github level 0 old streaming cdcit 136397
692 github level 0 with dict old streaming cdcit 41170
693 github level 1 old streaming cdcit 142450
694 github level 1 with dict old streaming cdcit 41682
695 github level 3 old streaming cdcit 136397
696 github level 3 with dict old streaming cdcit 41170
697 github level 4 old streaming cdcit 136144
698 github level 4 with dict old streaming cdcit 41306
699 github level 5 old streaming cdcit 135106
700 github level 5 with dict old streaming cdcit 38938
701 github level 6 old streaming cdcit 135108
702 github level 6 with dict old streaming cdcit 38632
703 github level 7 old streaming cdcit 135108
704 github level 7 with dict old streaming cdcit 38766
705 github level 9 old streaming cdcit 135108
706 github level 9 with dict old streaming cdcit 39326
707 github level 13 old streaming cdcit 133717
708 github level 13 with dict old streaming cdcit 39716
709 github level 16 old streaming cdcit 133717
710 github level 16 with dict old streaming cdcit 37577
711 github level 19 old streaming cdcit 133717
712 github level 19 with dict old streaming cdcit 37576
713 github no source size old streaming cdcit 141003
714 github long distance mode old streaming cdcit 412933
715 github multithreaded old streaming cdcit 412933
716 github multithreaded long distance mode old streaming cdcit 412933
717 github small window log old streaming cdcit 412933
718 github small hash log old streaming cdcit 412933
719 github small chain log old streaming cdcit 412933
720 github explicit params old streaming cdcit 412933
721 github uncompressed literals old streaming cdcit 136397
722 github uncompressed literals optimal old streaming cdcit 133717
723 github huffman literals old streaming cdcit 175568
724 github multithreaded with advanced params old streaming cdcit 412933
725 silesia level -5 old streaming advanced cdict 6882466
726 silesia level -3 old streaming advanced cdict 6568358
727 silesia level -1 old streaming advanced cdict 6183385
728 silesia level 0 old streaming advanced cdict 4862377
729 silesia level 1 old streaming advanced cdict 5314109
730 silesia level 3 old streaming advanced cdict 4862377
731 silesia level 4 old streaming advanced cdict 4800629
732 silesia level 5 old streaming advanced cdict 4710178
733 silesia level 6 old streaming advanced cdict 4659996
734 silesia level 7 old streaming advanced cdict 4596234
735 silesia level 9 old streaming advanced cdict 4543862
736 silesia level 13 old streaming advanced cdict 4482073
737 silesia level 16 old streaming advanced cdict 4377391
738 silesia level 19 old streaming advanced cdict 4293262
739 silesia no source size old streaming advanced cdict 4862341
740 silesia long distance mode old streaming advanced cdict 12000408
741 silesia multithreaded old streaming advanced cdict 12000408
742 silesia multithreaded long distance mode old streaming advanced cdict 12000408
743 silesia small window log old streaming advanced cdict 12000408
744 silesia small hash log old streaming advanced cdict 12000408
745 silesia small chain log old streaming advanced cdict 12000408
746 silesia explicit params old streaming advanced cdict 12000408
747 silesia uncompressed literals old streaming advanced cdict 4862377
748 silesia uncompressed literals optimal old streaming advanced cdict 4293262
749 silesia huffman literals old streaming advanced cdict 6183385
750 silesia multithreaded with advanced params old streaming advanced cdict 12000408
751 silesia.tar level -5 old streaming advanced cdict 6982738
752 silesia.tar level -3 old streaming advanced cdict 6641264
753 silesia.tar level -1 old streaming advanced cdict 6190789
754 silesia.tar level 0 old streaming advanced cdict 4875010
755 silesia.tar level 1 old streaming advanced cdict 5336879
756 silesia.tar level 3 old streaming advanced cdict 4875010
757 silesia.tar level 4 old streaming advanced cdict 4813507
758 silesia.tar level 5 old streaming advanced cdict 4722240
759 silesia.tar level 6 old streaming advanced cdict 4672203
760 silesia.tar level 7 old streaming advanced cdict 4606658
761 silesia.tar level 9 old streaming advanced cdict 4554105
762 silesia.tar level 13 old streaming advanced cdict 4491703
763 silesia.tar level 16 old streaming advanced cdict 4381277
764 silesia.tar level 19 old streaming advanced cdict 4281514
765 silesia.tar no source size old streaming advanced cdict 4875006
766 silesia.tar long distance mode old streaming advanced cdict 12022046
767 silesia.tar multithreaded old streaming advanced cdict 12022046
768 silesia.tar multithreaded long distance mode old streaming advanced cdict 12022046
769 silesia.tar small window log old streaming advanced cdict 12022046
770 silesia.tar small hash log old streaming advanced cdict 12022046
771 silesia.tar small chain log old streaming advanced cdict 12022046
772 silesia.tar explicit params old streaming advanced cdict 12022046
773 silesia.tar uncompressed literals old streaming advanced cdict 4875010
774 silesia.tar uncompressed literals optimal old streaming advanced cdict 4281514
775 silesia.tar huffman literals old streaming advanced cdict 6190789
776 silesia.tar multithreaded with advanced params old streaming advanced cdict 12022046
777 github level -5 old streaming advanced cdict 205285
778 github level -5 with dict old streaming advanced cdict 46718
779 github level -3 old streaming advanced cdict 190643
780 github level -3 with dict old streaming advanced cdict 45395
781 github level -1 old streaming advanced cdict 175568
782 github level -1 with dict old streaming advanced cdict 43170
783 github level 0 old streaming advanced cdict 136397
784 github level 0 with dict old streaming advanced cdict 41170
785 github level 1 old streaming advanced cdict 142450
786 github level 1 with dict old streaming advanced cdict 41682
787 github level 3 old streaming advanced cdict 136397
788 github level 3 with dict old streaming advanced cdict 41170
789 github level 4 old streaming advanced cdict 136144
790 github level 4 with dict old streaming advanced cdict 41306
791 github level 5 old streaming advanced cdict 135106
792 github level 5 with dict old streaming advanced cdict 38938
793 github level 6 old streaming advanced cdict 135108
794 github level 6 with dict old streaming advanced cdict 38632
795 github level 7 old streaming advanced cdict 135108
796 github level 7 with dict old streaming advanced cdict 38766
797 github level 9 old streaming advanced cdict 135108
798 github level 9 with dict old streaming advanced cdict 39326
799 github level 13 old streaming advanced cdict 133717
800 github level 13 with dict old streaming advanced cdict 39716
801 github level 16 old streaming advanced cdict 133717
802 github level 16 with dict old streaming advanced cdict 37577
803 github level 19 old streaming advanced cdict 133717
804 github level 19 with dict old streaming advanced cdict 37576
805 github no source size old streaming advanced cdict 141003
806 github long distance mode old streaming advanced cdict 412933
807 github multithreaded old streaming advanced cdict 412933
808 github multithreaded long distance mode old streaming advanced cdict 412933
809 github small window log old streaming advanced cdict 412933
810 github small hash log old streaming advanced cdict 412933
811 github small chain log old streaming advanced cdict 412933
812 github explicit params old streaming advanced cdict 412933
813 github uncompressed literals old streaming advanced cdict 136397
814 github uncompressed literals optimal old streaming advanced cdict 133717
815 github huffman literals old streaming advanced cdict 175568
816 github multithreaded with advanced params old streaming advanced cdict 412933
+1 -1
View File
@@ -153,7 +153,7 @@ static void print_help(void) {
} }
} }
/** Parse the arguments. Teturn 0 on success. Print help on failure. */ /** Parse the arguments. Return 0 on success. Print help on failure. */
static int parse_args(int argc, char** argv) { static int parse_args(int argc, char** argv) {
int option_index = 0; int option_index = 0;
int c; int c;
+3 -3
View File
@@ -93,9 +93,9 @@ static size_t cctxParamRoundTripTest(void* resultBuff, size_t resultBuffCapacity
int const cLevel = h32 % maxClevel; int const cLevel = h32 % maxClevel;
/* Set parameters */ /* Set parameters */
CHECK_Z( ZSTD_CCtxParam_setParameter(cctxParams, ZSTD_c_compressionLevel, cLevel) ); CHECK_Z( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_compressionLevel, cLevel) );
CHECK_Z( ZSTD_CCtxParam_setParameter(cctxParams, ZSTD_c_nbWorkers, 2) ); CHECK_Z( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_nbWorkers, 2) );
CHECK_Z( ZSTD_CCtxParam_setParameter(cctxParams, ZSTD_c_overlapLog, 5) ); CHECK_Z( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_overlapLog, 5) );
/* Apply parameters */ /* Apply parameters */
+1
View File
@@ -31,6 +31,7 @@ static const void *symbols[] = {
&ZSTD_getFrameContentSize, &ZSTD_getFrameContentSize,
&ZSTD_maxCLevel, &ZSTD_maxCLevel,
&ZSTD_compressBound, &ZSTD_compressBound,
&ZSTD_decompressBound,
&ZSTD_isError, &ZSTD_isError,
&ZSTD_getErrorName, &ZSTD_getErrorName,
&ZSTD_createCCtx, &ZSTD_createCCtx,
+1
View File
@@ -25,6 +25,7 @@
#include <stdlib.h> /* free */ #include <stdlib.h> /* free */
#include <stdio.h> /* fgets, sscanf */ #include <stdio.h> /* fgets, sscanf */
#include <string.h> /* strcmp */ #include <string.h> /* strcmp */
#include "timefn.h" /* UTIL_time_t */
#include "mem.h" #include "mem.h"
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel */ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel */
#include "zstd.h" /* ZSTD_compressBound */ #include "zstd.h" /* ZSTD_compressBound */
+178 -19
View File
@@ -26,6 +26,7 @@
#include <stdio.h> /* fgets, sscanf */ #include <stdio.h> /* fgets, sscanf */
#include <string.h> /* strcmp */ #include <string.h> /* strcmp */
#include <assert.h> /* assert */ #include <assert.h> /* assert */
#include "timefn.h" /* UTIL_time_t, UTIL_getTime */
#include "mem.h" #include "mem.h"
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel, ZSTD_customMem, ZSTD_getDictID_fromFrame */ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel, ZSTD_customMem, ZSTD_getDictID_fromFrame */
#include "zstd.h" /* ZSTD_compressBound */ #include "zstd.h" /* ZSTD_compressBound */
@@ -37,6 +38,7 @@
#include "xxhash.h" /* XXH64_* */ #include "xxhash.h" /* XXH64_* */
#include "seqgen.h" #include "seqgen.h"
#include "util.h" #include "util.h"
#include "timefn.h" /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */
/*-************************************ /*-************************************
@@ -344,6 +346,20 @@ static int basicUnitTests(U32 seed, double compressibility)
DISPLAYLEVEL(3, "OK (%u bytes) \n", (unsigned)(cstreamSize + cdictSize)); DISPLAYLEVEL(3, "OK (%u bytes) \n", (unsigned)(cstreamSize + cdictSize));
} }
/* context size functions */
DISPLAYLEVEL(3, "test%3i : estimate CStream size using CCtxParams : ", testNb++);
{ ZSTD_CCtx_params* const params = ZSTD_createCCtxParams();
size_t cstreamSize, cctxSize;
CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_compressionLevel, 19) );
cstreamSize = ZSTD_estimateCStreamSize_usingCCtxParams(params);
CHECK_Z(cstreamSize);
cctxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
CHECK_Z(cctxSize);
if (cstreamSize <= cctxSize + 2 * ZSTD_BLOCKSIZE_MAX) goto _output_error;
ZSTD_freeCCtxParams(params);
DISPLAYLEVEL(3, "OK \n");
}
DISPLAYLEVEL(3, "test%3i : check actual CStream size : ", testNb++); DISPLAYLEVEL(3, "test%3i : check actual CStream size : ", testNb++);
{ size_t const s = ZSTD_sizeof_CStream(zc); { size_t const s = ZSTD_sizeof_CStream(zc);
if (ZSTD_isError(s)) goto _output_error; if (ZSTD_isError(s)) goto _output_error;
@@ -495,7 +511,7 @@ static int basicUnitTests(U32 seed, double compressibility)
/* _srcSize compression test */ /* _srcSize compression test */
DISPLAYLEVEL(3, "test%3i : compress_srcSize %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH); DISPLAYLEVEL(3, "test%3i : compress_srcSize %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
ZSTD_initCStream_srcSize(zc, 1, CNBufferSize); CHECK_Z( ZSTD_initCStream_srcSize(zc, 1, CNBufferSize) );
outBuff.dst = (char*)(compressedBuffer); outBuff.dst = (char*)(compressedBuffer);
outBuff.size = compressedBufferSize; outBuff.size = compressedBufferSize;
outBuff.pos = 0; outBuff.pos = 0;
@@ -503,11 +519,14 @@ static int basicUnitTests(U32 seed, double compressibility)
inBuff.size = CNBufferSize; inBuff.size = CNBufferSize;
inBuff.pos = 0; inBuff.pos = 0;
CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );
if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ CHECK(inBuff.pos != inBuff.size, "Entire input should be consumed");
{ size_t const r = ZSTD_endStream(zc, &outBuff); { size_t const r = ZSTD_endStream(zc, &outBuff);
if (r != 0) goto _output_error; } /* error, or some data not flushed */ CHECK(r != 0, "Error or some data not flushed (ret=%zu)", r);
{ unsigned long long origSize = ZSTD_findDecompressedSize(outBuff.dst, outBuff.pos); }
if ((size_t)origSize != CNBufferSize) goto _output_error; } /* exact original size must be present */ { unsigned long long origSize = ZSTD_findDecompressedSize(outBuff.dst, outBuff.pos);
CHECK(origSize == ZSTD_CONTENTSIZE_UNKNOWN, "Unknown!");
CHECK((size_t)origSize != CNBufferSize, "Exact original size must be present (got %llu)", origSize);
}
DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100); DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
/* wrong _srcSize compression test */ /* wrong _srcSize compression test */
@@ -706,6 +725,156 @@ static int basicUnitTests(U32 seed, double compressibility)
} }
DISPLAYLEVEL(3, "OK\n"); DISPLAYLEVEL(3, "OK\n");
ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_CCtx_loadDictionary(zc, dictionary.start, dictionary.filled) );
cSize = ZSTD_compress2(zc, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBufferSize, 100 KB));
CHECK_Z(cSize);
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() with dictionary : ", testNb++);
{
ZSTD_DCtx* dctx = ZSTD_createDCtx();
/* We should fail to decompress without a dictionary. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
if (!ZSTD_isError(ret)) goto _output_error;
}
/* We should succeed to decompress with the dictionary. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictionary.start, dictionary.filled) );
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
if (in.pos != in.size) goto _output_error;
}
/* The dictionary should presist across calls. */
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
if (in.pos != in.size) goto _output_error;
}
/* The dictionary should not be cleared by ZSTD_reset_session_only. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
if (in.pos != in.size) goto _output_error;
}
/* When we reset the context the dictionary is cleared. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
if (!ZSTD_isError(ret)) goto _output_error;
}
ZSTD_freeDCtx(dctx);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_resetDStream() with dictionary : ", testNb++);
{
ZSTD_DCtx* dctx = ZSTD_createDCtx();
/* We should succeed to decompress with the dictionary. */
ZSTD_resetDStream(dctx);
CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictionary.start, dictionary.filled) );
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
if (in.pos != in.size) goto _output_error;
}
/* The dictionary should not be cleared by ZSTD_resetDStream(). */
ZSTD_resetDStream(dctx);
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
if (in.pos != in.size) goto _output_error;
}
/* The dictionary should be cleared by ZSTD_initDStream(). */
CHECK_Z( ZSTD_initDStream(dctx) );
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
if (!ZSTD_isError(ret)) goto _output_error;
}
ZSTD_freeDCtx(dctx);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() with ddict : ", testNb++);
{
ZSTD_DCtx* dctx = ZSTD_createDCtx();
ZSTD_DDict* ddict = ZSTD_createDDict(dictionary.start, dictionary.filled);
/* We should succeed to decompress with the ddict. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddict) );
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
if (in.pos != in.size) goto _output_error;
}
/* The ddict should presist across calls. */
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
if (in.pos != in.size) goto _output_error;
}
/* When we reset the context the ddict is cleared. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
if (!ZSTD_isError(ret)) goto _output_error;
}
ZSTD_freeDCtx(dctx);
ZSTD_freeDDict(ddict);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressDCtx() with prefix : ", testNb++);
{
ZSTD_DCtx* dctx = ZSTD_createDCtx();
/* We should succeed to decompress with the prefix. */
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);
CHECK_Z( ZSTD_DCtx_refPrefix_advanced(dctx, dictionary.start, dictionary.filled, ZSTD_dct_auto) );
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;
if (in.pos != in.size) goto _output_error;
}
/* The prefix should be cleared after the first compression. */
{ ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
if (!ZSTD_isError(ret)) goto _output_error;
}
ZSTD_freeDCtx(dctx);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_initDStream*() with dictionary : ", testNb++);
{
ZSTD_DCtx* dctx = ZSTD_createDCtx();
ZSTD_DDict* ddict = ZSTD_createDDict(dictionary.start, dictionary.filled);
size_t ret;
/* We should succeed to decompress with the dictionary. */
CHECK_Z( ZSTD_initDStream_usingDict(dctx, dictionary.start, dictionary.filled) );
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );
/* The dictionary should presist across calls. */
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );
/* We should succeed to decompress with the ddict. */
CHECK_Z( ZSTD_initDStream_usingDDict(dctx, ddict) );
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );
/* The ddict should presist across calls. */
CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );
/* When we reset the context the ddict is cleared. */
CHECK_Z( ZSTD_initDStream(dctx) );
ret = ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize);
if (!ZSTD_isError(ret)) goto _output_error;
ZSTD_freeDCtx(dctx);
ZSTD_freeDDict(ddict);
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_usingCDict_advanced with masked dictID : ", testNb++); DISPLAYLEVEL(3, "test%3i : ZSTD_initCStream_usingCDict_advanced with masked dictID : ", testNb++);
{ ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictionary.filled); { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictionary.filled);
ZSTD_frameParameters const fParams = { 1 /* contentSize */, 1 /* checksum */, 1 /* noDictID */}; ZSTD_frameParameters const fParams = { 1 /* contentSize */, 1 /* checksum */, 1 /* noDictID */};
@@ -882,7 +1051,7 @@ static int basicUnitTests(U32 seed, double compressibility)
inBuff.size = srcSize; assert(srcSize < COMPRESSIBLE_NOISE_LENGTH); inBuff.size = srcSize; assert(srcSize < COMPRESSIBLE_NOISE_LENGTH);
inBuff.pos = 0; inBuff.pos = 0;
} }
{ ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, 4 KB, dictionary.filled); /* intentionnally lies on estimatedSrcSize, to push cdict into targeting a small window size */ { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, 4 KB, dictionary.filled); /* intentionally lies on estimatedSrcSize, to push cdict into targeting a small window size */
ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem); ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem);
DISPLAYLEVEL(5, "cParams.windowLog = %u : ", cParams.windowLog); DISPLAYLEVEL(5, "cParams.windowLog = %u : ", cParams.windowLog);
CHECK_Z( ZSTD_CCtx_refCDict(zc, cdict) ); CHECK_Z( ZSTD_CCtx_refCDict(zc, cdict) );
@@ -1703,7 +1872,7 @@ static size_t setCCtxParameter(ZSTD_CCtx* zc, ZSTD_CCtx_params* cctxParams,
int useOpaqueAPI) int useOpaqueAPI)
{ {
if (useOpaqueAPI) { if (useOpaqueAPI) {
return ZSTD_CCtxParam_setParameter(cctxParams, param, value); return ZSTD_CCtxParams_setParameter(cctxParams, param, value);
} else { } else {
return ZSTD_CCtx_setParameter(zc, param, value); return ZSTD_CCtx_setParameter(zc, param, value);
} }
@@ -1900,7 +2069,7 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) ); CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) );
} }
/* multi-threading parameters. Only adjust ocassionally for small tests. */ /* multi-threading parameters. Only adjust occasionally for small tests. */
if (bigTests || (FUZ_rand(&lseed) & 0xF) == 0xF) { if (bigTests || (FUZ_rand(&lseed) & 0xF) == 0xF) {
U32 const nbThreadsCandidate = (FUZ_rand(&lseed) & 4) + 1; U32 const nbThreadsCandidate = (FUZ_rand(&lseed) & 4) + 1;
U32 const nbThreadsAdjusted = (windowLogMalus < nbThreadsCandidate) ? nbThreadsCandidate - windowLogMalus : 1; U32 const nbThreadsAdjusted = (windowLogMalus < nbThreadsCandidate) ? nbThreadsCandidate - windowLogMalus : 1;
@@ -1930,16 +2099,6 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
} else { } else {
CHECK_Z( ZSTD_CCtx_loadDictionary_byReference(zc, dict, dictSize) ); CHECK_Z( ZSTD_CCtx_loadDictionary_byReference(zc, dict, dictSize) );
} }
if (dict && dictSize) {
/* test that compression parameters are rejected (correctly) after loading a non-NULL dictionary */
if (opaqueAPI) {
size_t const setError = ZSTD_CCtx_setParametersUsingCCtxParams(zc, cctxParams);
CHECK(!ZSTD_isError(setError), "ZSTD_CCtx_setParametersUsingCCtxParams should have failed");
} else {
size_t const setError = ZSTD_CCtx_setParameter(zc, ZSTD_c_windowLog, cParams.windowLog-1);
CHECK(!ZSTD_isError(setError), "ZSTD_CCtx_setParameter should have failed");
}
}
} else { } else {
CHECK_Z( ZSTD_CCtx_refPrefix(zc, dict, dictSize) ); CHECK_Z( ZSTD_CCtx_refPrefix(zc, dict, dictSize) );
} }
+1 -1
View File
@@ -88,7 +88,7 @@ fitblk: $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(ZSTDLI
fitblk_zstd: $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstdTurnedOn_zlibwrapper.o $(ZSTDLIBRARY) fitblk_zstd: $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstdTurnedOn_zlibwrapper.o $(ZSTDLIBRARY)
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@
zwrapbench: $(EXAMPLE_PATH)/zwrapbench.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(PROGRAMS_PATH)/util.o $(PROGRAMS_PATH)/datagen.o $(ZSTDLIBRARY) zwrapbench: $(EXAMPLE_PATH)/zwrapbench.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(PROGRAMS_PATH)/util.o $(PROGRAMS_PATH)/timefn.o $(PROGRAMS_PATH)/datagen.o $(ZSTDLIBRARY)
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@
+3 -3
View File
@@ -71,7 +71,7 @@ inflate with dictionary: hello, hello!
The script used for compilation can be found at [zlibWrapper/Makefile](Makefile). The script used for compilation can be found at [zlibWrapper/Makefile](Makefile).
#### The measurement of performace of Zstandard wrapper for zlib #### The measurement of performance of Zstandard wrapper for zlib
The zstd distribution contains a tool called `zwrapbench` which can measure speed and ratio of zlib, zstd, and the wrapper. The zstd distribution contains a tool called `zwrapbench` which can measure speed and ratio of zlib, zstd, and the wrapper.
The benchmark is conducted using given filenames or synthetic data if filenames are not provided. The benchmark is conducted using given filenames or synthetic data if filenames are not provided.
@@ -96,8 +96,8 @@ as this case is automatically detected.
#### Reusing contexts #### Reusing contexts
The ordinary zlib compression of two files/streams allocates two contexts: The ordinary zlib compression of two files/streams allocates two contexts:
- for the 1st file calls `deflateInit`, `deflate`, `...`, `deflate`, `defalateEnd` - for the 1st file calls `deflateInit`, `deflate`, `...`, `deflate`, `deflateEnd`
- for the 2nd file calls `deflateInit`, `deflate`, `...`, `deflate`, `defalateEnd` - for the 2nd file calls `deflateInit`, `deflate`, `...`, `deflate`, `deflateEnd`
The speed of compression can be improved with reusing a single context with following steps: The speed of compression can be improved with reusing a single context with following steps:
- initialize the context with `deflateInit` - initialize the context with `deflateInit`
+2 -2
View File
@@ -21,7 +21,7 @@
data in order to determine how much of that input will compress to data in order to determine how much of that input will compress to
nearly the requested output block size. The first pass generates nearly the requested output block size. The first pass generates
enough deflate blocks to produce output to fill the requested enough deflate blocks to produce output to fill the requested
output size plus a specfied excess amount (see the EXCESS define output size plus a specified excess amount (see the EXCESS define
below). The last deflate block may go quite a bit past that, but below). The last deflate block may go quite a bit past that, but
is discarded. The second pass decompresses and recompresses just is discarded. The second pass decompresses and recompresses just
the compressed data that fit in the requested plus excess sized the compressed data that fit in the requested plus excess sized
@@ -217,7 +217,7 @@ int main(int argc, char **argv)
if (ret == Z_MEM_ERROR) if (ret == Z_MEM_ERROR)
quit("out of memory"); quit("out of memory");
/* set up for next reocmpression */ /* set up for next recompression */
ret = inflateReset(&inf); ret = inflateReset(&inf);
assert(ret != Z_STREAM_ERROR); assert(ret != Z_STREAM_ERROR);
ret = deflateReset(&def); ret = deflateReset(&def);
+2 -2
View File
@@ -17,7 +17,7 @@
data in order to determine how much of that input will compress to data in order to determine how much of that input will compress to
nearly the requested output block size. The first pass generates nearly the requested output block size. The first pass generates
enough deflate blocks to produce output to fill the requested enough deflate blocks to produce output to fill the requested
output size plus a specfied excess amount (see the EXCESS define output size plus a specified excess amount (see the EXCESS define
below). The last deflate block may go quite a bit past that, but below). The last deflate block may go quite a bit past that, but
is discarded. The second pass decompresses and recompresses just is discarded. The second pass decompresses and recompresses just
the compressed data that fit in the requested plus excess sized the compressed data that fit in the requested plus excess sized
@@ -198,7 +198,7 @@ int main(int argc, char **argv)
if (ret == Z_MEM_ERROR) if (ret == Z_MEM_ERROR)
quit("out of memory"); quit("out of memory");
/* set up for next reocmpression */ /* set up for next recompression */
ret = inflateReset(&inf); ret = inflateReset(&inf);
assert(ret != Z_STREAM_ERROR); assert(ret != Z_STREAM_ERROR);
ret = deflateReset(&def); ret = deflateReset(&def);
+2 -1
View File
@@ -19,6 +19,7 @@
#include <ctype.h> /* toupper */ #include <ctype.h> /* toupper */
#include <errno.h> /* errno */ #include <errno.h> /* errno */
#include "timefn.h" /* UTIL_time_t, UTIL_getTime, UTIL_clockSpanMicro, UTIL_waitForNextTick */
#include "mem.h" #include "mem.h"
#define ZSTD_STATIC_LINKING_ONLY #define ZSTD_STATIC_LINKING_ONLY
#include "zstd.h" #include "zstd.h"
@@ -192,7 +193,7 @@ static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
remaining -= thisBlockSize; remaining -= thisBlockSize;
} } } } } }
/* warmimg up memory */ /* warming up memory */
RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1); RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1);
/* Bench */ /* Bench */
+2
View File
@@ -38,6 +38,8 @@
#ifdef _WIN32 #ifdef _WIN32
# include <stddef.h> # include <stddef.h>
#else
# include <unistd.h>
#endif #endif
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)