| 17 | |
| 18 | |
| 19 | static void compressFile_orDie(const char* fname, const char* outName, int cLevel) |
| 20 | { |
| 21 | /* Open the input and output files. */ |
| 22 | FILE* const fin = fopen_orDie(fname, "rb"); |
| 23 | FILE* const fout = fopen_orDie(outName, "wb"); |
| 24 | /* Create the input and output buffers. |
| 25 | * They may be any size, but we recommend using these functions to size them. |
| 26 | * Performance will only suffer significantly for very tiny buffers. |
| 27 | */ |
| 28 | size_t const buffInSize = ZSTD_CStreamInSize(); |
| 29 | void* const buffIn = malloc_orDie(buffInSize); |
| 30 | size_t const buffOutSize = ZSTD_CStreamOutSize(); |
| 31 | void* const buffOut = malloc_orDie(buffOutSize); |
| 32 | |
| 33 | /* Create the context. */ |
| 34 | ZSTD_CCtx* const cctx = ZSTD_createCCtx(); |
| 35 | CHECK(cctx != NULL, "ZSTD_createCCtx() failed!"); |
| 36 | |
| 37 | /* Set any parameters you want. |
| 38 | * Here we set the compression level, and enable the checksum. |
| 39 | */ |
| 40 | CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel) ); |
| 41 | CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) ); |
| 42 | ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 4); |
| 43 | |
| 44 | /* This loop read from the input file, compresses that entire chunk, |
| 45 | * and writes all output produced to the output file. |
| 46 | */ |
| 47 | size_t const toRead = buffInSize; |
| 48 | for (;;) { |
| 49 | size_t read = fread_orDie(buffIn, toRead, fin); |
| 50 | /* Select the flush mode. |
| 51 | * If the read may not be finished (read == toRead) we use |
| 52 | * ZSTD_e_continue. If this is the last chunk, we use ZSTD_e_end. |
| 53 | * Zstd optimizes the case where the first flush mode is ZSTD_e_end, |
| 54 | * since it knows it is compressing the entire source in one pass. |
| 55 | */ |
| 56 | int const lastChunk = (read < toRead); |
| 57 | ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue; |
| 58 | /* Set the input buffer to what we just read. |
| 59 | * We compress until the input buffer is empty, each time flushing the |
| 60 | * output. |
| 61 | */ |
| 62 | ZSTD_inBuffer input = { buffIn, read, 0 }; |
| 63 | int finished; |
| 64 | do { |
| 65 | /* Compress into the output buffer and write all of the output to |
| 66 | * the file so we can reuse the buffer next iteration. |
| 67 | */ |
| 68 | ZSTD_outBuffer output = { buffOut, buffOutSize, 0 }; |
| 69 | size_t const remaining = ZSTD_compressStream2(cctx, &output , &input, mode); |
| 70 | CHECK_ZSTD(remaining); |
| 71 | fwrite_orDie(buffOut, output.pos, fout); |
| 72 | /* If we're on the last chunk we're finished when zstd returns 0, |
| 73 | * which means its consumed all the input AND finished the frame. |
| 74 | * Otherwise, we're finished when we've consumed all the input. |
| 75 | */ |
| 76 | finished = lastChunk ? (remaining == 0) : (input.pos == input.size); |
no test coverage detected