diff --git a/examples/multiple_streaming_compression.c b/examples/multiple_streaming_compression.c index 442ff40a..0054c7b0 100644 --- a/examples/multiple_streaming_compression.c +++ b/examples/multiple_streaming_compression.c @@ -18,7 +18,7 @@ #include // fprintf, perror, feof #include // strerror #include // errno -#define ZSTD_STATIC_LINKING_ONLY // streaming API defined as "experimental" for the time being +#define ZSTD_STATIC_LINKING_ONLY // TODO: Remove once the API is stable #include // presumes zstd library is installed #include "utils.h" @@ -27,53 +27,68 @@ typedef struct { void* buffOut; size_t buffInSize; size_t buffOutSize; - ZSTD_CStream* cstream; -} resources ; + ZSTD_CCtx* cctx; +} resources; -static resources createResources_orDie() +static resources createResources_orDie(int cLevel) { resources ress; ress.buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */ ress.buffOutSize= ZSTD_CStreamOutSize(); /* can always flush a full block */ ress.buffIn = malloc_orDie(ress.buffInSize); ress.buffOut= malloc_orDie(ress.buffOutSize); - ress.cstream = ZSTD_createCStream(); - if (ress.cstream==NULL) { fprintf(stderr, "ZSTD_createCStream() error \n"); exit(10); } + ress.cctx = ZSTD_createCCtx(); + 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; } static void freeResources(resources ress) { - ZSTD_freeCStream(ress.cstream); + ZSTD_freeCCtx(ress.cctx); free(ress.buffIn); 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 fout = fopen_orDie(outName, "wb"); - size_t const initResult = ZSTD_initCStream(ress.cstream, cLevel); - if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initCStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); } + /* Reset the context to a clean state to start a new compression operation. + * 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 }; - while (input.pos < input.size) { - ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 }; - toRead = ZSTD_compressStream(ress.cstream, &output , &input); /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */ - if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_compressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); } - 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); - } + int finished; + do { + ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 }; + size_t const remaining = ZSTD_compressStream2(ress.cctx, &output, &input, mode); + CHECK_ZSTD(remaining); + fwrite_orDie(ress.buffOut, output.pos, fout); + finished = lastChunk ? (remaining == 0) : (input.pos == input.size); + } while (!finished); + assert(input.pos == input.size); } - 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(fin); } @@ -89,7 +104,8 @@ int main(int argc, const char** argv) return 1; } - resources const ress = createResources_orDie(); + int const cLevel = 7; + resources const ress = createResources_orDie(cLevel); void* ofnBuffer = NULL; size_t ofnbSize = 0; @@ -106,7 +122,7 @@ int main(int argc, const char** argv) memset(ofnBuffer, 0, ofnSize); strcat(ofnBuffer, ifn); strcat(ofnBuffer, ".zst"); - compressFile_orDie(ress, ifn, ofnBuffer, 7); + compressFile_orDie(ress, ifn, ofnBuffer); } freeResources(ress);