$(LIB) :
$(MAKE) -C ../lib libzstd.a
-simple_compression : simple_compression.c utils.h $(LIB)
+simple_compression : simple_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
-simple_decompression : simple_decompression.c utils.h $(LIB)
+simple_decompression : simple_decompression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
-multiple_simple_compression : multiple_simple_compression.c utils.h $(LIB)
+multiple_simple_compression : multiple_simple_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
-dictionary_compression : dictionary_compression.c utils.h $(LIB)
+dictionary_compression : dictionary_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
-dictionary_decompression : dictionary_decompression.c utils.h $(LIB)
+dictionary_decompression : dictionary_decompression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
-streaming_compression : streaming_compression.c utils.h $(LIB)
+streaming_compression : streaming_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
-multiple_streaming_compression : multiple_streaming_compression.c utils.h $(LIB)
+multiple_streaming_compression : multiple_streaming_compression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
-streaming_decompression : streaming_decompression.c utils.h $(LIB)
+streaming_decompression : streaming_decompression.c common.h $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@
streaming_memory_usage : streaming_memory_usage.c $(LIB)
/*
* This header file has common utility functions used in examples.
*/
-#ifndef UTILS_H
-#define UTILS_H
+#ifndef COMMON_H
+#define COMMON_H
#include <stdlib.h> // malloc, free, exit
#include <stdio.h> // fprintf, perror, fopen, etc.
-#include <string.h> // strlen, strcat, memset, strerror
+#include <string.h> // strerror
#include <errno.h> // errno
-#include <assert.h> // assert
#include <sys/stat.h> // stat
#include <zstd.h>
ERROR_saveFile = 7,
ERROR_malloc = 8,
ERROR_largeFile = 9,
-} UTILS_ErrorCode;
+} COMMON_ErrorCode;
+
+/*! CHECK
+ * Check that the condition holds. If it doesn't print a message and die.
+ */
+#define CHECK(cond, ...) \
+ do { \
+ if (!(cond)) { \
+ fprintf(stderr, \
+ "%s:%d CHECK(%s) failed: ", \
+ __FILE__, \
+ __LINE__, \
+ #cond); \
+ fprintf(stderr, "" __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ exit(1); \
+ } \
+ } while (0)
+
+/*! CHECK_ZSTD
+ * Check the zstd error code and die if an error occurred after printing a
+ * message.
+ */
+#define CHECK_ZSTD(fn, ...) \
+ do { \
+ size_t const err = (fn); \
+ CHECK(!ZSTD_isError(err), "%s", ZSTD_getErrorName(err)); \
+ } while (0)
/*! fsize_orDie() :
* Get the size of a given file path.
static size_t loadFile_orDie(const char* fileName, void* buffer, size_t bufferSize)
{
size_t const fileSize = fsize_orDie(fileName);
- assert(fileSize <= bufferSize);
+ CHECK(fileSize <= bufferSize, "File too large!");
FILE* const inFile = fopen_orDie(fileName, "rb");
size_t const readSize = fread(buffer, 1, fileSize, inFile);
}
}
-/*! CHECK
- * Check that the condition holds. If it doesn't print a message and die.
- */
-#define CHECK(cond, ...) \
- do { \
- if (!(cond)) { \
- fprintf(stderr, \
- "%s:%d CHECK(%s) failed: ", \
- __FILE__, \
- __LINE__, \
- #cond); \
- fprintf(stderr, "" __VA_ARGS__); \
- fprintf(stderr, "\n"); \
- exit(1); \
- } \
- } while (0)
-
-/*! CHECK_ZSTD
- * Check the zstd error code and die if an error occurred after printing a
- * message.
- */
-#define CHECK_ZSTD(fn, ...) \
- do { \
- size_t const err = (fn); \
- CHECK(!ZSTD_isError(err), "%s", ZSTD_getErrorName(err)); \
- } while (0)
-
#endif
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
-#include <stdlib.h> // malloc, exit
#include <stdio.h> // printf
-#include <string.h> // strerror
-#include <errno.h> // errno
-#include <sys/stat.h> // stat
+#include <stdlib.h> // free
+#include <string.h> // memset, strcat
#include <zstd.h> // presumes zstd library is installed
-#include "utils.h"
+#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
/* createDict() :
`dictFileName` is supposed to have been created using `zstd --train` */
printf("loading dictionary %s \n", dictFileName);
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel);
- if (!cdict) {
- fprintf(stderr, "ZSTD_createCDict error \n");
- exit(7);
- }
+ CHECK(cdict != NULL, "ZSTD_createCDict() failed!");
free(dictBuffer);
return cdict;
}
size_t const cBuffSize = ZSTD_compressBound(fSize);
void* const cBuff = malloc_orDie(cBuffSize);
+ /* Compress using the dictionary.
+ * This function writes the dictionary id, and content size into the header.
+ * But, it doesn't use a checksum. You can control these options using the
+ * advanced API: ZSTD_CCtx_setParameter(), ZSTD_CCtx_refCDict(),
+ * and ZSTD_compress2().
+ */
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
- if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); }
+ CHECK(cctx != NULL, "ZSTD_createCCtx() failed!");
size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict);
- if (ZSTD_isError(cSize)) {
- fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
- exit(7);
- }
+ CHECK_ZSTD(cSize);
saveFile_orDie(oname, cBuff, cSize);
*/
-
-#include <stdlib.h> // malloc, exit
#include <stdio.h> // printf
-#include <string.h> // strerror
-#include <errno.h> // errno
-#include <sys/stat.h> // stat
-#define ZSTD_STATIC_LINKING_ONLY // ZSTD_findDecompressedSize
+#include <stdlib.h> // free
#include <zstd.h> // presumes zstd library is installed
-#include "utils.h"
+#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
/* createDict() :
`dictFileName` is supposed to have been created using `zstd --train` */
printf("loading dictionary %s \n", dictFileName);
void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);
ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize);
- if (ddict==NULL) { fprintf(stderr, "ZSTD_createDDict error \n"); exit(5); }
+ CHECK(ddict != NULL, "ZSTD_createDDict() failed!");
free(dictBuffer);
return ddict;
}
{
size_t cSize;
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
- unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize);
- if (rSize==ZSTD_CONTENTSIZE_ERROR) {
- fprintf(stderr, "%s : it was not compressed by zstd.\n", fname);
- exit(5);
- } else if (rSize==ZSTD_CONTENTSIZE_UNKNOWN) {
- fprintf(stderr, "%s : original size unknown \n", fname);
- exit(6);
- }
-
+ /* Read the content size from the frame header. For simplicity we require
+ * that it is always present. By default, zstd will write the content size
+ * in the header when it is known. If you can't guarantee that the frame
+ * content size is always written into the header, either use streaming
+ * decompression, or ZSTD_decompressBound().
+ */
+ unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
+ CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, "%s: not compressed by zstd!", fname);
+ CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, "%s: original size unknown!", fname);
void* const rBuff = malloc_orDie((size_t)rSize);
+ /* Check that the dictionary ID matches.
+ * If a non-zstd dictionary is used, then both will be zero.
+ * By default zstd always writes the dictionary ID into the frame.
+ * Zstd will check if there is a dictionary ID mismatch as well.
+ */
+ unsigned const expectedDictID = ZSTD_getDictID_fromDDict(ddict);
+ unsigned const actualDictID = ZSTD_getDictID_fromFrame(cBuff, cSize);
+ CHECK(actualDictID == expectedDictID,
+ "DictID mismatch: expected %u got %u",
+ expectedDictID,
+ actualDictID);
+
+ /* Decompress using the dictionary.
+ * If you need to control the decompression parameters, then use the
+ * advanced API: ZSTD_DCtx_setParameter(), ZSTD_DCtx_refDDict(), and
+ * ZSTD_decompressDCtx().
+ */
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
- if (dctx==NULL) { fprintf(stderr, "ZSTD_createDCtx() error \n"); exit(10); }
+ CHECK(dctx != NULL, "ZSTD_createDCtx() failed!");
size_t const dSize = ZSTD_decompress_usingDDict(dctx, rBuff, rSize, cBuff, cSize, ddict);
- if (dSize != rSize) {
- fprintf(stderr, "error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize));
- exit(7);
- }
+ CHECK_ZSTD(dSize);
+ /* When zstd knows the content size, it will error if it doesn't match. */
+ CHECK(dSize == rSize, "Impossible because zstd will check this condition!");
/* success */
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
* You may select, at your option, one of the above-listed licenses.
*/
-#include <stdlib.h> // malloc, free, exit
-#include <stdio.h> // fprintf, perror, fopen, etc.
-#include <string.h> // strlen, strcat, memset, strerror
-#include <errno.h> // errno
-#include <sys/stat.h> // stat
+#include <stdio.h> // printf
+#include <stdlib.h> // free
+#include <string.h> // memcpy, strlen
#include <zstd.h> // presumes zstd library is installed
-#include "utils.h"
+#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
typedef struct {
void* fBuffer;
ress.fBuffer = malloc_orDie(ress.fBufferSize);
ress.cBuffer = malloc_orDie(ress.cBufferSize);
ress.cctx = ZSTD_createCCtx();
- if (ress.cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); }
+ CHECK(ress.cctx != NULL, "ZSTD_createCCtx() failed!");
return ress;
}
{
size_t fSize = loadFile_orDie(fname, ress.fBuffer, ress.fBufferSize);
+ /* Compress using the context.
+ * If you need more control over parameters, use the advanced API:
+ * ZSTD_CCtx_setParameter(), and ZSTD_compress2().
+ */
size_t const cSize = ZSTD_compressCCtx(ress.cctx, ress.cBuffer, ress.cBufferSize, ress.fBuffer, fSize, 1);
- if (ZSTD_isError(cSize)) {
- fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
- exit(8);
- }
+ CHECK_ZSTD(cSize);
saveFile_orDie(oname, ress.cBuffer, cSize);
/* success */
- // printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname);
+ printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname);
}
int main(int argc, const char** argv)
for (argNb = 1; argNb < argc; argNb++) {
const char* const inFilename = argv[argNb];
size_t const inFilenameLen = strlen(inFilename);
- assert(inFilenameLen + 5 <= outFilenameBufferLen);
+ CHECK(inFilenameLen + 5 <= outFilenameBufferLen, "File name too long!");
memcpy(outFilename, inFilename, inFilenameLen);
memcpy(outFilename+inFilenameLen, ".zst", 5);
compressFile_orDie(ress, inFilename, outFilename);
* All structures and buffers will be created only once,
* and shared across all compression operations */
-#include <stdlib.h> // malloc, exit
-#include <stdio.h> // fprintf, perror, feof
-#include <string.h> // strerror
-#include <errno.h> // errno
-#define ZSTD_STATIC_LINKING_ONLY // TODO: Remove once the API is stable
+#include <stdio.h> // printf
+#include <stdlib.h> // free
+#include <string.h> // memset, strcat
#include <zstd.h> // presumes zstd library is installed
-#include "utils.h"
+#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
typedef struct {
void* buffIn;
fwrite_orDie(ress.buffOut, output.pos, fout);
finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
} while (!finished);
- assert(input.pos == input.size);
+ CHECK(input.pos == input.size,
+ "Impossible: zstd only returns 0 when the input is completely consumed!");
}
fclose_orDie(fout);
* You may select, at your option, one of the above-listed licenses.
*/
-#include <stdlib.h> // malloc, free, exit
-#include <stdio.h> // fprintf, perror, fopen, etc.
-#include <string.h> // strlen, strcat, memset, strerror
-#include <errno.h> // errno
-#include <sys/stat.h> // stat
+#include <stdio.h> // printf
+#include <stdlib.h> // free
+#include <string.h> // strlen, strcat, memset
#include <zstd.h> // presumes zstd library is installed
-#include "utils.h"
+#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
static void compress_orDie(const char* fname, const char* oname)
{
size_t const cBuffSize = ZSTD_compressBound(fSize);
void* const cBuff = malloc_orDie(cBuffSize);
+ /* Compress.
+ * If you are doing many compressions, you may want to reuse the context.
+ * See the multiple_simple_compression.c example.
+ */
size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1);
- if (ZSTD_isError(cSize)) {
- fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
- exit(8);
- }
+ CHECK_ZSTD(cSize);
saveFile_orDie(oname, cBuff, cSize);
* You may select, at your option, one of the above-listed licenses.
*/
-#include <stdlib.h> // malloc, exit
#include <stdio.h> // printf
-#include <string.h> // strerror
-#include <errno.h> // errno
-#include <sys/stat.h> // stat
-#define ZSTD_STATIC_LINKING_ONLY // ZSTD_findDecompressedSize
+#include <stdlib.h> // free
#include <zstd.h> // presumes zstd library is installed
-#include "utils.h"
+#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
static void decompress(const char* fname)
{
size_t cSize;
void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);
- unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize);
- if (rSize==ZSTD_CONTENTSIZE_ERROR) {
- fprintf(stderr, "%s : it was not compressed by zstd.\n", fname);
- exit(5);
- } else if (rSize==ZSTD_CONTENTSIZE_UNKNOWN) {
- fprintf(stderr,
- "%s : original size unknown. Use streaming decompression instead.\n", fname);
- exit(6);
- }
+ /* Read the content size from the frame header. For simplicity we require
+ * that it is always present. By default, zstd will write the content size
+ * in the header when it is known. If you can't guarantee that the frame
+ * content size is always written into the header, either use streaming
+ * decompression, or ZSTD_decompressBound().
+ */
+ unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
+ CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, "%s: not compressed by zstd!", fname);
+ CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, "%s: original size unknown!", fname);
void* const rBuff = malloc_orDie((size_t)rSize);
+ /* Decompress.
+ * If you are doing many decompressions, you may want to reuse the context
+ * and use ZSTD_decompressDCtx(). If you want to set advanced parameters,
+ * use ZSTD_DCtx_setParameter().
+ */
size_t const dSize = ZSTD_decompress(rBuff, rSize, cBuff, cSize);
-
- if (dSize != rSize) {
- fprintf(stderr, "error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize));
- exit(7);
- }
+ CHECK_ZSTD(dSize);
+ /* When zstd knows the content size, it will error if it doesn't match. */
+ CHECK(dSize == rSize, "Impossible because zstd will check this condition!");
/* success */
printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
*/
-#include <stdlib.h> // malloc, free, exit
-#include <stdio.h> // fprintf, perror, feof, fopen, etc.
-#include <string.h> // strlen, memset, strcat
-#define ZSTD_STATIC_LINKING_ONLY // TODO: Remove once the API is stable
+#include <stdio.h> // printf
+#include <stdlib.h> // free
+#include <string.h> // memset, strcat, strlen
#include <zstd.h> // presumes zstd library is installed
-#include "utils.h"
+#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
static void compressFile_orDie(const char* fname, const char* outName, int cLevel)
*/
finished = lastChunk ? (remaining == 0) : (input.pos == input.size);
} while (!finished);
- assert(input.pos == input.size);
+ CHECK(input.pos == input.size,
+ "Impossible: zstd only returns 0 when the input is completely consumed!");
}
ZSTD_freeCCtx(cctx);
*/
-#include <stdlib.h> // malloc, exit
-#include <stdio.h> // fprintf, perror, feof
-#include <string.h> // strerror
-#include <errno.h> // errno
+#include <stdio.h> // fprintf
+#include <stdlib.h> // free
#include <zstd.h> // presumes zstd library is installed
-#include "utils.h"
+#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
static void decompressFile_orDie(const char* fname)
{
/*=== Dependencies ===*/
-#include <stdio.h> /* printf */
+#include <stdio.h> // printf
#define ZSTD_STATIC_LINKING_ONLY
-#include "zstd.h"
-#include "utils.h"
+#include <zstd.h> // presumes zstd library is installed
+#include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD()
/*=== functions ===*/