2 * Copyright (c) Meta Platforms, Inc. and affiliates.
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
12 /* The objective of this example is to show of to compress multiple successive files
13 * while preserving memory management.
14 * All structures and buffers will be created only once,
15 * and shared across all compression operations */
17 #include <stdio.h> // printf
18 #include <stdlib.h> // free
19 #include <string.h> // memset, strcat
20 #include <zstd.h> // presumes zstd library is installed
21 #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
31 static resources createResources_orDie(int cLevel)
34 ress.buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */
35 ress.buffOutSize= ZSTD_CStreamOutSize(); /* can always flush a full block */
36 ress.buffIn = malloc_orDie(ress.buffInSize);
37 ress.buffOut= malloc_orDie(ress.buffOutSize);
38 ress.cctx = ZSTD_createCCtx();
39 CHECK(ress.cctx != NULL, "ZSTD_createCCtx() failed!");
41 /* Set any compression parameters you want here.
42 * They will persist for every compression operation.
43 * Here we set the compression level, and enable the checksum.
45 CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) );
46 CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, 1) );
50 static void freeResources(resources ress)
52 ZSTD_freeCCtx(ress.cctx);
57 static void compressFile_orDie(resources ress, const char* fname, const char* outName)
59 // Open the input and output files.
60 FILE* const fin = fopen_orDie(fname, "rb");
61 FILE* const fout = fopen_orDie(outName, "wb");
63 /* Reset the context to a clean state to start a new compression operation.
64 * The parameters are sticky, so we keep the compression level and extra
65 * parameters that we set in createResources_orDie().
67 CHECK_ZSTD( ZSTD_CCtx_reset(ress.cctx, ZSTD_reset_session_only) );
69 size_t const toRead = ress.buffInSize;
71 while ( (read = fread_orDie(ress.buffIn, toRead, fin)) ) {
72 /* This loop is the same as streaming_compression.c.
73 * See that file for detailed comments.
75 int const lastChunk = (read < toRead);
76 ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;
78 ZSTD_inBuffer input = { ress.buffIn, read, 0 };
81 ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 };
82 size_t const remaining = ZSTD_compressStream2(ress.cctx, &output, &input, mode);
83 CHECK_ZSTD(remaining);
84 fwrite_orDie(ress.buffOut, output.pos, fout);
85 finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
87 CHECK(input.pos == input.size,
88 "Impossible: zstd only returns 0 when the input is completely consumed!");
95 int main(int argc, const char** argv)
97 const char* const exeName = argv[0];
100 printf("wrong arguments\n");
102 printf("%s FILE(s)\n", exeName);
106 int const cLevel = 7;
107 resources const ress = createResources_orDie(cLevel);
108 void* ofnBuffer = NULL;
112 for (argNb = 1; argNb < argc; argNb++) {
113 const char* const ifn = argv[argNb];
114 size_t const ifnSize = strlen(ifn);
115 size_t const ofnSize = ifnSize + 5;
116 if (ofnbSize <= ofnSize) {
117 ofnbSize = ofnSize + 16;
119 ofnBuffer = malloc_orDie(ofnbSize);
121 memset(ofnBuffer, 0, ofnSize);
122 strcat(ofnBuffer, ifn);
123 strcat(ofnBuffer, ".zst");
124 compressFile_orDie(ress, ifn, ofnBuffer);
130 printf("compressed %i files \n", argc-1);