Blender V4.5
zstd_compress.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include <cstdint>
6#include <cstdlib>
7#include <fstream>
8#include <thread>
9#include <vector>
10
11#include <zstd.h>
12
13int main(const int argc, const char **argv)
14{
15 if (argc < 3) {
16 return -1;
17 }
18
19 /* TODO: This might fail for non-ASCII paths on Windows... */
20 std::ifstream in(argv[1], std::ios_base::binary);
21 std::ofstream out(argv[2], std::ios_base::binary);
22 if (!in || !out) {
23 return -1;
24 }
25
26 in.seekg(0, std::ios_base::end);
27 size_t in_size = in.tellg();
28 in.seekg(0, std::ios_base::beg);
29 if (!in) {
30 return -1;
31 }
32
33 std::vector<char> in_data(in_size);
34 in.read(in_data.data(), in_size);
35 if (!in) {
36 return -1;
37 }
38
39 size_t out_size = ZSTD_compressBound(in_size);
40 if (ZSTD_isError(out_size)) {
41 return -1;
42 }
43 std::vector<char> out_data(out_size);
44
45 ZSTD_CCtx *cctx = ZSTD_createCCtx();
46 if (!cctx) {
47 return -1;
48 }
49 ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19);
50 /* Enable multi-threaded compression. Output is a standard zstd frame,
51 * fully compatible with regular single-threaded decompression.
52 * If libzstd lacks MT support the parameter is ignored (still works).
53 *
54 * Cap the worker count so that several parallel ninja jobs do not
55 * multiply into an out-of-memory situation on many-core build hosts.
56 * Override with the CYCLES_ZSTD_WORKERS environment variable. */
57 unsigned int workers = std::thread::hardware_concurrency();
58 if (workers == 0) {
59 workers = 4;
60 }
61 if (workers > 4) {
62 workers = 4;
63 }
64 if (const char *env = std::getenv("CYCLES_ZSTD_WORKERS")) {
65 const int env_workers = std::atoi(env);
66 if (env_workers >= 0) {
67 workers = static_cast<unsigned int>(env_workers);
68 }
69 }
70 ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, static_cast<int>(workers));
71 out_size = ZSTD_compress2(cctx, out_data.data(), out_data.size(), in_data.data(), in_data.size());
72 ZSTD_freeCCtx(cctx);
73 if (ZSTD_isError(out_size)) {
74 return -1;
75 }
76
77 out.write(out_data.data(), out_size);
78 if (!out) {
79 return -1;
80 }
81
82 return 0;
83}
#define in
#define out
#define main()