Skip to main content
Contexts are required for streaming compression and decompression operations. Reusing contexts across multiple operations is recommended for better memory efficiency.

Compression Context

ZSTD_createCCtx()

Allocates and initializes a compression context.
ZSTD_CCtx* ZSTD_createCCtx(void);

Returns

Pointer to the allocated ZSTD_CCtx structure, or NULL if allocation failed.

Usage

ZSTD_CCtx* cctx = ZSTD_createCCtx();
if (cctx == NULL) {
    fprintf(stderr, "Failed to create compression context\n");
    exit(1);
}

// Set compression parameters
ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 5);
ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1);

// Use for compression...
When compressing multiple files or streams, it is recommended to allocate the context once and reuse it for each successive compression operation. This improves memory efficiency and performance.
For multi-threaded environments, use one separate context per thread. Contexts are not thread-safe.

ZSTD_freeCCtx()

Frees memory allocated for a compression context.
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx);
cctx
ZSTD_CCtx*
Compression context to free. Passing NULL is safe and performs no operation.

Returns

Always returns 0 (provided for consistency with the API).

Usage

ZSTD_CCtx* cctx = ZSTD_createCCtx();
// ... use context ...
ZSTD_freeCCtx(cctx);
The function is compatible with NULL pointers, so you can safely call it even if context creation failed.

Decompression Context

ZSTD_createDCtx()

Allocates and initializes a decompression context.
ZSTD_DCtx* ZSTD_createDCtx(void);

Returns

Pointer to the allocated ZSTD_DCtx structure, or NULL if allocation failed.

Usage

ZSTD_DCtx* dctx = ZSTD_createDCtx();
if (dctx == NULL) {
    fprintf(stderr, "Failed to create decompression context\n");
    exit(1);
}

// Use for decompression...
When decompressing many files or streams, allocate the context once and reuse it for each successive decompression operation. This makes the workload friendlier for system memory.
Use one context per thread for parallel execution. Contexts are not thread-safe.

ZSTD_freeDCtx()

Frees memory allocated for a decompression context.
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
dctx
ZSTD_DCtx*
Decompression context to free. Passing NULL is safe and performs no operation.

Returns

Always returns 0 (provided for consistency with the API).

Usage

ZSTD_DCtx* dctx = ZSTD_createDCtx();
// ... use context ...
ZSTD_freeDCtx(dctx);

Complete Example

Here’s a complete example showing context creation, usage, and cleanup:
#include <stdio.h>
#include <stdlib.h>
#include <zstd.h>

void compress_file(const char* input_file, const char* output_file) {
    // Create compression context
    ZSTD_CCtx* cctx = ZSTD_createCCtx();
    if (cctx == NULL) {
        fprintf(stderr, "Failed to create compression context\n");
        return;
    }
    
    // Set compression level
    ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 3);
    ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1);
    
    // Allocate buffers
    size_t const buffInSize = ZSTD_CStreamInSize();
    void* buffIn = malloc(buffInSize);
    size_t const buffOutSize = ZSTD_CStreamOutSize();
    void* buffOut = malloc(buffOutSize);
    
    FILE* fin = fopen(input_file, "rb");
    FILE* fout = fopen(output_file, "wb");
    
    // Compression loop
    size_t const toRead = buffInSize;
    for (;;) {
        size_t read = fread(buffIn, 1, toRead, fin);
        int lastChunk = (read < toRead);
        ZSTD_EndDirective mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;
        
        ZSTD_inBuffer input = { buffIn, read, 0 };
        int finished;
        do {
            ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
            size_t remaining = ZSTD_compressStream2(cctx, &output, &input, mode);
            
            if (ZSTD_isError(remaining)) {
                fprintf(stderr, "Compression error: %s\n", 
                        ZSTD_getErrorName(remaining));
                goto cleanup;
            }
            
            fwrite(buffOut, 1, output.pos, fout);
            finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
        } while (!finished);
        
        if (lastChunk) break;
    }
    
cleanup:
    // Free resources
    ZSTD_freeCCtx(cctx);
    fclose(fin);
    fclose(fout);
    free(buffIn);
    free(buffOut);
}

void decompress_file(const char* input_file, const char* output_file) {
    // Create decompression context
    ZSTD_DCtx* dctx = ZSTD_createDCtx();
    if (dctx == NULL) {
        fprintf(stderr, "Failed to create decompression context\n");
        return;
    }
    
    // Allocate buffers
    size_t const buffInSize = ZSTD_DStreamInSize();
    void* buffIn = malloc(buffInSize);
    size_t const buffOutSize = ZSTD_DStreamOutSize();
    void* buffOut = malloc(buffOutSize);
    
    FILE* fin = fopen(input_file, "rb");
    FILE* fout = fopen(output_file, "wb");
    
    // Decompression loop
    size_t read;
    while ((read = fread(buffIn, 1, buffInSize, fin))) {
        ZSTD_inBuffer input = { buffIn, read, 0 };
        
        while (input.pos < input.size) {
            ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
            size_t ret = ZSTD_decompressStream(dctx, &output, &input);
            
            if (ZSTD_isError(ret)) {
                fprintf(stderr, "Decompression error: %s\n", 
                        ZSTD_getErrorName(ret));
                goto cleanup;
            }
            
            fwrite(buffOut, 1, output.pos, fout);
        }
    }
    
cleanup:
    // Free resources
    ZSTD_freeDCtx(dctx);
    fclose(fin);
    fclose(fout);
    free(buffIn);
    free(buffOut);
}
The examples above use ZSTD_CCtx and ZSTD_DCtx. Since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same type, as are ZSTD_DStream and ZSTD_DCtx. The distinct naming is maintained for compatibility with older code.

Build docs developers (and LLMs) love